Desktop Dungeons Shops
Calculate probabilities for item spawns in desktop dungeons shops.
HTML
<label for="shops">Shops:</label>
<input id="shops" type="text" value="8">
<label for="shops">Exponent:</label>
<input id="exponent" type="text" value="2">
<br>
<label for="order">Order:</label>
<select id="order" value="bqe">
<option value="bqe">Basic Quest Elite</option>
<option value="qbe">Quest Basic Elite</option>
<option value="ebq">Elite Basic Quest</option>
<option value="qeb">Quest Elite Basic</option>
<option value="eqb">Elite Quest Basic</option>
</select>
<br>
Vanilla:
Basic<input id="vanillaBasic" type="checkbox" checked="1"/>
Quest<input id="vanillaQuest" type="checkbox" checked="1"/>
Elite<input id="vanillaElite" type="checkbox" checked="1"/>
<br>
EE:
Basic<input id="eeBasic" type="checkbox" checked="0"/>
Quest<input id="eeQuest" type="checkbox" checked="0"/>
Elite<input id="eeElite" type="checkbox" checked="0"/>
<br>
AQE:
Basic<input id="aqeBasic" type="checkbox" checked="0"/>
Quest<input id="aqeQuest" type="checkbox" checked="0"/>
Elite<input id="aqeElite" type="checkbox" checked="0"/>
<br>
<button id="update">Update</button>
<div id="odds-of-basic">Odds your first shop is a Basic:</div>
<div id="odds-of-quest">Odds your first shop is a Quest:</div>
<div id="odds-of-elite">Odds your first shop is an Elite:</div>
<table id="itemlist"></table>
JavaScript
function probabilityShopIsItem(index, numItemsInPool) {
const flippedIndex = numItemsInPool - index - 1;
const itemChosenRange = Math.pow(flippedIndex + 1, power) - Math.pow(flippedIndex, power);
const totalRange = Math.pow(numItemsInPool, power);
const probabilityChosen = itemChosenRange / totalRange;
//console.log(index, flippedIndex, numItemsInPool, probabilityChosen);
return probabilityChosen;
}
function probabilityShopIsNotItem(index, numItemsInPool) {
return 1 - probabilityShopIsItem(index, numItemsInPool);
}
function probabilityOneOfShopsIsItem(startIndex, endIndex, numItemsInPool) {
let totalProbabilityChosen = 0;
for (let i = startIndex; i < endIndex; i++) {
totalProbabilityChosen += probabilityShopIsItem(i, numItemsInPool);
}
return totalProbabilityChosen;
}
function p_multi(i, n, s) {
let totalProbabilityChosen = probabilityShopIsItem(i, n);
if (s > 1) {
if (i > 0) {
const probabilityItemBeforeThisWasChosen = probabilityOneOfShopsIsItem(0, i, n);
totalProbabilityChosen += probabilityItemBeforeThisWasChosen * p_multi(i - 1, n - 1, s - 1);
}
if (i < n - 1) {
const probabilityItemBeforeThisWasChosen = probabilityOneOfShopsIsItem(i + 1, n, n);
totalProbabilityChosen += probabilityItemBeforeThisWasChosen * p_multi(i, n - 1, s - 1)
}
}
return totalProbabilityChosen;
}
function refreshDisplayedItems() {
items = [];
itemlist = [];
let numBasics = 0;
let numQuests = 0;
let numElites = 0;
if (document.getElementById('vanillaBasic').checked) {
numBasics += vanillaBasics.length;
items = items.concat(vanillaBasics);
}
if (document.getElementById('eeBasic').checked) {
numBasics += eeBasics.length;
items = items.concat(eeBasics);
}
if (document.getElementById('aqeBasic').checked) {
numBasics += aqeBasics.length;
items = items.concat(aqeBasics);
}
if (document.getElementById('vanillaQuest').checked) {
numQuests += vanillaQuests.length;
items =...