Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
function fowAchTableSort() {
var results = document.evaluate("id('Ach_OrderHeader')/a", document, null, XPathResult.ANY_TYPE, null);
var aResult;
if (aResult = results.iterateNext()) {
aResult.onclick();
return aResult;
}
return null;
}
function fowAchTableSortSetup() {
var aResult = fowAchTableSort();
if (aResult) {
var tbl = aResult;
while (tbl.nodeName.toLowerCase() != "table") {
tbl = tbl.parentNode;
if (tbl == null) return;
}
var p = document.createElement('p');
p.appendChild(document.createTextNode('['));
var btn = document.createElement('a');
btn.setAttribute("onclick", "fowAchTableSort();return false;");
btn.setAttribute("href", "#");
btn.appendChild(document.createTextNode("Default order"));
p.appendChild(btn);
p.appendChild(document.createTextNode(']'));
tbl.parentNode.insertBefore(p, tbl);
}
}
addOnloadHook(fowAchTableSortSetup);
function dacalc_roll(stat1, stat2) {
var n = parseInt(stat1);
if (n < 0) n = 0;
var d = n + parseInt(stat2);
if (d <= n) return 1;
return n / d;
}
function attackSuccess(a, d, s, h, H) {
if (H == -1) return 1;
if (h == -1) return 0;
var r1 = a * attackSuccess(a, d, false, h, H-1);
var r2 = (1-d) * attackSuccess(a, d, true, h-1, H);
if (s) return (r1 + (1-a) * r2) / (1 - (1-a) * d);
return (d * r1 + r2) / (1 - (1-a) * d);
}
function dacalc_simple(statname1, stat1, statname2, stat2) {return statname1 + " " + stat1 + " vs " + statname2 + " " + stat2 + ": success probability " + dacalc_roll(stat1, stat2);}
function dacalc() {
// Attack, defence, dodge, sneak, special
var raiderStats = document.getElementById("dacalcRaider").value.split(":");
// Attack, defence, snare, detect, type, special
var roomStats = document.getElementById("dacalcRoom").value.split(":");
if (roomStats[4] == "M") {
var res = new Array();
var s = dacalc_roll(raiderStats[3], roomStats[3]);
if (raiderStats[4] == "B") { // Berserker
res.push("Berserker has First Strike");
s = 1;
}
else res.push(dacalc_simple("Sneak", raiderStats[3], "detect", roomStats[3]));
for (charge = 0; charge < 2; charge++) {
res.push("<br /><br />");
if (charge == 0) res.push("Advance:");
else res.push("Charge:");
var a = dacalc_roll(raiderStats[0] + charge, roomStats[1]);
// There's a subtlety here: is the probability of the raider successfully defending against
// an attack equal to dacalc_roll(raiderStats[1], roomStats[0]) or
// 1 - dacalc_roll(roomStats[0], raiderStats[1])? This matters for 0 vs 0 and for asymmetric
// formulae.
var d = dacalc_roll(raiderStats[1], roomStats[0]);
if (d == 1 && a == 0) return "Both raider and room have attack 0. Raider always wins."; // Based on Talk:Dungeon Assault
// Handle multiple attacks / defences.
var h = 0;
var H = 0;
if (roomStats[5] == "SG") H = 1;
if (raiderStats[4] == "KN") h = 1;
var p1 = attackSuccess(a, d, true, h, H);
var p2 = attackSuccess(a, d, false, h, H);
// The Ranger of the North's special ability is a bit complicated. We assume h == 0.
if (raiderStats[4] == "RN") {
var special_a = dacalc_roll(2 * (raiderStats[0] + charge), roomStats[1]);
p1 = special_a * attackSuccess(a, d, false, h, H-1) + (1 - special_a) * p2;
p2 = d * p1;
}
if (s != 0) {
if (roomStats[5] == "CS") {
if (s == 1) res.push("<br/>Raider");
else res.push("<br/>If sneak successful, raider");
res.push(" sneaks past Corrosive Slime without the need for combat.");
p1 = 1;
}
else {
if (s == 1) res.push("<br/>Raider attacks first with success probability ");
else res.push("<br/>If sneak successful, raider attacks first with success probability ");
res.push(p1);
}
}
if (s != 1) {
if (s == 0) res.push("<br/>Raider defends first with success probability ");
else res.push("<br/>Otherwise raider defends first with success probability ");
res.push(p2);
}
res.push("<br/>Overall success probability: ");
res.push(s * p1 + (1 - s) * p2);
}
return res.join("");
}
else if (roomStats[4] == "T") {
// Special case(s)
if (raiderStats[4] == "SS" && roomStats[5] == "Pit") return "Pit Immunity: success is certain";
var s = dacalc_roll(raiderStats[3], roomStats[3]);
var res = new Array();
res.push(dacalc_simple("Sneak", raiderStats[3], "detect", roomStats[3]));
res.push("<br/>If that fails, ");
res.push(dacalc_simple("dodge", raiderStats[2], "snare" , roomStats[2]));
res.push("<br/>Combined success probability: ");
res.push(s + dacalc_roll(raiderStats[2], roomStats[2]) * (1 - s));
return res.join("");
}
else if (roomStats[4] == "G") {
// Depends on which stat the room has
if (roomStats[3] != 0) return dacalc_simple("Sneak", raiderStats[3], "detect", roomStats[3]);
else return dacalc_simple("Dodge", raiderStats[2], "snare" , roomStats[2]);
}
}
function setupDACalc() {
var thediv = document.getElementById('dacalc');
if (thediv) {
var dacalcHTML = new Array();
// Version allows to check that the script has been refreshed.
dacalcHTML.push('Dungeon Assault probability calculator, version 0.2.7T<br/>');
dacalcHTML.push('<select id="dacalcRaider">');
dacalcHTML.push(' <option value="1:1:1:1:">Goblin Runt</option>');
dacalcHTML.push(' <option value="2:1:2:1:">Goblin Cleaver</option>');
dacalcHTML.push(' <option value="2:2:1:1:">Orc Warrior</option>');
dacalcHTML.push(' <option value="1:1:3:2:">Saurus Spawn</option>');
dacalcHTML.push(' <option value="3:4:1:0:">Ogre Thug</option>');
dacalcHTML.push(' <option value="1:3:3:1:SS">Saurus Slink</option>');
dacalcHTML.push(' <option value="4:1:1:3:">Beastman</option>');
dacalcHTML.push(' <option value="2:3:2:3:">Witch</option>');
dacalcHTML.push(' <option value="1:3:2:4:">Dryad</option>');
dacalcHTML.push(' <option value="4:4:2:0:">Cave Troll</option>');
dacalcHTML.push(' <option value="1:4:5:2:">Goblin Scout</option>');
dacalcHTML.push(' <option value="3:3:4:4:">Saurus Warrior</option>');
dacalcHTML.push(' <option value="5:3:4:1:">Orc Shaman</option>');
dacalcHTML.push(' <option value="6:5:1:1:">Mercenary Knight</option>');
dacalcHTML.push(' <option value="7:1:1:5:">Orc Blademaster</option>');
dacalcHTML.push(' <option value="3:3:6:5:">Thief</option>');
dacalcHTML.push(' <option value="6:7:1:0:">Ogre Brute</option>');
dacalcHTML.push(' <option value="5:5:3:3:">Priest</option>');
dacalcHTML.push(' <option value="3:4:2:2:">Dwarf Renegade</option>');
dacalcHTML.push(' <option value="5:7:5:0:">Minotaur</option>');
dacalcHTML.push(' <option value="2:3:8:8:">Spy</option>');
dacalcHTML.push(' <option value="1:6:4:6:">Enchantress</option>');
dacalcHTML.push(' <option value="8:2:7:0:">Zealot</option>');
dacalcHTML.push(' <option value="4:7:7:5:RN">Ranger of the North</option>');
dacalcHTML.push(' <option value="10:0:0:0:B">Berserker</option>');
dacalcHTML.push(' <option value="8:9:4:1:KN">Black Knight</option>');
dacalcHTML.push(' <option value="8:5:5:9:">Dark Elf Assassin</option>');
dacalcHTML.push(' <option value="7:6:2:2:">Sorceress</option>');
dacalcHTML.push(' <option value="6:6:9:9:">Daemonette</option>');
dacalcHTML.push(' <option value="10:10:10:10:">Chaos Champion</option>');
dacalcHTML.push('</select>');
dacalcHTML.push('<select id="dacalcRoom">');
dacalcHTML.push(' <optgroup label="Monsters">');
dacalcHTML.push(' <option value="1:1:1:1:M:">Giant Rats</option>');
dacalcHTML.push(' <option value="1:1:0:2:M:">Rot Worms</option>');
dacalcHTML.push(' <option value="2:2:1:1:M:">Troglodytes</option>');
dacalcHTML.push(' <option value="2:1:1:3:M:">Imp</option>');
dacalcHTML.push(' <option value="2:3:1:1:M:">Giant Snake</option>');
dacalcHTML.push(' <option value="2:3:1:3:M:">Vampire Bats</option>');
dacalcHTML.push(' <option value="2:3:4:1:M:">Giant Spider</option>');
dacalcHTML.push(' <option value="2:4:0:3:M:">Skeleton Sentinels</option>');
dacalcHTML.push(' <option value="2:2:2:5:M:">Spectre</option>');
dacalcHTML.push(' <option value="5:4:6:2:M:">Banshee</option>');
dacalcHTML.push(' <option value="6:6:0:2:M:">Pit Demon</option>');
dacalcHTML.push(' <option value="6:8:0:5:M:CS">Corrosive Slime</option>');
dacalcHTML.push(' <option value="4:8:0:7:M:SG">Stone Golem</option>');
dacalcHTML.push(' <option value="7:7:1:1:M:">Razor Construct</option>');
dacalcHTML.push(' <option value="5:4:4:7:M:">Vampire Lord</option>');
dacalcHTML.push(' <option value="9:5:5:8:M:">Hell Beast</option>');
dacalcHTML.push(' <option value="10:6:5:1:M:">Demon Lord</option>');
dacalcHTML.push(' </optgroup>');
dacalcHTML.push(' <optgroup label="Traps">');
dacalcHTML.push(' <option value="0:0:1:1:T:">Snakes</option>');
dacalcHTML.push(' <option value="0:0:1:4:T:Pit">Pit</option>');
dacalcHTML.push(' <option value="0:0:2:2:T:">Nails</option>');
dacalcHTML.push(' <option value="0:0:3:6:T:Pit">Hidden Pit</option>');
dacalcHTML.push(' <option value="0:0:4:3:T:">Teleport</option>');
dacalcHTML.push(' <option value="0:0:3:4:T:">Hidden Nails</option>');
dacalcHTML.push(' <option value="0:0:7:3:T:">Crusher</option>');
dacalcHTML.push(' <option value="6:0:4:6:T:">Hidden Darts</option>');
dacalcHTML.push(' <option value="0:0:7:7:T:">Whirling Blades</option>');
dacalcHTML.push(' <option value="0:0:4:8:T:Pit">Bottomless Pit</option>');
dacalcHTML.push(' <option value="0:0:8:6:T:">Poisonous Gas</option>');
dacalcHTML.push(' </optgroup>');
dacalcHTML.push(' <optgroup label="Guardians">');
dacalcHTML.push(' <option value="0:0:0:2:G:">Tripwire Bell</option>');
dacalcHTML.push(' <option value="0:0:6:0:G:">Hall of Glass</option>');
dacalcHTML.push(' </optgroup>');
dacalcHTML.push('</select>');
dacalcHTML.push('<br />Kills (Vampire Lord only):<br />');
dacalcHTML.push('<input type="text" value="0" id="VL_Kills"/>');
dacalcHTML.push('<br />Attack Decrease:');
dacalcHTML.push('<input type="text" value="0" id="AttackDown"/>');
dacalcHTML.push('<br />Defence Decrease:');
dacalcHTML.push('<input type="text" value="0" id="DefenceDown"/>');
dacalcHTML.push('<input type="button" onClick="document.getElementById(');
dacalcHTML.push("'dacalcResult'");
dacalcHTML.push(').innerHTML = dacalc();" value="Calculate"/>');
dacalcHTML.push('<div id="dacalcResult">Click the button to update the result.</div>');
thediv.innerHTML = dacalcHTML.join('');
}
}
addOnloadHook(setupDACalc);
username = "Zehnstein";