Skip to content

Instantly share code, notes, and snippets.

@perillamint
Last active August 2, 2022 06:15
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 perillamint/61b8ed949c4054afeb06fc541a74d3cc to your computer and use it in GitHub Desktop.
Save perillamint/61b8ed949c4054afeb06fc541a74d3cc to your computer and use it in GitHub Desktop.
Gacha of Monte Carlo (Genshin Impact ver.)
/*
* MIT No Attribution
*
* Copyright 2022 perillamint
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// This code simulates and calculate Genshin Impact Gacha probability.
// I'm too lazy to analyze Discrete Cumulative Distribution Function by myself
// So this code just simulates and analyze it using Monte Carlo method.
function prob_distribution_func(n) {
if (n < 75 && n >= 1) return 0.006;
if (n <= 89) return 0.33;
if (n == 90) return 1;
throw new Error("Undefined!")
}
function do_gacha(n, m) {
if (Math.random() <= prob_distribution_func(n, m)) {
// Simulate prize
if (m == 1) {
return {
ur: true,
pickup: true,
};
} else {
return {
ur: true,
pickup: Math.random() <= 0.5,
};
}
}
return {
ur: false,
pickup: false,
}
}
function montecarlo_cnt() {
let n = 1; m = 0;
let cnt = 1;
for(;;) {
let res = do_gacha(n, m);
if (res.pickup) {
return cnt;
} else if (res.ur) {
m += 1;
n = 0;
}
cnt += 1;
n += 1;
}
}
const iter = 1000000;
const gachaMap = [];
for (let i = 0; i <= 90*2; i++) {
gachaMap[i] = 0;
}
let sum = 0;
for (let i = 0; i < iter; i++) {
let cnt = montecarlo_cnt();
sum += cnt;
gachaMap[cnt] += 1;
}
console.log(`Avg try: ${sum / iter}`);
console.log("Gacha histogram");
for (let i = 0; i <= 90*2; i++) {
let msg = `${i}: `.padStart(6);
for (let j = 0; j <= Math.ceil(gachaMap[i] / 200); j++) {
msg += "*";
}
console.log(msg);
}
for (let i = 0; i <= 90*2; i++) {
let msg = `${i}: `.padStart(6);
msg += `${gachaMap[i] / iter * 100}%`;
console.log(msg);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment