Nonograms Katana Wiki

Are you new to wikis?
Do you have trouble navigating the wiki?
Check this page.

READ MORE

Nonograms Katana Wiki
mNo edit summary
m (fix (should be the last))
 
(117 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
/* Any JavaScript here will be loaded for all users on every page load. */
 
/* Any JavaScript here will be loaded for all users on every page load. */
   
  +
//Changes every output cell in the table to "0" or "".
  +
function delete_table(){
  +
document.getElementById("xp").innerHTML = "0";
  +
document.getElementById("coin").innerHTML = "0";
  +
document.getElementById("ruby").innerHTML = "0";
  +
document.getElementById("item1").innerHTML = "0";
  +
document.getElementById("item2").innerHTML = "0";
  +
document.getElementById("bt_ram").innerHTML = "0";
  +
document.getElementById("tr_map").innerHTML = "0";
  +
document.getElementById("unlocks1").innerHTML = "";
  +
document.getElementById("unlocks2").innerHTML = "";
  +
document.getElementById("unlocks3").innerHTML = "";
  +
document.getElementById("unlocks4").innerHTML = "";
  +
document.getElementById("unlocks5").innerHTML = "";
  +
document.getElementById("add_reward1").innerHTML = "";
  +
document.getElementById("add_reward2").innerHTML = "";
  +
document.getElementById("add_reward3").innerHTML = "";
  +
}
 
//Calculates rewards for levels on page "Levelling".
 
//Calculates rewards for levels on page "Levelling".
 
function calculate() {
 
function calculate() {
 
var level = document.getElementById("level").value;
 
var level = document.getElementById("level").value;
  +
//If the input is not a number or if the number is not between 2 and 1000, clears the table.
  +
if(isNaN(level)){
  +
document.getElementById("wrong_number").innerHTML = "Please enter a number.";
  +
delete_table();
  +
return;
  +
}
 
if (level < 2){
 
if (level < 2){
  +
document.getElementById("wrong_number").innerHTML = "You have enter a number smaller than 2.";
  +
delete_table();
 
return;
 
return;
 
}
 
}
  +
if (level > 1000){
var xp = 1000, ruby = 1, item1 = 0, bt_ram = 1, tr_map = 3, j = -1, n = -1;
 
  +
document.getElementById("wrong_number").innerHTML = "You have enter a number bigger than 1000.";
const items = ["Arrows","Fan","Shuriken","Katana","Spikes","Boomerang","Petard","Bomb","Steel","Iron sand","Sushi","Mortar"];
 
  +
delete_table();
const images = [
 
  +
return;
"https://static.wikia.nocookie.net/nonograms-katana/images/f/f0/Arrows.png/revision/latest?cb=20210111142621",
 
  +
}
"https://static.wikia.nocookie.net/nonograms-katana/images/b/b9/Fan.png/revision/latest?cb=20210111143226",
 
  +
document.getElementById("level_display").innerHTML = level;
"https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Shuriken.png/revision/latest?cb=20210111145634",
 
  +
document.getElementById("wrong_number").innerHTML = "";
"https://static.wikia.nocookie.net/nonograms-katana/images/e/e9/Katana.png/revision/latest?cb=20210111145304",
 
  +
var xp = 1000, ruby = 1, bt_ram = 1, tr_map = 3;
"https://static.wikia.nocookie.net/nonograms-katana/images/9/9a/Spikes.png/revision/latest?cb=20210111145700",
 
  +
var items1 = [
"https://static.wikia.nocookie.net/nonograms-katana/images/7/7c/Boomerang.png/revision/latest?cb=20210111142949",
 
"https://static.wikia.nocookie.net/nonograms-katana/images/3/31/Petard.png/revision/latest?cb=20210111145400",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/f/f0/Arrows.png/revision/latest?cb=20210710185924"],
"https://static.wikia.nocookie.net/nonograms-katana/images/3/3b/Bomb.png/revision/latest?cb=20210111142922",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/b/b9/Fan.png/revision/latest?cb=20210710185840"],
"https://static.wikia.nocookie.net/nonograms-katana/images/c/c9/Steel.png/revision/latest?cb=20210111145724",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Shuriken.png/revision/latest?cb=20210710190109"],
"https://static.wikia.nocookie.net/nonograms-katana/images/a/a7/Iron_sand.png/revision/latest?cb=20210111143836",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/e/e9/Katana.png/revision/latest?cb=20210710190010"],
"https://static.wikia.nocookie.net/nonograms-katana/images/6/6d/Sushi.png/revision/latest?cb=20210111145817",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/6/67/Spikes_%28Makibishi%29.png/revision/latest?cb=20210710190757"],
"https://static.wikia.nocookie.net/nonograms-katana/images/8/83/Mortar.png/revision/latest?cb=20210307192837",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/7/7c/Boomerang.png/revision/latest?cb=20210710190854"],
"https://static.wikia.nocookie.net/nonograms-katana/images/4/4f/Charcoal.png/revision/latest?cb=20210111143028",
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/3/31/Petard.png/revision/latest?cb=20210710190156"],
"https://static.wikia.nocookie.net/nonograms-katana/images/9/92/Chemicals.png/revision/latest?cb=20210111143103"];
+
["5","https://static.wikia.nocookie.net/nonograms-katana/images/c/ce/Bomb_%28Horoku%29.png/revision/latest?cb=20210710190341"],
  +
["5","https://static.wikia.nocookie.net/nonograms-katana/images/c/c9/Steel.png/revision/latest?cb=20210710193716"],
  +
["5","https://static.wikia.nocookie.net/nonograms-katana/images/a/a7/Iron_sand.png/revision/latest?cb=20210710194025"],
  +
["2","https://static.wikia.nocookie.net/nonograms-katana/images/6/6d/Sushi.png/revision/latest?cb=20210710194303"],
  +
["1","https://static.wikia.nocookie.net/nonograms-katana/images/8/83/Mortar.png/revision/latest?cb=20210307192837"]];
  +
var items2 = [
  +
["0",""],
  +
["0",""],
  +
["0",""],
  +
["0",""],
  +
["0",""],
  +
["0",""],
  +
["0",""],
  +
["0",""],
  +
["5","https://static.wikia.nocookie.net/nonograms-katana/images/4/4f/Charcoal.png/revision/latest?cb=20210710193800"],
  +
["5","https://static.wikia.nocookie.net/nonograms-katana/images/9/92/Chemicals.png/revision/latest?cb=20210710194109"],
  +
["0",""],
  +
["0",""]];
  +
//Here are listed when buildings, classes (character), skills (character) and ship mission types unlock.
  +
var unlocks = [["Workshop lvl. 1"],
  +
/*lvl. 3*/ ["Shop lvl. 1","Class: Warrior"],
  +
/*lvl. 4*/ ["Pagoda lvl. 1"],
  +
/*lvl. 5*/ ["Warehouse lvl. 1"],
  +
/*lvl. 6*/ ["Alchemist's Hut lvl. 1","Class: Wizard"],
  +
/*lvl. 7*/ ["Field lvl. 1","Pagoda lvl. 2","Skill: Logistician lvl. 1","Skill: Weapon Collector lvl. 1","Skill: Treasure Hunter lvl. 1"],
  +
/*lvl. 8*/ ["Furnace lvl. 1","Food Stall lvl. 1"],
  +
/*lvl. 9*/ ["Smithy lvl. 1","Windmill lvl. 1","Class: Rogue"],
  +
/*lvl. 10*/ ["Dungeon lvl. 1","Gong lvl. 1","Pagoda lvl. 3","Skill: Logistician lvl. 2","Skill: Athlete lvl. 1","Skill: Antiquarian lvl. 1"],
  +
/*lvl. 11*/ ["Lumber Mill lvl. 1","Skill: Intellectual lvl. 1"],
  +
/*lvl. 12*/ ["Garden lvl. 1","Class: Monk"],
  +
/*lvl. 13*/ ["Rock Garden lvl. 1","Skill: Logistician lvl. 3","Skill: Weapon Collector lvl. 2","Skill: Treasure Hunter lvl. 2"],
  +
/*lvl. 14*/ ["Pagoda lvl. 4"],
  +
/*lvl. 15*/ ["Chicken Coop lvl. 1","Class: Geologist","Skill: Athlete lvl. 2"],
  +
/*lvl. 16*/ ["Skill: Logistician lvl. 4","Skill: Antiquarian lvl. 2"],
  +
/*lvl. 17*/ ["Skill: Intellectual lvl. 2"],
  +
/*lvl. 18*/ ["Pagoda lvl. 5","Class: Archeologist"],
  +
/*lvl. 19*/ ["Skill: Logistician lvl. 5","Skill: Weapon Collector lvl. 3","Skill: Treasure Hunter lvl. 3"],
  +
/*lvl. 20*/ ["Onsen lvl. 1","Dungeon lvl. 2","Skill: Athlete lvl. 3"],
  +
/*lvl. 21*/ ["Coffee Bonsai lvl. 1","Class: Samurai","Skill: Gardener lvl. 1","Skill: Rock Garden Contemplator lvl. 1"],
  +
/*lvl. 22*/ ["Pier lvl. 1","Ship lvl. 1","Skill: Carpenter lvl. 1","Skill: Metallurgist lvl. 1"],
  +
/*lvl. 23*/ ["Pagoda lvl. 6","Skill: Mechanic lvl. 1","Skill: Blacksmith lvl. 1","Ship: Exploring"],
  +
/*lvl. 24*/ ["Food Stall lvl. 2","Class: Ninja","Skill: Alchemist lvl. 1","Ship: Fishing"],
  +
/*lvl. 25*/ ["Skill: Athlete lvl. 4","Ship: Prospecting"],
  +
/*lvl. 26*/ ["Skill: Gardener lvl. 2","Skill: Rock Garden Contemplator lvl. 2","Skill: Boatswain lvl. 1","Ship: Patrolling"],
  +
/*lvl. 27*/ ["Class: Adventurer","Skill: Carpenter lvl. 2","Skill: Metallurgist lvl. 2"],
  +
/*lvl. 28*/ ["Pagoda lvl. 7","Skill: Mechanic lvl. 2","Skill: Blacksmith lvl. 2"],
  +
/*lvl. 29*/ ["Skill: Alchemist lvl. 2"],
  +
/*lvl. 30*/ ["Bridge lvl. 1","Dungeon lvl. 3","Caravan lvl. 1","Class: Scientist","Skill: Athlete lvl. 5"],
  +
/*lvl. 31*/ ["Outpost lvl. 1","Skill: Boatswain lvl. 2"],
  +
/*lvl. 32*/ ["Alchemist's Hut lvl. 6","Tailor lvl. 1","Skill: Carpenter lvl. 3","Skill: Metallurgist lvl. 3"],
  +
/*lvl. 33*/ ["Skill: Mechanic lvl. 3","Skill: Blacksmith lvl. 3"],
  +
/*lvl. 34*/ ["Skill: Alchemist lvl. 3","Skill: Cameleer lvl. 1"],
  +
/*lvl. 35*/ ["Skill: Athlete lvl. 6","Skill: Intellectual lvl. 3"],
  +
/*lvl. 36*/ [""],
  +
/*lvl. 37*/ [""],
  +
/*lvl. 38*/ [""],
  +
/*lvl. 39*/ ["Skill: Cameleer lvl. 2"],
  +
/*lvl. 40*/ ["Dungeon lvl. 4","Airship lvl. 1"],
  +
/*lvl. 41*/ [""],
  +
/*lvl. 42*/ [""],
  +
/*lvl. 43*/ [""],
  +
/*lvl. 44*/ ["Skill: Aeronaut lvl. 1"],
  +
/*lvl. 45*/ [""],
  +
/*lvl. 46*/ [""],
  +
/*lvl. 47*/ [""],
  +
/*lvl. 48*/ [""],
  +
/*lvl. 49*/ ["Skill: Aeronaut lvl. 2"],
  +
/*lvl. 50*/ ["Dungeon lvl. 5"]];
  +
  +
//Images for additional rewards.
  +
var firework = "https://static.wikia.nocookie.net/nonograms-katana/images/2/24/Firework.png/revision/latest?cb=20211025160230";
  +
var ramen = "https://static.wikia.nocookie.net/nonograms-katana/images/f/f8/Ramen.png/revision/latest?cb=20210614184327";
  +
var curry = "https://static.wikia.nocookie.net/nonograms-katana/images/d/dd/Curry.png/revision/latest?cb=20210716171827";
  +
var date_cake = "https://static.wikia.nocookie.net/nonograms-katana/images/1/12/Date_cake.png/revision/latest?cb=20211025160247";
  +
var kimono = "https://static.wikia.nocookie.net/nonograms-katana/images/8/85/Kimono.png/revision/latest?cb=20211026102346";
  +
var ninja_suit = "https://static.wikia.nocookie.net/nonograms-katana/images/3/3d/Ninja_suit.png/revision/latest?cb=20211026102357";
  +
var samurai_armor = "https://static.wikia.nocookie.net/nonograms-katana/images/5/51/Samurai_armor.png/revision/latest?cb=20211026102409";
  +
//Additional rewards for levels: 30, 50, 80 and 100 (and 150, 200, 250, etc.).
  +
var add_level = [30, 50, 80, 100];
  +
var add_rewards = [["3", firework, "0", "", "0", ""],
  +
["1", ramen, "1", curry, "1", date_cake],
  +
["1", kimono, "1", ninja_suit, "1", samurai_armor],
  +
["3", firework, "1", date_cake, "1", samurai_armor]];
 
 
  +
//Calculates experience.
 
for (i = 2; i < level; i++) {
 
for (i = 2; i < level; i++) {
xp += i*1000;
+
xp += i*1000;
 
}
 
}
   
  +
//Logic for Rubies.
 
if (level % 5 === 0) {
 
if (level % 5 === 0) {
 
ruby = 2;
 
ruby = 2;
Line 36: Line 146:
 
}
 
}
   
  +
//Calculates first and second item rewards. "n" is the number of item in the array.
item1 = items[(level-2)%items.length];
 
if (item1 == "Arrows") {
+
var n = (level-2)%12;
j = 0;
 
n = 5;
 
} else if (item1 == "Fan") {
 
j = 1;
 
n = 5;
 
} else if (item1 == "Shuriken") {
 
j = 2;
 
n = 5;
 
} else if (item1 == "Katana") {
 
j = 3;
 
n = 5;
 
} else if (item1 == "Spikes") {
 
j = 4;
 
n = 5;
 
} else if (item1 == "Boomerang") {
 
j = 5;
 
n = 5;
 
} else if (item1 == "Petard") {
 
j = 6;
 
n = 5;
 
} else if (item1 == "Bomb") {
 
j = 7;
 
n = 5;
 
} else if (item1 == "Steel") {
 
j = 8;
 
n = 5;
 
} else if (item1 == "Iron sand") {
 
j = 9;
 
n = 5;
 
} else if (item1 == "Sushi") {
 
j = 10;
 
n = 2;
 
} else if (item1 == "Mortar") {
 
j = 11;
 
n = 1;
 
}
 
 
 
  +
//Logic for Treasure map fragments.
 
if (level == 5) {
 
if (level == 5) {
 
tr_map = 5;
 
tr_map = 5;
 
}
 
}
 
 
  +
//Adds commas if the xp number is larger than 3 digits.
 
  +
var p = 0;
  +
var xpArray = xp.toString(10).split("");
  +
for (k = 3; k < xpArray.length-p; k += 3){
  +
xpArray.splice(-(k+p),0,",");
  +
p += 1;
  +
}
  +
xp = xpArray.join("");
  +
  +
//Displays everything in the table.
 
document.getElementById("xp").innerHTML = xp;
 
document.getElementById("xp").innerHTML = xp;
 
 
  +
var coins = level*2;
document.getElementById("coin").innerHTML = level*2 + " x ";
 
  +
if (coins > 200){
  +
coins = 200;
  +
}
  +
document.getElementById("coin").innerHTML = coins + " x ";
 
var imgCoin = document.createElement("img");
 
var imgCoin = document.createElement("img");
imgCoin.src = "https://static.wikia.nocookie.net/nonograms-katana/images/6/6d/Coin.png/revision/latest?cb=20210111143200";
+
imgCoin.src = "https://static.wikia.nocookie.net/nonograms-katana/images/6/6d/Coin.png/revision/latest?cb=20210710184706";
 
imgCoin.width = "30";
 
imgCoin.width = "30";
 
imgCoin.height = "30";
 
imgCoin.height = "30";
Line 91: Line 179:
 
document.getElementById("ruby").innerHTML = ruby + " x ";
 
document.getElementById("ruby").innerHTML = ruby + " x ";
 
var imgRuby = document.createElement("img");
 
var imgRuby = document.createElement("img");
imgRuby.src = "https://static.wikia.nocookie.net/nonograms-katana/images/a/a9/Ruby.png/revision/latest?cb=20210111145432";
+
imgRuby.src = "https://static.wikia.nocookie.net/nonograms-katana/images/a/a9/Ruby.png/revision/latest?cb=20210710184829";
 
imgRuby.width = "30";
 
imgRuby.width = "30";
 
imgRuby.height = "30";
 
imgRuby.height = "30";
 
document.getElementById("ruby").appendChild(imgRuby);
 
document.getElementById("ruby").appendChild(imgRuby);
 
 
document.getElementById("item1").innerHTML = n + " x ";
+
document.getElementById("item1").innerHTML = items1[n][0] + " x ";
 
var imgItem1 = document.createElement("img");
 
var imgItem1 = document.createElement("img");
imgItem1.src = images[j];
+
imgItem1.src = items1[n][1];
 
imgItem1.width = "30";
 
imgItem1.width = "30";
 
imgItem1.height = "30";
 
imgItem1.height = "30";
 
document.getElementById("item1").appendChild(imgItem1);
 
document.getElementById("item1").appendChild(imgItem1);
 
 
if (j == 8 || j == 9){
+
if (n == 8 || n == 9){
  +
document.getElementById("item2").innerHTML = items2[n][0] + " x ";
j += 4;
 
document.getElementById("item2").innerHTML = n + " x ";
 
 
var imgItem2 = document.createElement("img");
 
var imgItem2 = document.createElement("img");
imgItem2.src = images[j];
+
imgItem2.src = items2[n][1];
 
imgItem2.width = "30";
 
imgItem2.width = "30";
 
imgItem2.height = "30";
 
imgItem2.height = "30";
Line 115: Line 202:
 
}
 
}
 
 
if (level > 15) {
+
if (level > 13) {
 
document.getElementById("bt_ram").innerHTML = bt_ram + " x ";
 
document.getElementById("bt_ram").innerHTML = bt_ram + " x ";
 
var imgBTram = document.createElement("img");
 
var imgBTram = document.createElement("img");
imgBTram.src = "https://static.wikia.nocookie.net/nonograms-katana/images/d/d9/Battering_Ram.png/revision/latest?cb=20210111142838";
+
imgBTram.src = "https://static.wikia.nocookie.net/nonograms-katana/images/2/2f/Battering_ram_%28Kikkosha%29.png/revision/latest?cb=20210710192019";
 
imgBTram.width = "30";
 
imgBTram.width = "30";
 
imgBTram.height = "30";
 
imgBTram.height = "30";
Line 126: Line 213:
 
}
 
}
 
 
if (level > 5) {
+
if (level > 4) {
 
document.getElementById("tr_map").innerHTML = tr_map + " x ";
 
document.getElementById("tr_map").innerHTML = tr_map + " x ";
 
var imgTRmap = document.createElement("img");
 
var imgTRmap = document.createElement("img");
imgTRmap.src = "https://static.wikia.nocookie.net/nonograms-katana/images/9/9b/Treasure_map_fragment_lvl._1.png/revision/latest?cb=20210111145859";
+
imgTRmap.src = "https://static.wikia.nocookie.net/nonograms-katana/images/9/9b/Treasure_map_fragment_lvl._1.png/revision/latest?cb=20210710194412";
 
imgTRmap.width = "30";
 
imgTRmap.width = "30";
 
imgTRmap.height = "30";
 
imgTRmap.height = "30";
Line 135: Line 222:
 
} else {
 
} else {
 
document.getElementById("tr_map").innerHTML = "0";
 
document.getElementById("tr_map").innerHTML = "0";
  +
}
  +
  +
//Writes unlockables into the table.
  +
for (j = 0; j < 6; j += 1){
  +
try {
  +
if (unlocks[level-2][j]){
  +
document.getElementById("unlocks"+(j+1)).innerHTML = unlocks[level-2][j];
  +
} else {
  +
document.getElementById("unlocks"+(j+1)).innerHTML = "";
  +
}
  +
}
  +
catch (TypeError){
  +
document.getElementById("unlocks"+(j+1)).innerHTML = "";
  +
}
  +
  +
}
  +
  +
if (level == 80){
  +
document.getElementById("unlocks1").innerHTML = "Class: Zen Master";
  +
}
  +
  +
//This helps with calculating additional rewards.
  +
var ar = -1;
  +
for (i = 0; i < add_level.length; i++){
  +
if (level == add_level[i]){
  +
var ar = i;
  +
}
  +
}
  +
//Displays additional rewards for jubilee levels.
  +
if (ar != -1){
  +
document.getElementById("add_reward1").innerHTML = add_rewards[ar][0] + " x ";
  +
var imgAddItem1 = document.createElement("img");
  +
imgAddItem1.src = add_rewards[ar][1];
  +
imgAddItem1.width = "30";
  +
imgAddItem1.height = "30";
  +
document.getElementById("add_reward1").appendChild(imgAddItem1);
  +
  +
if (add_rewards[ar][2] != "0"){
  +
document.getElementById("add_reward2").innerHTML = add_rewards[ar][2] + " x ";
  +
var imgAddItem2 = document.createElement("img");
  +
imgAddItem2.src = add_rewards[ar][3];
  +
imgAddItem2.width = "30";
  +
imgAddItem2.height = "30";
  +
document.getElementById("add_reward2").appendChild(imgAddItem2);
  +
} else {
  +
document.getElementById("add_reward2").innerHTML = "0";
  +
}
  +
  +
if (add_rewards[ar][4] != "0"){
  +
document.getElementById("add_reward3").innerHTML = add_rewards[ar][4] + " x ";
  +
var imgAddItem3 = document.createElement("img");
  +
imgAddItem3.src = add_rewards[ar][5];
  +
imgAddItem3.width = "30";
  +
imgAddItem3.height = "30";
  +
document.getElementById("add_reward3").appendChild(imgAddItem3);
  +
} else {
  +
document.getElementById("add_reward3").innerHTML = "0";
  +
}
  +
  +
//Displays additional rewards for levels above 150.
  +
} else if (level%50 == 0 && level >= 150) {
  +
document.getElementById("add_reward1").innerHTML = add_rewards[3][0] + " x ";
  +
var imgAddItem1 = document.createElement("img");
  +
imgAddItem1.src = add_rewards[3][1];
  +
imgAddItem1.width = "30";
  +
imgAddItem1.height = "30";
  +
document.getElementById("add_reward1").appendChild(imgAddItem1);
  +
  +
document.getElementById("add_reward2").innerHTML = add_rewards[3][2] + " x ";
  +
var imgAddItem2 = document.createElement("img");
  +
imgAddItem2.src = add_rewards[3][3];
  +
imgAddItem2.width = "30";
  +
imgAddItem2.height = "30";
  +
document.getElementById("add_reward2").appendChild(imgAddItem2);
  +
  +
document.getElementById("add_reward3").innerHTML = add_rewards[3][4] + " x ";
  +
var imgAddItem3 = document.createElement("img");
  +
imgAddItem3.src = add_rewards[3][5];
  +
imgAddItem3.width = "30";
  +
imgAddItem3.height = "30";
  +
document.getElementById("add_reward3").appendChild(imgAddItem3);
  +
} else {
  +
document.getElementById("add_reward1").innerHTML = "0";
  +
document.getElementById("add_reward2").innerHTML = "0";
  +
document.getElementById("add_reward3").innerHTML = "0";
  +
}
  +
}
  +
  +
//Changes every output cell in the table to "0" or "".
  +
function delete_table_m(){
  +
document.getElementById("mosaic").innerHTML = "#0";
  +
document.getElementById("collected").innerHTML = "0";
  +
document.getElementById("needed").innerHTML = "0";
  +
document.getElementById("percent").innerHTML = "0";
  +
}
  +
  +
//Calculates how many fragments are still needed to complete a mosaic, plus some other useful information.
  +
function mosaic_calculator_f(){
  +
var mosaic_sizes = [368, 640, 640, 640, 1280, 2560, 2560, 2560, 2560, 2560];
  +
var mosaics_f = [0];
  +
var fragment_counter = 0;
  +
for (i = 0; i < mosaic_sizes.length; i++){
  +
fragment_counter = fragment_counter + mosaic_sizes[i];
  +
mosaics_f.push(fragment_counter);
  +
}
  +
//var mosaics_f = [0, 368, 1008, 1648, 2288, 3568, 6128, 8688, 11248, 13808, 16368];
  +
  +
var max_fragments = mosaics_f[mosaics_f.length - 1];
  +
var fragments = document.getElementById("fragments").value;
  +
  +
//If the input is not a number or if the number is not between 0 and last mosaic fragment, clears the table.
  +
if(isNaN(fragments)){
  +
document.getElementById("wrong_number").innerHTML = "Please enter a number.";
  +
delete_table_m();
  +
return;
  +
}
  +
if (fragments < 0){
  +
document.getElementById("wrong_number").innerHTML = "You have enter a number smaller than 0.";
  +
delete_table_m();
  +
return;
  +
}
  +
if (fragments > max_fragments){
  +
document.getElementById("wrong_number").innerHTML = "You have enter a number bigger than " + max_fragments + '.';
  +
delete_table_m();
  +
return;
  +
}
  +
if (fragments == max_fragments){
  +
document.getElementById("wrong_number").innerHTML = "Congratulations, you have completed all mosaics.";
  +
delete_table_m();
  +
return;
  +
}
  +
document.getElementById("wrong_number").innerHTML = "";
  +
  +
//Logic of the calculator.
  +
for (i = 1; i < mosaics_f.length; i++){
  +
if (fragments < mosaics_f[i]){
  +
document.getElementById("mosaic").innerHTML = "#" + i;
  +
var collected = document.getElementById("collected").innerHTML = fragments - mosaics_f[i-1];
  +
document.getElementById("needed").innerHTML = mosaics_f[i] - fragments;
  +
document.getElementById("percent").innerHTML = Math.round((collected/(mosaics_f[i] - mosaics_f[i-1])) * 10000)/100 + "%";
  +
break;
  +
}
 
}
 
}
 
}
 
}
Line 145: Line 374:
 
var getAnswer = document.createElement("button");
 
var getAnswer = document.createElement("button");
 
getAnswer.innerHTML = "Calculate";
 
getAnswer.innerHTML = "Calculate";
  +
getAnswer.id = "myBtn";
 
getAnswer.addEventListener("click", calculate);
 
getAnswer.addEventListener("click", calculate);
 
inputBox.appendChild(input);
 
inputBox.appendChild(input);
 
inputBox.appendChild(getAnswer);
 
inputBox.appendChild(getAnswer);
  +
inputBox.addEventListener("keyup", function(event) {
  +
if (event.keyCode === 13) {
  +
event.preventDefault();
  +
document.getElementById("myBtn").click();
  +
}
  +
});
 
document.getElementById("reward_calculator").appendChild(inputBox);
 
document.getElementById("reward_calculator").appendChild(inputBox);
  +
}
  +
  +
//Creates the input box and button on page "Mosaic".
  +
if (mw.config.get("wgPageName") === "Mosaic") {
  +
var inputBox = document.createElement("div");
  +
var input = document.createElement("input");
  +
input.id = "fragments";
  +
var getAnswer = document.createElement("button");
  +
getAnswer.innerHTML = "Calculate";
  +
getAnswer.id = "myBtn";
  +
getAnswer.addEventListener("click", mosaic_calculator_f);
  +
inputBox.appendChild(input);
  +
inputBox.appendChild(getAnswer);
  +
inputBox.addEventListener("keyup", function(event) {
  +
if (event.keyCode === 13) {
  +
event.preventDefault();
  +
document.getElementById("myBtn").click();
  +
}
  +
});
  +
document.getElementById("mosaic_calculator").appendChild(inputBox);
  +
}
  +
  +
  +
  +
/* the code below is needed for combat simulation */
  +
  +
var food_effects = { Ambrosia: {hp:30}, Onigiri:{hp:10}, Flatbread:{ep:10}, Bun:{hp:15,ep:5}, Muffin:{hp:15,ep:7}, Bento:{hp:5,ep:15}, Pasta:{hp:7,ep:20}, Baklava:{hp:12,ep:12}, Eggs:{hp:17,ep:5}, PoHP1:{hp:20}, PoHP2:{hp:25}, PoEP1:{ep:20} }
  +
  +
var boost_list = {
  +
'Level': { 'repl':26, '*':{'hp':'*','ep':'*'} },
  +
'Sword': { '0':{}, '1': {'dmg':3}, '2': {'dmg':5}, '3': {'dmg':7}, '4': {'dmg':9} },
  +
'Armor': { '0':{}, '1': {'def':2}, '2': {'def':4}, '3': {'def':6}, '4': {'def':8,'dmg':1,'ep':10} },
  +
'Shield': { '0':{}, '1': {'def':1}, '2': {'def':2}, '3': {'def':3}, '4': {'def':4,'c2r':10} },
  +
'Ring': { '0':{}, '1': {'dmg':1}, '2': {'dmg':2}, '3': {'dmg':3}, '4': {'dmg':4}, '4+': {'dmg':4,'ep':5} },
  +
'Martial arts': { '0':{}, '1': {'dmg':1}, '2': {'dmg':2}, '3': {'dmg':3} },
  +
'Hardening': { '0':{}, '1': {'def':1}, '2': {'def':2} },
  +
'Equipment preparation':{ '0':{}, '1': {'sck':1}, '2': {'sck':2} },
  +
'Agility': { '0':{}, '1': {'ap':1} },
  +
'Smashing blow':{ '0':{}, '1': {}, '2': {} },
  +
'Helmet': { '0':{}, '1':{'hp':5} },
  +
'Dagger': { '0':{}, '1':{'c2c':5} }
  +
};
  +
  +
var presets = {
  +
1: {Sword: 0, Armor: 0, Shield: 0, Ring: 0, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':0 },
  +
3: {Sword: 0, Armor: 0, Shield: 0, Ring: 0, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':1 },
  +
5: {Sword: 1, Armor: 1, Shield: 1, Ring: 1, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':1 },
  +
6: {Sword: 1, Armor: 1, Shield: 1, Ring: 1, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':2 },
  +
9: {Sword: 1, Armor: 1, Shield: 1, Ring: 1, 'Martial arts': 1, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':2 },
  +
10: {Sword: 2, Armor: 2, Shield: 2, Ring: 2, 'Martial arts': 1, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':2 },
  +
12: {Sword: 2, Armor: 2, Shield: 2, Ring: 2, 'Martial arts': 1, 'Equipment preparation': 1, Hardening: 1, Agility: 0, 'Smashing blow':2 },
  +
15: {Sword: 3, Armor: 3, Shield: 3, Ring: 3, 'Martial arts': 2, 'Equipment preparation': 1, Hardening: 1, Agility: 1, 'Smashing blow':2 },
  +
18: {Sword: 3, Armor: 3, Shield: 3, Ring: 3, 'Martial arts': 2, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 },
  +
20: {Sword: 4, Armor: 4, Shield: 4, Ring: 4, 'Martial arts': 2, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 },
  +
21: {Sword: 4, Armor: 4, Shield: 4, Ring: 4, 'Martial arts': 3, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 },
  +
26: {Sword: 4, Armor: 4, Shield: 4, Ring: 4, 'Martial arts': 3, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 }
  +
};
  +
  +
var enemy_list = [
  +
{name: 'Shapeshifter 3A-3C', hp: 27, dmg: 8, def: 5, ap: 6, skills: '*Shapeshifter*'},
  +
{name: 'Orc chieftain (3A boss)', hp: 55, dmg: 9, def: 5, ap: 4},
  +
{name: 'Orc warlord (3B boss)', hp: 65, dmg: 9, def: 5, ap: 4},
  +
{name: 'Bone dragon (3C boss)', hp: 85, dmg: 9, def: 5, ap: 4},
  +
{name: 'Shapeshifter 4A-4C', hp: 36, dmg: 12, def: 9, ap: 6, skills: '*Shapeshifter*'},
  +
{name: 'Leviathan (4A boss)', hp: 84, dmg: 14, def: 9, ap: 4},
  +
{name: 'Mynd flyer (4B boss)', hp: 104, dmg: 14, def: 9, ap: 6},
  +
{name: 'Eye tyrant (4C boss)', hp: 124, dmg: 15, def: 9, ap: 4},
  +
{name: 'Demon kingpin (5A boss)', hp: 130, dmg: 18, def: 12, ap: 4},
  +
{name: 'Demon lord (5B boss)', hp: 170, dmg: 19, def: 13, ap: 4},
  +
{name: 'Bone dragon (5C quest)', hp: 230, dmg: 19, def: 13, ap: 4, image: 'a/a5/Foe-Bone_Dragon.png'},
  +
{name: 'The dragon (5C boss)', hp: 230, dmg: 21, def: 14, ap: 4, image: '9/92/Foe-Evil_dragon%28boss5C%29.png'}
  +
];
  +
  +
var icons = {
  +
'Sword-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/a4/Sword_for_a_hero_lvl._1.png">',
  +
'Sword-2': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/b/bc/Sword_for_a_hero_lvl._2.png">',
  +
'Sword-3': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/36/Sword_for_a_hero_lvl._3.png">',
  +
'Sword-4': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/0/09/Sword_for_a_hero_lvl._4.png">',
  +
'Armor-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/f/f3/Armor_for_a_hero_lvl._1.png">',
  +
'Armor-2': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/a6/Armor_for_a_hero_lvl._2.png">',
  +
'Armor-3': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/0/05/Armor_for_a_hero_lvl._3.png">',
  +
'Armor-4': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/a3/Armor_for_a_hero_lvl._4.png">',
  +
'Shield-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/6/6c/Shield_for_a_hero_lvl._1.png">',
  +
'Shield-2': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/9/9f/Shield_for_a_hero_lvl._2.png">',
  +
'Shield-3': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/c/ca/Shield_for_a_hero_lvl._3.png">',
  +
'Shield-4': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/8/80/Shield_for_a_hero_lvl._4.png">',
  +
'Ring-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/e/eb/Ring_for_a_hero_lvl._1.png">',
  +
'Ring-2': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/18/Ring_for_a_hero_lvl._2.png">',
  +
'Ring-3': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/b/bb/Ring_for_a_hero_lvl._3.png">',
  +
'Ring-4': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/10/Ring_for_a_hero_lvl._4.png">',
  +
'Ring-4+': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Ring_for_a_hero_lvl._4%2B.png">',
  +
'Dagger-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/4/45/Dagger.png">',
  +
'Helmet-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/37/Helmet.png">',
  +
'HP': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/31/Dungeon_-_Health.png">',
  +
'EP': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/1e/Dungeon_-_Energy.png">',
  +
'AP': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/8/84/Dungeon_-_Action_points.png">',
  +
'DEF': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Dungeon_-_Defense.png">',
  +
'DMG': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/5/59/Dungeon_-_Damage.png">',
  +
'sck': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/6/61/Sack.png">',
  +
'Ambrosia': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/e/e9/Potion_Ambrosia.png">',
  +
'Onigiri': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/f/f3/Onigiri.png">',
  +
'Flatbread':'<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/4/4f/Flatbread.png">',
  +
'Bun': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/9/9a/Cherry_bun.png">',
  +
'Muffin': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/1d/Muffin.png">',
  +
'Bento': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/34/Mushroom_rice_%28Bento%29.png">',
  +
'Pasta': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/b/bf/Porcini_pasta.png">',
  +
'Baklava': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/34/Baklava.png">',
  +
'Eggs': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/3f/Marinated_eggs.png">',
  +
'PoHP1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/35/Potion_of_healing.png">',
  +
'PoHP2': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/f/f4/Potion_of_healing_lvl._2.png">',
  +
'PoEP1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/7/72/Potion_of_energy.png">',
  +
'fortified': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/2/27/Poke.png">',
  +
'frenzied': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/d/d2/Potion_Berserker_rage.png">',
  +
'demoralized': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/8/8e/Demoralization.png">',
  +
'Smashing blow-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/d/d4/Smashing_blow.png">',
  +
'c2c': '',
  +
'c2r': ''
  +
};
  +
  +
icons['Agility-1'] = icons['AP'];
  +
icons['Hardening-1'] = icons['DEF'];
  +
icons['Hardening-2'] = icons['DEF']+icons['DEF'];
  +
icons['Martial arts-1'] = icons['DMG'];
  +
icons['Martial arts-2'] = icons['DMG']+icons['DMG'];
  +
icons['Martial arts-3'] = icons['DMG']+icons['DMG']+icons['DMG'];
  +
icons['Equipment preparation-1'] = icons['sck'];
  +
icons['Equipment preparation-2'] =icons['sck']+icons['sck'];
  +
icons['Smashing blow-2'] = icons['Smashing blow-1']+icons['Smashing blow-1'];
  +
  +
function fillHeroFromPreset(event) {
  +
var id = event.srcElement.innerHTML;
  +
document.getElementById('Level').value = id;
  +
for (var boost in presets[id]) {
  +
var boost_level = presets[id][boost];
  +
document.getElementById(boost).value = boost_level;
  +
}
  +
fillHeroStats();
  +
}
  +
  +
function fillHeroStats() {
  +
var attr = ['hp', 'ep','dmg','def','ap', 'sck', 'c2c', 'c2r'];
  +
//reset fields to their initial values
  +
for (var a in attr) {
  +
document.getElementById('h'+attr[a]).value = document.getElementById('h'+attr[a]).getAttribute('data-init');
  +
}
  +
//iterate fields
  +
var boost_fields = document.getElementById('h_defi').getElementsByTagName('select');
  +
for (var f=0; f<boost_fields.length; f++) {
  +
var boost_name = boost_fields[f].id;
  +
var boost_value = boost_fields[f].value;
  +
//show boost's icon
  +
var icon_ph = document.getElementById(boost_name+'-pic');
  +
var icon_tag = boost_name+'-'+boost_value
  +
icon_ph.innerHTML = ' '+( icons[icon_tag] ? icons[icon_tag] : '' );
  +
//add boost's value to the appropriate hero's stats
  +
var targets = boost_list[boost_name][boost_value];
  +
for (var t in targets) {
  +
var field = document.getElementById('h'+t);
  +
field.value = parseInt(field.value) + targets[t];
  +
}
  +
}
  +
//clear previous results
  +
document.getElementById('h_calc');
  +
document.getElementById('e_calc');
  +
}
  +
  +
function filterEnemyList(event) {
  +
var level = event.srcElement.value;
  +
var elist = document.getElementById("enemylist").options;
  +
var lastshown = null;
  +
var beforelastshown = null;
  +
for (option in elist) {
  +
if (elist[option].innerHTML) {
  +
var show = (level=="" || elist[option].innerHTML.indexOf(" - "+level)>0);
  +
elist[option].style.display = show ? "" : "none";
  +
elist[option].selected = "";
  +
if (show) {
  +
beforelastshown = lastshown;
  +
lastshown = elist[option];
  +
}
  +
}
  +
}
  +
//adjust selection to include only visible ones
  +
if (lastshown) {
  +
if (beforelastshown && (level=='1C' || level=='F2' || level=='F3' || level=='5C' || level=='')) {
  +
lastshown = beforelastshown;
  +
}
  +
lastshown.selected = "selected"
  +
lastshown.click();
  +
}
  +
}
  +
  +
function fillEnemyStats(event) {
  +
var index = event.srcElement.value;
  +
var attr = ['hp','dmg','def','ap'];
  +
for (var a in attr) {
  +
document.getElementById('e'+attr[a]).value = enemy_list[index][attr[a]];
  +
}
  +
document.getElementById('hdemo').checked = enemy_list[index].skills && (enemy_list[index].skills.indexOf('*Shapeshifter*')>=0 || enemy_list[index].skills.indexOf('*Demoralization*')>=0);
  +
document.getElementById('epoke').checked = enemy_list[index].skills && (enemy_list[index].skills.indexOf('*Shielding*')>=0);
  +
//remove enemy's portrait
  +
if (document.getElementById('eimage')) {
  +
document.getElementById('eimage').remove();
  +
}
  +
//... and attach it again, if possible
  +
if (enemy_list[index].image) {
  +
var eimage = document.createElement('img');
  +
eimage.src = 'https://static.wikia.nocookie.net/nonograms-katana/images/'+enemy_list[index].image;
  +
eimage.style = 'width:150px;height:auto';
  +
eimage.id = 'eimage';
  +
document.getElementById('e_defi').appendChild(eimage);
  +
}
  +
}
  +
  +
function calculateCombat() {
  +
//prepare food selection
  +
var es = parseInt(document.getElementById('hsck').value);
  +
var foodlist = { Onigiri:7+es, Flatbread:7+es, Bun:5+es, Muffin:5+es, Bento:5+es, Pasta:5+es, Baklava:7+es, Eggs:5+es, PoHP1:5+es, PoHP2:5+es, PoEP1:5+es, Ambrosia:1+es };
  +
for (var food in foodlist) {
  +
document.getElementById(food).setAttribute('data-limit', foodlist[food]);
  +
}
  +
var h_out = document.getElementById('h_calc');
  +
var e_out = document.getElementById('e_calc');
  +
//get hero stats and apply effects
  +
var hero = {};
  +
hero.hpmax = parseInt(document.getElementById('hhp').value);
  +
hero.epmax = parseInt(document.getElementById('hep').value);
  +
hero.apmax = parseInt(document.getElementById('hap').value);
  +
hero.dmg = parseInt(document.getElementById('hdmg').value);
  +
hero.def = parseInt(document.getElementById('hdef').value);
  +
if (document.getElementById('hpoke').checked) {
  +
hero.def+= 4;
  +
}
  +
if (document.getElementById('hdemo').checked) {
  +
hero.def = Math.floor(hero.def * 0.4);
  +
}
  +
if (document.getElementById('hberserk').checked) {
  +
hero.dmg = Math.floor(hero.dmg * 1.4); //hero's berserk damage rounded down? not confirmed
  +
hero.apmax+= 2;
  +
}
  +
hero.spread = Math.floor(hero.dmg>=15 ? hero.dmg/5 : (hero.dmg>=12 ? 3 : 2));
  +
hero.critchance = parseInt(document.getElementById('hc2c').value);
  +
hero.critdmgratio = 2;
  +
hero.retaliatechance = parseInt(document.getElementById('hc2r').value);
  +
hero.log = document.getElementById('h_simlog');
  +
//get enemy stats and apply effects
  +
var enemy = {};
  +
enemy.hpmax = parseInt(document.getElementById('ehp').value);
  +
enemy.apmax = parseInt(document.getElementById('eap').value);
  +
enemy.dmg = parseInt(document.getElementById('edmg').value);
  +
enemy.def = parseInt(document.getElementById('edef').value);
  +
if (document.getElementById('epoke').checked) {
  +
enemy.def+= 4;
  +
}
  +
if (document.getElementById('edemo').checked) {
  +
enemy.def = Math.floor(enemy.def * 0.4);
  +
}
  +
enemy.spread = Math.floor(enemy.dmg>=15 ? enemy.dmg/5 : (enemy.dmg>=12 ? 3 : 2));
  +
enemy.critchance = parseInt(document.getElementById('hc2c').value);
  +
enemy.critdmgratio = 1.5;
  +
enemy.log = document.getElementById('e_simlog');
  +
//output calculations for the hero
  +
h_out.innerHTML = '<div><small>Effective AP: ' + hero.apmax + ', DEF: ' + hero.def + ', DMG: ' + hero.dmg + ' &#177;'+hero.spread+'</small></div>';
  +
var ddmgmin = Math.max( hero.dmg-hero.spread , 1);
  +
var ddmgmax = hero.dmg+hero.spread;
  +
var ddmgminc = hero.critdmgratio*ddmgmin;
  +
var ddmgmaxc = hero.critdmgratio*ddmgmax;
  +
h_out.innerHTML+= '<div>Damage delivered: ' + ddmgmin + '-' + ddmgmax + ' <small>(when critical: ' + ddmgminc + '-' + ddmgmaxc + ')</small></div>';
  +
var rdmgmin = Math.max(ddmgmin-enemy.def,1);
  +
var rdmgmax = Math.max(ddmgmax-enemy.def,1);
  +
var rdmgminc = Math.max(ddmgminc-enemy.def,2);
  +
var rdmgmaxc = Math.max(ddmgmaxc-enemy.def,2);
  +
h_out.innerHTML+= '<div>Damage to enemy: ' + rdmgmin + '-' + rdmgmax + ' <small>(when critical: ' + rdmgminc + '-' + rdmgmaxc + ')</small></div>';
  +
h_out.innerHTML+= '<div><b>Hits to kill the enemy: ' + Math.ceil(enemy.hpmax/rdmgmax) + '-' + Math.ceil(enemy.hpmax/rdmgmin) + '</b></div>';
  +
h_out.innerHTML+= '<div>(absolute minimum: ' + Math.ceil(enemy.hpmax/rdmgmaxc) + ')</div>';
  +
//output calculations for the enemy
  +
e_out.innerHTML = '<div><small>Effective AP: ' + enemy.apmax + ', DEF: ' + enemy.def + ', DMG: ' + enemy.dmg + ' &#177;'+enemy.spread+'</small></div>';
  +
ddmgmin = Math.max( enemy.dmg-enemy.spread , 1);
  +
ddmgmax = enemy.dmg+enemy.spread;
  +
ddmgminc = Math.floor(enemy.critdmgratio*ddmgmin);
  +
ddmgmaxc = Math.floor(enemy.critdmgratio*ddmgmax);
  +
e_out.innerHTML+= '<div>Damage delivered: ' + ddmgmin + '-' + ddmgmax + ' <small>(when critical: ' + ddmgminc + '-' + ddmgmaxc + ')</small></div>';
  +
rdmgmin = Math.max(ddmgmin-hero.def,1);
  +
rdmgmax = Math.max(ddmgmax-hero.def,1);
  +
rdmgminc = Math.max(ddmgminc-hero.def,2);
  +
rdmgmaxc = Math.max(ddmgmaxc-hero.def,2);
  +
e_out.innerHTML+= '<div>Damage to hero: ' + rdmgmin + '-' + rdmgmax + ' <small>(when critical: ' + rdmgminc + '-' + rdmgmaxc + ')</small></div>';
  +
e_out.innerHTML+= '<div><b>Hits to kill the hero: ' + Math.ceil(hero.hpmax/rdmgmax) + '-' + Math.ceil(hero.hpmax/rdmgmin) + '</b></div>';
  +
e_out.innerHTML+= '<div>(absolute minimum: ' + Math.ceil(hero.hpmax/rdmgmaxc) + ')</div>';
  +
//SIMULATE
  +
//assume hero's initiative, setup food reserves
  +
var attacker = hero;
  +
attacker.hp = attacker.hpmax;
  +
attacker.ep = attacker.epmax;
  +
attacker.ap = attacker.apmax;
  +
attacker.healing = document.getElementById('heal').checked;
  +
attacker.smashing = document.getElementById('sbuse').checked ? parseInt(document.getElementById('Smashing blow').value) : 0;
  +
attacker.food = {};
  +
if (attacker.healing) {
  +
for (var fooditem in food_effects) {
  +
if (document.getElementById(fooditem).checked) {
  +
attacker.food[fooditem] = parseInt(document.getElementById(fooditem).getAttribute('data-limit'));
  +
}
  +
}
  +
}
  +
attacker.counter = 0;
  +
attacker.log.innerHTML = '';
  +
//setup enemy
  +
var defender = enemy;
  +
defender.hp = defender.hpmax;
  +
defender.ap = 0;
  +
defender.counter = 0;
  +
defender.log.innerHTML = '';
  +
//healing info
  +
if (attacker.healing) {
  +
var out = '<nobr>Food:'
  +
for (var food in attacker.food) {
  +
if (attacker.food[food]) {
  +
out+= ' '+attacker.food[food]+'x'+(icons[food]?icons[food]:food);
  +
}
  +
}
  +
out+= '</nobr><hr>';
  +
attacker.log.innerHTML+= out;
  +
defender.log.innerHTML+= 'unlimited '+icons['EP']+' and no food<hr>';
  +
}
  +
//main loop
  +
var watchdog = 0;
  +
var roundno = 1;
  +
while (defender.hp>0 && attacker.hp>0 && watchdog<1000) {
  +
watchdog+= 1;
  +
//update stats, show results
  +
var alog = 'HP:'+attacker.hp+(attacker.epmax?', EP:'+attacker.ep:'')+', AP:'+attacker.ap;
  +
var dlog = 'HP:'+defender.hp+(defender.epmax?', EP:'+defender.ep:'')+', AP:'+defender.ap;
  +
//decision is being made
  +
var action = 'attack'; //default action to be taken
  +
//replenish health if necessary
  +
if (attacker.healing && attacker.hpmax-attacker.hp>=10) {
  +
//find the best food to use
  +
var bestheal = 0;
  +
for (var food in food_effects) {
  +
if (food!='Ambrosia' && food_effects[food].hp && attacker.food[food]>0 && (!food_effects[food].ep || food_effects[food].hp>bestheal) && attacker.hpmax>=attacker.hp+food_effects[food].hp*0.9) {
  +
action = food;
  +
bestheal = food_effects[food].hp;
  +
}
  +
}
  +
}
  +
//replenish energy if necessary
  +
if (attacker.healing && attacker.epmax && (attacker.smashing && attacker.ep<4 || attacker.ep<1)) {
  +
//find the best food to use
  +
for (var food in food_effects) {
  +
if (food_effects[food].ep && (!food_effects[food].hp || food_effects[food].hp<food_effects[food].ep) && attacker.food[food]>0 && attacker.epmax>=attacker.ep+food_effects[food].ep) {
  +
action = food;
  +
}
  +
}
  +
}
  +
//use the food, if so decided
  +
if (action!="attack") {
  +
if (food_effects[action].hp) {
  +
attacker.hp = Math.min(attacker.hp+food_effects[action].hp, attacker.hpmax);
  +
}
  +
if (food_effects[action].ep) {
  +
attacker.ep = Math.min(attacker.ep+food_effects[action].ep, attacker.epmax);
  +
}
  +
attacker.ap-= 2;
  +
attacker.food[action]-= 1;
  +
alog+= ' => <b style="color:darkred">consumes</b> '+action+' ('+attacker.food[action]+' left)';
  +
dlog+= ' => (waits)';
  +
}
  +
//attack not possible - out of energy and no healing was possible?
  +
if (action=='attack' && attacker.epmax && (attacker.smashing && attacker.ep<4 || attacker.ep<1) ) {
  +
attacker.ap-= 3;
  +
attacker.ep+= 10;
  +
alog+= ' => <b style="color:goldenrod">Charge of motivation!</b>';
  +
dlog+= ' => (waits)';
  +
action = 'CoM';
  +
}
  +
//if no other action was taken, fight
  +
if (action=='attack') {
  +
//determine damage: base, delivered, received
  +
var effdmg = attacker.dmg + Math.floor(Math.random()*(attacker.spread+attacker.spread+1))-attacker.spread;
  +
var smashing = attacker.smashing && attacker.ep>=4 ? attacker.smashing : 0;
  +
var crit = smashing ? false : Math.random()*100<attacker.critchance; //normal crit is not possible when SB used
  +
var dmgdelivered = Math.floor(effdmg * (crit ? attacker.critdmgratio : 1) * (smashing ? 1+smashing*0.5 : 1)); //monster's crit damage rounded down? not confirmed
  +
var dmgreceived = Math.max(dmgdelivered - defender.def, (crit || smashing ? 2 : 1));
  +
//update stats
  +
attacker.counter+= 1;
  +
defender.hp-= dmgreceived;
  +
attacker.ap-= smashing ? 4 : 3;
  +
if (attacker.epmax) {
  +
attacker.ep-= smashing ? 4 : 1;
  +
}
  +
alog+= ' => <b>attacks</b> '+(smashing?' <b style="color:limegreen">SB L'+attacker.smashing+'</b>':'')+(crit?' <b style="color:orange">CRIT!</b>':'');
  +
dlog+= ' => gets hit for: '+dmgreceived;
  +
//counter-attack?
  +
if (defender.retaliatechance && Math.random()*100<defender.retaliatechance) {
  +
dmgreturned = Math.floor(3+3*Math.random());
  +
dmgreturned = Math.min(dmgreturned, Math.floor(attacker.hpmax*0.25), attacker.hp-1);
  +
alog+= ', gets counter-hit for: '+dmgreturned;
  +
attacker.hp-= dmgreturned;
  +
dlog+= ', <b style="color:blue">counter-attacks</b>';
  +
}
  +
}
  +
//check if still alive (or rescue if possible)
  +
if (defender.hp<=0) {
  +
if (defender.healing && defender.food.Ambrosia>0) {
  +
defender.hp = Math.min(30, defender.hpmax);
  +
defender.food.Ambrosia-= 1;
  +
dlog+= ' <b style="color:red">Ambrosia</b> ('+defender.food.Ambrosia+' left)';
  +
}
  +
else {
  +
dlog+= ' <b style="color:magenta">FALLEN</b><br>- defeated in '+attacker.counter+' hit(s), '+roundno+' turn(s)';
  +
}
  +
}
  +
//update logs
  +
attacker.log.innerHTML+= '<div>'+alog+'</div>';
  +
defender.log.innerHTML+= '<div>'+dlog+'</div>';
  +
//when attacker is out of AP, switch sides
  +
if (attacker.ap<=0) {
  +
var swap = attacker;
  +
attacker = defender;
  +
defender = swap;
  +
attacker.ap+= attacker.apmax;
  +
roundno+= 1;
  +
}
  +
}
  +
//end of main loop
  +
if (hero.healing) {
  +
var out = '<hr><nobr>Left:';
  +
var anyleft = 0;
  +
for (var food in hero.food) {
  +
if (hero.food[food]) {
  +
anyleft+= 1;
  +
out+= ' '+hero.food[food]+'x'+(icons[food]?icons[food]:food);
  +
}
  +
}
  +
if (anyleft==0) {
  +
out+= ' NOTHING ';
  +
}
  +
out+= '</nobr>';
  +
hero.log.innerHTML+= out;
  +
}
  +
}
  +
  +
function togglefood() {
  +
var foodsack = document.getElementById('foodsack');
  +
if (foodsack.style.display=='none') {
  +
foodsack.style.display = null;
  +
}
  +
else {
  +
foodsack.style.display = 'none';
  +
}
  +
}
  +
  +
function setupCombatForm(placeholderId) {
  +
var target = document.getElementById(placeholderId);
  +
//general form structure
  +
var tipstyle = 'color:gray; margin:3px; font-style:italic; font-size: smaller; line-height:1';
  +
var table = document.createElement('table');
  +
table.border = 1;
  +
table.cellSpacing = 0;
  +
table.cellPadding = 2;
  +
table.innerHTML = '<tr valign="top"><td id="h_defi">Hero configuration:</td><td id="e_defi">Enemy selection:</td></tr>';
  +
table.innerHTML+= '<tr valign="top"><td id="h_stat"></td><td id="e_stat"></td></tr>';
  +
table.innerHTML+= '<tr valign="top"><td id="h_buff"></td><td id="e_buff"></td></tr>';
  +
var foodsack = '';
  +
for (var food in food_effects) {
  +
foodsack+= ' <input type="checkbox" id="'+food+'" data-limit="0" checked="checked">'+(icons[food]?icons[food]:food);
  +
}
  +
table.innerHTML+= '<tr><td colspan="2" align="left"><div style="'+tipstyle+'">Special algorithms may be applied to simulate using consumables/skills permitted, e.g. to replenish HP/EP.<br>This is not a part of the game engine, it acts as user would do and may be not optimal.</div><input type="checkbox" id="heal" />Allow using food<span id="foodsack" style="display:none">: '+foodsack+'</span><br><input type="checkbox" id="sbuse" />Use Smashing blow whenever possible</td></tr>';
  +
table.innerHTML+= '<tr><td colspan="2" align="center"><button id="emu_run">CALCULATE</button></td></tr>';
  +
table.innerHTML+= '<tr valign="top"><td id="h_calc"></td><td id="e_calc"></td></tr>';
  +
table.innerHTML+= '<tr valign="top" style="font-size: 66%"><td id="h_simlog"></td><td id="e_simlog"></td></tr>';
  +
target.appendChild(table);
  +
document.getElementById('heal').addEventListener('click', togglefood);
  +
document.getElementById('emu_run').addEventListener('click', calculateCombat);
  +
//stats forms
  +
document.getElementById('h_stat').innerHTML = '<div style="'+tipstyle+'">Enter/verify attributes of the hero.<br>These values are updated when gear/skils are selected above.</div>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hhp" data-init="19"/> '+icons['HP']+' HP &nbsp; &nbsp; &nbsp; <input size="1" id="hep" data-init="29"/> '+icons['EP']+' EP<br>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hdmg" data-init="5"/> '+icons['DMG']+' DMG<br>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hdef" data-init="2"/> '+icons['DEF']+' DEF<br>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hap" data-init="4"/> '+icons['AP']+' AP<br>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hc2c" data-init="5"/> '+icons['c2c']+' % chance to crit<br>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hc2r" data-init="0" /> '+icons['c2r']+' % chance to reflect damage<br>';
  +
document.getElementById('h_stat').innerHTML+= '<input size="1" id="hsck" data-init="0" /> '+icons['sck']+' extra space';
  +
document.getElementById('e_stat').innerHTML = '<div style="'+tipstyle+'">Enter/verify attributes of the enemy.<br>These values are updated when enemy is selected above.</div>';
  +
document.getElementById('e_stat').innerHTML+= '<input size="1" id="ehp"/> '+icons['HP']+' HP<br>';
  +
document.getElementById('e_stat').innerHTML+= '<input size="1" id="edmg"/> '+icons['DMG']+' DMG<br>';
  +
document.getElementById('e_stat').innerHTML+= '<input size="1" id="edef"/> '+icons['DEF']+' DEF<br>';
  +
document.getElementById('e_stat').innerHTML+= '<input size="1" id="eap"/> '+icons['AP']+' AP<br>';
  +
document.getElementById('e_stat').innerHTML+= '<input size="1" id="ec2c" value="5"/> '+icons['c2c']+' % chance to crit';
  +
//buffs forms
  +
document.getElementById('h_buff').innerHTML = '<div style="'+tipstyle+'">Declare special status of the hero - buffs and debuffs.<br>Some values may change when selecting an enemy.</div>';
  +
document.getElementById('h_buff').innerHTML+= '<input type="checkbox" id="hpoke"/>'+(icons['fortified']?icons['fortified']+' ':'')+'Hero used "Poke"<br><input type="checkbox" id="hberserk"/>'+(icons['frenzied']?icons['frenzied']+' ':'')+'Hero used "Berserker rage"<br><input type="checkbox" id="hdemo"/>'+(icons['demoralized']?icons['demoralized']+' ':'')+'Has been demoralized by enemy';
  +
document.getElementById('e_buff').innerHTML = '<div style="'+tipstyle+'">Declare special status of the enemy - buffs and debuffs.<br>Some values may change when selecting an enemy.</div>';
  +
document.getElementById('e_buff').innerHTML+= '<input type="checkbox" id="edemo"/>'+(icons['demoralized']?icons['demoralized']+' ':'')+'Has been demoralized by hero<br><input type="checkbox" id="epoke"/>'+(icons['DEF']?icons['DEF']+' ':'')+'Used/received defence boost';
  +
//hero setup form
  +
var hero_setup = document.getElementById('h_defi');
  +
//... first preset buttons...
  +
var preset_bar = document.createElement('div');
  +
preset_bar.innerHTML = '<div style="'+tipstyle+'">Pick a preset reflecting hero\'s level to quickly fill the form<br>with the best gear and skills available for that level.</div><small>Presets: </small>';
  +
for (var p in presets) {
  +
var p_btn = document.createElement('button');
  +
p_btn.innerHTML = p;
  +
p_btn.style = 'font-size: 8pt; padding: 0; margin: 1px';
  +
p_btn.addEventListener('click', fillHeroFromPreset);
  +
preset_bar.appendChild(p_btn);
  +
}
  +
hero_setup.appendChild(preset_bar);
  +
hero_setup.appendChild(document.createElement('hr'));
  +
var info2 = document.createElement('div');
  +
info2.style = tipstyle;
  +
info2.innerHTML = "Select/verify gear and skills your hero possesses.<br>These values are updated when preset is selected above.";
  +
hero_setup.appendChild(info2);
  +
//... then individual gear/skill entries
  +
for (var boostname in boost_list) {
  +
//first, unpack a short definition
  +
if (boost_list[boostname]['repl']) {
  +
for (var r=1; r<=boost_list[boostname]['repl']; r++) {
  +
boost_list[boostname][r] = {};
  +
for (var attr in boost_list[boostname]['*']) {
  +
boost_list[boostname][r][attr] = boost_list[boostname]['*'][attr]=='*' ? r : boost_list[boostname]['*'][attr];
  +
}
  +
}
  +
delete boost_list[boostname]['repl'];
  +
delete boost_list[boostname]['*'];
  +
}
  +
//process the form
  +
if (boostname=='Helmet' || boostname=='Martial arts') {
  +
hero_setup.appendChild(document.createElement('hr'));
  +
}
  +
var attr_row = document.createElement('div');
  +
attr_row.innerHTML = (icons[boostname] ? icons[boostname]+' ' : '')+boostname+': ';
  +
var attr_sel = document.createElement('select');
  +
attr_sel.id = boostname;
  +
attr_sel.addEventListener('change', fillHeroStats);
  +
//introduce list elements
  +
for (var boost_level in boost_list[boostname]) {
  +
var option = document.createElement('option');
  +
option.value = boost_level;
  +
option.innerHTML = boost_level!=0 ? boost_level : 'no';
  +
attr_sel.appendChild(option);
  +
}
  +
attr_row.appendChild(attr_sel);
  +
//icon placeholder
  +
var attr_sel_pic = document.createElement('span');
  +
attr_sel_pic.id = boostname+'-pic';
  +
attr_row.appendChild(attr_sel_pic);
  +
//atribute ready
  +
hero_setup.appendChild(attr_row);
  +
}
  +
//check if extended enemy data is available (replaces hardcoded table)
  +
var levels = [];
  +
if (document.getElementById('foestats')) {
  +
var entries = document.getElementById('foestats').innerHTML.split('~');
  +
enemy_list = [];
  +
for (e in entries) {
  +
if (entries[e]) {
  +
var fields = entries[e].split("|");
  +
var ename = fields[0].split(' - ');
  +
levels[ename[0]] = 1;
  +
var enemy = {name: ename[1]+' - '+ename[0], hp: fields[1], dmg: fields[2], def: fields[3], ap: fields[4], skills: fields[5], image: fields[6]};
  +
enemy_list.push(enemy);
  +
}
  +
}
  +
}
  +
//enemy selection form
  +
var enemy_selection = document.getElementById('e_defi');
  +
enemy_selection.innerHTML+= '<div style="'+tipstyle+'">Pick an opponent from the list of known enemies.<br>List may be filtered by selecting dungeon level.</div>';
  +
//level selection dropdown (optional)
  +
if (levels) {
  +
var levelselect = document.createElement('select');
  +
var opt = document.createElement('option');
  +
opt.value = "";
  +
opt.innerHTML = "- any -";
  +
levelselect.appendChild(opt);
  +
for (l in levels) {
  +
var opt = document.createElement('option');
  +
opt.value = l;
  +
opt.innerHTML = l;
  +
levelselect.appendChild(opt);
  +
}
  +
levelselect.addEventListener('change', filterEnemyList);
  +
levelselect.addEventListener('click', filterEnemyList);
  +
enemy_selection.appendChild(levelselect);
  +
}
  +
//enemy selection dropdown
  +
var enemyselect = document.createElement('select');
  +
enemyselect.id = "enemylist";
  +
for (var f in enemy_list) {
  +
var opt = document.createElement('option');
  +
opt.value = f;
  +
opt.innerHTML = enemy_list[f].name;
  +
enemyselect.appendChild(opt);
  +
}
  +
enemyselect.addEventListener('click', fillEnemyStats);
  +
enemyselect.addEventListener('change', fillEnemyStats);
  +
enemy_selection.appendChild(enemyselect);
  +
enemy_selection.appendChild(document.createElement('br'));
  +
enemy_selection.appendChild(document.createElement('br'));
  +
//quick fill
  +
opt.setAttribute("selected","selected");
  +
levelselect.click();
  +
if (window.location.search) {
  +
var autoenemy = decodeURI(window.location.search.split('=')[1]).replaceAll('+',' ');
  +
var elist = document.getElementById("enemylist").options;
  +
var lastshown = null;
  +
for (option in elist) {
  +
elist[option].selected = '';
  +
if (elist[option].innerHTML==autoenemy) {
  +
lastshown = elist[option];
  +
break;
  +
}
  +
}
  +
if (lastshown) {
  +
lastshown.selected = "selected"
  +
lastshown.click();
  +
}
  +
}
  +
fillHeroStats();
  +
}
  +
  +
/* above combat simulator is now executed on a page that is ready to accept it */
  +
  +
if (document.getElementById("combat_calc")) {
  +
setupCombatForm("combat_calc");
 
}
 
}

Latest revision as of 21:20, 21 February 2024

/* Any JavaScript here will be loaded for all users on every page load. */

//Changes every output cell in the table to "0" or "".
function delete_table(){
	document.getElementById("xp").innerHTML = "0";
	document.getElementById("coin").innerHTML = "0";
	document.getElementById("ruby").innerHTML = "0";
	document.getElementById("item1").innerHTML = "0";
	document.getElementById("item2").innerHTML = "0";
	document.getElementById("bt_ram").innerHTML = "0";
	document.getElementById("tr_map").innerHTML = "0";
	document.getElementById("unlocks1").innerHTML = "";
	document.getElementById("unlocks2").innerHTML = "";
	document.getElementById("unlocks3").innerHTML = "";
	document.getElementById("unlocks4").innerHTML = "";
	document.getElementById("unlocks5").innerHTML = "";
	document.getElementById("add_reward1").innerHTML = "";
	document.getElementById("add_reward2").innerHTML = "";
	document.getElementById("add_reward3").innerHTML = "";
}
//Calculates rewards for levels on page "Levelling".
function calculate() {
	var level = document.getElementById("level").value;
	//If the input is not a number or if the number is not between 2 and 1000, clears the table.
	if(isNaN(level)){
    	document.getElementById("wrong_number").innerHTML = "Please enter a number.";
		delete_table();
		return;
        }
	if (level < 2){
		document.getElementById("wrong_number").innerHTML = "You have enter a number smaller than 2.";
		delete_table();
		return;
	}
	if (level > 1000){
		document.getElementById("wrong_number").innerHTML = "You have enter a number bigger than 1000.";
		delete_table();
		return;
	}
	document.getElementById("level_display").innerHTML = level;
	document.getElementById("wrong_number").innerHTML = "";
	var xp = 1000, ruby = 1, bt_ram = 1, tr_map = 3;
	var items1 = [
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/f/f0/Arrows.png/revision/latest?cb=20210710185924"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/b/b9/Fan.png/revision/latest?cb=20210710185840"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Shuriken.png/revision/latest?cb=20210710190109"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/e/e9/Katana.png/revision/latest?cb=20210710190010"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/6/67/Spikes_%28Makibishi%29.png/revision/latest?cb=20210710190757"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/7/7c/Boomerang.png/revision/latest?cb=20210710190854"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/3/31/Petard.png/revision/latest?cb=20210710190156"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/c/ce/Bomb_%28Horoku%29.png/revision/latest?cb=20210710190341"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/c/c9/Steel.png/revision/latest?cb=20210710193716"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/a/a7/Iron_sand.png/revision/latest?cb=20210710194025"],
		["2","https://static.wikia.nocookie.net/nonograms-katana/images/6/6d/Sushi.png/revision/latest?cb=20210710194303"],
		["1","https://static.wikia.nocookie.net/nonograms-katana/images/8/83/Mortar.png/revision/latest?cb=20210307192837"]];
	var items2 = [
		["0",""],
		["0",""],
		["0",""],
		["0",""],
		["0",""],
		["0",""],
		["0",""],
		["0",""],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/4/4f/Charcoal.png/revision/latest?cb=20210710193800"],
		["5","https://static.wikia.nocookie.net/nonograms-katana/images/9/92/Chemicals.png/revision/latest?cb=20210710194109"],
		["0",""],
		["0",""]];
	//Here are listed when buildings, classes (character), skills (character) and ship mission types unlock.
	var unlocks = [["Workshop lvl. 1"],
		/*lvl. 3*/	["Shop lvl. 1","Class: Warrior"],
		/*lvl. 4*/	["Pagoda lvl. 1"],
		/*lvl. 5*/	["Warehouse lvl. 1"],
		/*lvl. 6*/	["Alchemist's Hut lvl. 1","Class: Wizard"],
		/*lvl. 7*/	["Field lvl. 1","Pagoda lvl. 2","Skill: Logistician lvl. 1","Skill: Weapon Collector lvl. 1","Skill: Treasure Hunter lvl. 1"],
		/*lvl. 8*/	["Furnace lvl. 1","Food Stall lvl. 1"],
		/*lvl. 9*/	["Smithy lvl. 1","Windmill lvl. 1","Class: Rogue"],
		/*lvl. 10*/	["Dungeon lvl. 1","Gong lvl. 1","Pagoda lvl. 3","Skill: Logistician lvl. 2","Skill: Athlete lvl. 1","Skill: Antiquarian lvl. 1"],
		/*lvl. 11*/	["Lumber Mill lvl. 1","Skill: Intellectual lvl. 1"],
		/*lvl. 12*/	["Garden lvl. 1","Class: Monk"],
		/*lvl. 13*/	["Rock Garden lvl. 1","Skill: Logistician lvl. 3","Skill: Weapon Collector lvl. 2","Skill: Treasure Hunter lvl. 2"],
		/*lvl. 14*/	["Pagoda lvl. 4"],
		/*lvl. 15*/	["Chicken Coop lvl. 1","Class: Geologist","Skill: Athlete lvl. 2"],
		/*lvl. 16*/	["Skill: Logistician lvl. 4","Skill: Antiquarian lvl. 2"],
		/*lvl. 17*/	["Skill: Intellectual lvl. 2"],
		/*lvl. 18*/	["Pagoda lvl. 5","Class: Archeologist"],
		/*lvl. 19*/	["Skill: Logistician lvl. 5","Skill: Weapon Collector lvl. 3","Skill: Treasure Hunter lvl. 3"],
		/*lvl. 20*/	["Onsen lvl. 1","Dungeon lvl. 2","Skill: Athlete lvl. 3"],
		/*lvl. 21*/	["Coffee Bonsai lvl. 1","Class: Samurai","Skill: Gardener lvl. 1","Skill: Rock Garden Contemplator lvl. 1"],
		/*lvl. 22*/	["Pier lvl. 1","Ship lvl. 1","Skill: Carpenter lvl. 1","Skill: Metallurgist lvl. 1"],
		/*lvl. 23*/	["Pagoda lvl. 6","Skill: Mechanic lvl. 1","Skill: Blacksmith lvl. 1","Ship: Exploring"],
		/*lvl. 24*/	["Food Stall lvl. 2","Class: Ninja","Skill: Alchemist lvl. 1","Ship: Fishing"],
		/*lvl. 25*/	["Skill: Athlete lvl. 4","Ship: Prospecting"],
		/*lvl. 26*/	["Skill: Gardener lvl. 2","Skill: Rock Garden Contemplator lvl. 2","Skill: Boatswain lvl. 1","Ship: Patrolling"],
		/*lvl. 27*/	["Class: Adventurer","Skill: Carpenter lvl. 2","Skill: Metallurgist lvl. 2"],
		/*lvl. 28*/	["Pagoda lvl. 7","Skill: Mechanic lvl. 2","Skill: Blacksmith lvl. 2"],
		/*lvl. 29*/	["Skill: Alchemist lvl. 2"],
		/*lvl. 30*/	["Bridge lvl. 1","Dungeon lvl. 3","Caravan lvl. 1","Class: Scientist","Skill: Athlete lvl. 5"],
		/*lvl. 31*/	["Outpost lvl. 1","Skill: Boatswain lvl. 2"],
		/*lvl. 32*/	["Alchemist's Hut lvl. 6","Tailor lvl. 1","Skill: Carpenter lvl. 3","Skill: Metallurgist lvl. 3"],
		/*lvl. 33*/	["Skill: Mechanic lvl. 3","Skill: Blacksmith lvl. 3"],
		/*lvl. 34*/	["Skill: Alchemist lvl. 3","Skill: Cameleer lvl. 1"],
		/*lvl. 35*/	["Skill: Athlete lvl. 6","Skill: Intellectual lvl. 3"],
		/*lvl. 36*/	[""],
		/*lvl. 37*/	[""],
		/*lvl. 38*/	[""],
		/*lvl. 39*/	["Skill: Cameleer lvl. 2"],
		/*lvl. 40*/	["Dungeon lvl. 4","Airship lvl. 1"],
		/*lvl. 41*/	[""],
		/*lvl. 42*/	[""],
		/*lvl. 43*/	[""],
		/*lvl. 44*/	["Skill: Aeronaut lvl. 1"],
		/*lvl. 45*/	[""],
		/*lvl. 46*/	[""],
		/*lvl. 47*/	[""],
		/*lvl. 48*/	[""],
		/*lvl. 49*/	["Skill: Aeronaut lvl. 2"],
		/*lvl. 50*/	["Dungeon lvl. 5"]];
	
	//Images for additional rewards.
	var firework = "https://static.wikia.nocookie.net/nonograms-katana/images/2/24/Firework.png/revision/latest?cb=20211025160230";
	var ramen = "https://static.wikia.nocookie.net/nonograms-katana/images/f/f8/Ramen.png/revision/latest?cb=20210614184327";
	var curry = "https://static.wikia.nocookie.net/nonograms-katana/images/d/dd/Curry.png/revision/latest?cb=20210716171827";
	var date_cake = "https://static.wikia.nocookie.net/nonograms-katana/images/1/12/Date_cake.png/revision/latest?cb=20211025160247";
	var kimono = "https://static.wikia.nocookie.net/nonograms-katana/images/8/85/Kimono.png/revision/latest?cb=20211026102346";
	var ninja_suit = "https://static.wikia.nocookie.net/nonograms-katana/images/3/3d/Ninja_suit.png/revision/latest?cb=20211026102357";
	var samurai_armor = "https://static.wikia.nocookie.net/nonograms-katana/images/5/51/Samurai_armor.png/revision/latest?cb=20211026102409";
	//Additional rewards for levels: 30, 50, 80 and 100 (and 150, 200, 250, etc.).
	var add_level = [30, 50, 80, 100];
	var add_rewards = [["3", firework, "0", "", "0", ""],
						["1", ramen, "1", curry, "1", date_cake],
						["1", kimono, "1", ninja_suit, "1", samurai_armor],
						["3", firework, "1", date_cake, "1", samurai_armor]];
	
	//Calculates experience.
	for (i = 2; i < level; i++) {
		xp += i*1000; 
	}

	//Logic for Rubies.
	if (level % 5 === 0) {
		ruby = 2;
	}
	if (level % 10 === 0) {
		ruby = 3;
	}

	//Calculates first and second item rewards. "n" is the number of item in the array.
	var n = (level-2)%12;
	
	//Logic for Treasure map fragments.
	if (level == 5) {
		tr_map = 5;
	}
	
	//Adds commas if the xp number is larger than 3 digits.
	var p = 0;
	var xpArray = xp.toString(10).split("");
	for (k = 3; k < xpArray.length-p; k += 3){
		xpArray.splice(-(k+p),0,",");
		p += 1;
	}
	xp = xpArray.join("");
	
	//Displays everything in the table.
	document.getElementById("xp").innerHTML = xp;
	
	var coins = level*2;
	if (coins > 200){
		coins = 200;
	}
	document.getElementById("coin").innerHTML = coins + " x ";
	var imgCoin = document.createElement("img");
	imgCoin.src = "https://static.wikia.nocookie.net/nonograms-katana/images/6/6d/Coin.png/revision/latest?cb=20210710184706";
	imgCoin.width = "30";
	imgCoin.height = "30";
	document.getElementById("coin").appendChild(imgCoin);
	
	document.getElementById("ruby").innerHTML = ruby + " x ";
	var imgRuby = document.createElement("img");
	imgRuby.src = "https://static.wikia.nocookie.net/nonograms-katana/images/a/a9/Ruby.png/revision/latest?cb=20210710184829";
	imgRuby.width = "30";
	imgRuby.height = "30";
	document.getElementById("ruby").appendChild(imgRuby);
	
	document.getElementById("item1").innerHTML = items1[n][0] + " x ";
	var imgItem1 = document.createElement("img");
	imgItem1.src = items1[n][1];
	imgItem1.width = "30";
	imgItem1.height = "30";
	document.getElementById("item1").appendChild(imgItem1);
	
	if (n == 8 || n == 9){
		document.getElementById("item2").innerHTML = items2[n][0] + " x ";
		var imgItem2 = document.createElement("img");
		imgItem2.src = items2[n][1];
		imgItem2.width = "30";
		imgItem2.height = "30";
		document.getElementById("item2").appendChild(imgItem2);
	} else {
		document.getElementById("item2").innerHTML = "0";
	}
	
	if (level > 13) {
		document.getElementById("bt_ram").innerHTML = bt_ram + " x ";
		var imgBTram = document.createElement("img");
		imgBTram.src = "https://static.wikia.nocookie.net/nonograms-katana/images/2/2f/Battering_ram_%28Kikkosha%29.png/revision/latest?cb=20210710192019";
		imgBTram.width = "30";
		imgBTram.height = "30";
		document.getElementById("bt_ram").appendChild(imgBTram);
	} else {
		document.getElementById("bt_ram").innerHTML = "0";
	}
	
	if (level > 4) {
		document.getElementById("tr_map").innerHTML = tr_map + " x ";
		var imgTRmap = document.createElement("img");
		imgTRmap.src = "https://static.wikia.nocookie.net/nonograms-katana/images/9/9b/Treasure_map_fragment_lvl._1.png/revision/latest?cb=20210710194412";
		imgTRmap.width = "30";
		imgTRmap.height = "30";
		document.getElementById("tr_map").appendChild(imgTRmap);
	} else {
		document.getElementById("tr_map").innerHTML = "0";
	}
	
	//Writes unlockables into the table.
	for (j = 0; j < 6; j += 1){
		try {
			if (unlocks[level-2][j]){
				document.getElementById("unlocks"+(j+1)).innerHTML = unlocks[level-2][j];
			} else {
				document.getElementById("unlocks"+(j+1)).innerHTML = "";
			}
		}
		catch (TypeError){
			document.getElementById("unlocks"+(j+1)).innerHTML = "";
		}
		
	}

	if (level == 80){
		document.getElementById("unlocks1").innerHTML = "Class: Zen Master";
	}
	
	//This helps with calculating additional rewards.
	var ar = -1;
	for (i = 0; i < add_level.length; i++){
		if (level == add_level[i]){
			var ar = i;
		}
	}
	//Displays additional rewards for jubilee levels.
	if (ar != -1){
		document.getElementById("add_reward1").innerHTML = add_rewards[ar][0] + " x ";
		var imgAddItem1 = document.createElement("img");
		imgAddItem1.src = add_rewards[ar][1];
		imgAddItem1.width = "30";
		imgAddItem1.height = "30";
		document.getElementById("add_reward1").appendChild(imgAddItem1);
		
		if (add_rewards[ar][2] != "0"){
			document.getElementById("add_reward2").innerHTML = add_rewards[ar][2] + " x ";
			var imgAddItem2 = document.createElement("img");
			imgAddItem2.src = add_rewards[ar][3];
			imgAddItem2.width = "30";
			imgAddItem2.height = "30";
			document.getElementById("add_reward2").appendChild(imgAddItem2);
		} else {
			document.getElementById("add_reward2").innerHTML = "0";
		}
		
		if (add_rewards[ar][4] != "0"){
			document.getElementById("add_reward3").innerHTML = add_rewards[ar][4] + " x ";
			var imgAddItem3 = document.createElement("img");
			imgAddItem3.src = add_rewards[ar][5];
			imgAddItem3.width = "30";
			imgAddItem3.height = "30";
			document.getElementById("add_reward3").appendChild(imgAddItem3);
		} else {
			document.getElementById("add_reward3").innerHTML = "0";
		} 
	
	//Displays additional rewards for levels above 150.
	} else if (level%50 == 0 && level >= 150) {
		document.getElementById("add_reward1").innerHTML = add_rewards[3][0] + " x ";
		var imgAddItem1 = document.createElement("img");
		imgAddItem1.src = add_rewards[3][1];
		imgAddItem1.width = "30";
		imgAddItem1.height = "30";
		document.getElementById("add_reward1").appendChild(imgAddItem1);
		
		document.getElementById("add_reward2").innerHTML = add_rewards[3][2] + " x ";
		var imgAddItem2 = document.createElement("img");
		imgAddItem2.src = add_rewards[3][3];
		imgAddItem2.width = "30";
		imgAddItem2.height = "30";
		document.getElementById("add_reward2").appendChild(imgAddItem2);
		
		document.getElementById("add_reward3").innerHTML = add_rewards[3][4] + " x ";
		var imgAddItem3 = document.createElement("img");
		imgAddItem3.src = add_rewards[3][5];
		imgAddItem3.width = "30";
		imgAddItem3.height = "30";
		document.getElementById("add_reward3").appendChild(imgAddItem3);
	} else {
		document.getElementById("add_reward1").innerHTML = "0";
		document.getElementById("add_reward2").innerHTML = "0";
		document.getElementById("add_reward3").innerHTML = "0";
	}
}

//Changes every output cell in the table to "0" or "".
function delete_table_m(){
	document.getElementById("mosaic").innerHTML = "#0";
	document.getElementById("collected").innerHTML = "0";
	document.getElementById("needed").innerHTML = "0";
	document.getElementById("percent").innerHTML = "0";
}

//Calculates how many fragments are still needed to complete a mosaic, plus some other useful information.
function mosaic_calculator_f(){
	var mosaic_sizes = [368, 640, 640, 640, 1280, 2560, 2560, 2560, 2560, 2560];
	var mosaics_f = [0];
	var fragment_counter = 0;
	for (i = 0; i < mosaic_sizes.length; i++){
		fragment_counter = fragment_counter + mosaic_sizes[i];
		mosaics_f.push(fragment_counter);
	}
	//var mosaics_f = [0, 368, 1008, 1648, 2288, 3568, 6128, 8688, 11248, 13808, 16368];
	
	var max_fragments = mosaics_f[mosaics_f.length - 1];
	var fragments = document.getElementById("fragments").value;
	
	//If the input is not a number or if the number is not between 0 and last mosaic fragment, clears the table.
	if(isNaN(fragments)){
    	document.getElementById("wrong_number").innerHTML = "Please enter a number.";
		delete_table_m();
		return;
        }
	if (fragments < 0){
		document.getElementById("wrong_number").innerHTML = "You have enter a number smaller than 0.";
		delete_table_m();
		return;
	}
	if (fragments > max_fragments){
		document.getElementById("wrong_number").innerHTML = "You have enter a number bigger than " + max_fragments + '.';
		delete_table_m();
		return;
	}
	if (fragments == max_fragments){
		document.getElementById("wrong_number").innerHTML = "Congratulations, you have completed all mosaics.";
		delete_table_m();
		return;
	}
	document.getElementById("wrong_number").innerHTML = "";
	
	//Logic of the calculator.
	for (i = 1; i < mosaics_f.length; i++){
		if (fragments < mosaics_f[i]){
			document.getElementById("mosaic").innerHTML = "#" + i;
			var collected = document.getElementById("collected").innerHTML = fragments - mosaics_f[i-1];
			document.getElementById("needed").innerHTML = mosaics_f[i] - fragments;
			document.getElementById("percent").innerHTML = Math.round((collected/(mosaics_f[i] - mosaics_f[i-1])) * 10000)/100 + "%";
			break;
		}
	}
}

//Creates the input box and button on page "Levelling".
if (mw.config.get("wgPageName") === "Levelling") {
	var inputBox = document.createElement("div");
	var input = document.createElement("input");
	input.id = "level";
	var getAnswer = document.createElement("button");
	getAnswer.innerHTML = "Calculate"; 
	getAnswer.id = "myBtn";
	getAnswer.addEventListener("click", calculate); 
	inputBox.appendChild(input);
	inputBox.appendChild(getAnswer);
	inputBox.addEventListener("keyup", function(event) {
		if (event.keyCode === 13) {
			event.preventDefault();
			document.getElementById("myBtn").click();
		}
	});
	document.getElementById("reward_calculator").appendChild(inputBox); 
}

//Creates the input box and button on page "Mosaic".
if (mw.config.get("wgPageName") === "Mosaic") {
	var inputBox = document.createElement("div");
	var input = document.createElement("input");
	input.id = "fragments";
	var getAnswer = document.createElement("button");
	getAnswer.innerHTML = "Calculate"; 
	getAnswer.id = "myBtn";
	getAnswer.addEventListener("click", mosaic_calculator_f); 
	inputBox.appendChild(input);
	inputBox.appendChild(getAnswer);
	inputBox.addEventListener("keyup", function(event) {
		if (event.keyCode === 13) {
			event.preventDefault();
			document.getElementById("myBtn").click();
		}
	});
	document.getElementById("mosaic_calculator").appendChild(inputBox); 
}



/* the code below is needed for combat simulation */

var food_effects = { Ambrosia: {hp:30}, Onigiri:{hp:10}, Flatbread:{ep:10}, Bun:{hp:15,ep:5}, Muffin:{hp:15,ep:7}, Bento:{hp:5,ep:15}, Pasta:{hp:7,ep:20}, Baklava:{hp:12,ep:12}, Eggs:{hp:17,ep:5}, PoHP1:{hp:20}, PoHP2:{hp:25}, PoEP1:{ep:20} }

var boost_list = {
                    'Level':        { 'repl':26, '*':{'hp':'*','ep':'*'} },
                    'Sword':        { '0':{}, '1': {'dmg':3}, '2': {'dmg':5}, '3': {'dmg':7}, '4': {'dmg':9} },
                    'Armor':        { '0':{}, '1': {'def':2}, '2': {'def':4}, '3': {'def':6}, '4': {'def':8,'dmg':1,'ep':10} },
                    'Shield':       { '0':{}, '1': {'def':1}, '2': {'def':2}, '3': {'def':3}, '4': {'def':4,'c2r':10} },
                    'Ring':         { '0':{}, '1': {'dmg':1}, '2': {'dmg':2}, '3': {'dmg':3}, '4': {'dmg':4}, '4+': {'dmg':4,'ep':5} },
                    'Martial arts': { '0':{}, '1': {'dmg':1}, '2': {'dmg':2}, '3': {'dmg':3} },
                    'Hardening':    { '0':{}, '1': {'def':1}, '2': {'def':2} },
                    'Equipment preparation':{ '0':{}, '1': {'sck':1}, '2': {'sck':2} },
                    'Agility':      { '0':{}, '1': {'ap':1} },
                    'Smashing blow':{ '0':{}, '1': {}, '2': {} },
                    'Helmet':       { '0':{}, '1':{'hp':5} },
                    'Dagger':       { '0':{}, '1':{'c2c':5} }
                };

var presets = {
                     1: {Sword: 0, Armor: 0, Shield: 0, Ring: 0, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':0 },
                     3: {Sword: 0, Armor: 0, Shield: 0, Ring: 0, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':1 },
                     5: {Sword: 1, Armor: 1, Shield: 1, Ring: 1, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':1 },
                     6: {Sword: 1, Armor: 1, Shield: 1, Ring: 1, 'Martial arts': 0, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':2 },
                     9: {Sword: 1, Armor: 1, Shield: 1, Ring: 1, 'Martial arts': 1, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':2 },
                    10: {Sword: 2, Armor: 2, Shield: 2, Ring: 2, 'Martial arts': 1, 'Equipment preparation': 0, Hardening: 0, Agility: 0, 'Smashing blow':2 },
                    12: {Sword: 2, Armor: 2, Shield: 2, Ring: 2, 'Martial arts': 1, 'Equipment preparation': 1, Hardening: 1, Agility: 0, 'Smashing blow':2 },
                    15: {Sword: 3, Armor: 3, Shield: 3, Ring: 3, 'Martial arts': 2, 'Equipment preparation': 1, Hardening: 1, Agility: 1, 'Smashing blow':2 },
                    18: {Sword: 3, Armor: 3, Shield: 3, Ring: 3, 'Martial arts': 2, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 },
                    20: {Sword: 4, Armor: 4, Shield: 4, Ring: 4, 'Martial arts': 2, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 },
                    21: {Sword: 4, Armor: 4, Shield: 4, Ring: 4, 'Martial arts': 3, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 },
                    26: {Sword: 4, Armor: 4, Shield: 4, Ring: 4, 'Martial arts': 3, 'Equipment preparation': 2, Hardening: 2, Agility: 1, 'Smashing blow':2 }
                };

var enemy_list = [
                    {name: 'Shapeshifter 3A-3C',      hp: 27,  dmg: 8,  def: 5,  ap: 6, skills: '*Shapeshifter*'},
                    {name: 'Orc chieftain (3A boss)', hp: 55,  dmg: 9,  def: 5,  ap: 4},
                    {name: 'Orc warlord (3B boss)',   hp: 65,  dmg: 9,  def: 5,  ap: 4},
                    {name: 'Bone dragon (3C boss)',   hp: 85,  dmg: 9,  def: 5,  ap: 4},
                    {name: 'Shapeshifter 4A-4C',      hp: 36,  dmg: 12, def: 9,  ap: 6, skills: '*Shapeshifter*'},
                    {name: 'Leviathan (4A boss)',     hp: 84,  dmg: 14, def: 9,  ap: 4},
                    {name: 'Mynd flyer (4B boss)',    hp: 104, dmg: 14, def: 9,  ap: 6},
                    {name: 'Eye tyrant (4C boss)',    hp: 124, dmg: 15, def: 9,  ap: 4},
                    {name: 'Demon kingpin (5A boss)', hp: 130, dmg: 18, def: 12, ap: 4},
                    {name: 'Demon lord (5B boss)',    hp: 170, dmg: 19, def: 13, ap: 4},
                    {name: 'Bone dragon (5C quest)',  hp: 230, dmg: 19, def: 13, ap: 4, image: 'a/a5/Foe-Bone_Dragon.png'},
                    {name: 'The dragon (5C boss)',    hp: 230, dmg: 21, def: 14, ap: 4, image: '9/92/Foe-Evil_dragon%28boss5C%29.png'}
                ];

var icons = {
                'Sword-1':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/a4/Sword_for_a_hero_lvl._1.png">',
                'Sword-2':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/b/bc/Sword_for_a_hero_lvl._2.png">',
                'Sword-3':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/36/Sword_for_a_hero_lvl._3.png">',
                'Sword-4':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/0/09/Sword_for_a_hero_lvl._4.png">',
                'Armor-1':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/f/f3/Armor_for_a_hero_lvl._1.png">',
                'Armor-2':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/a6/Armor_for_a_hero_lvl._2.png">',
                'Armor-3':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/0/05/Armor_for_a_hero_lvl._3.png">',
                'Armor-4':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/a3/Armor_for_a_hero_lvl._4.png">',
                'Shield-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/6/6c/Shield_for_a_hero_lvl._1.png">',
                'Shield-2': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/9/9f/Shield_for_a_hero_lvl._2.png">',
                'Shield-3': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/c/ca/Shield_for_a_hero_lvl._3.png">',
                'Shield-4': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/8/80/Shield_for_a_hero_lvl._4.png">',
                'Ring-1':   '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/e/eb/Ring_for_a_hero_lvl._1.png">',
                'Ring-2':   '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/18/Ring_for_a_hero_lvl._2.png">',
                'Ring-3':   '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/b/bb/Ring_for_a_hero_lvl._3.png">',
                'Ring-4':   '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/10/Ring_for_a_hero_lvl._4.png">',
                'Ring-4+':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Ring_for_a_hero_lvl._4%2B.png">',
                'Dagger-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/4/45/Dagger.png">',
                'Helmet-1': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/37/Helmet.png">',
                'HP':       '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/31/Dungeon_-_Health.png">',
                'EP':       '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/1e/Dungeon_-_Energy.png">',
                'AP':       '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/8/84/Dungeon_-_Action_points.png">',
                'DEF':      '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/a/ac/Dungeon_-_Defense.png">',
                'DMG':      '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/5/59/Dungeon_-_Damage.png">',
                'sck':      '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/6/61/Sack.png">',
                'Ambrosia': '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/e/e9/Potion_Ambrosia.png">',
                'Onigiri':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/f/f3/Onigiri.png">',
                'Flatbread':'<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/4/4f/Flatbread.png">',
                'Bun':      '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/9/9a/Cherry_bun.png">',
                'Muffin':   '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/1/1d/Muffin.png">',
                'Bento':    '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/34/Mushroom_rice_%28Bento%29.png">',
                'Pasta':    '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/b/bf/Porcini_pasta.png">',
                'Baklava':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/34/Baklava.png">',
                'Eggs':     '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/3f/Marinated_eggs.png">',
                'PoHP1':    '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/3/35/Potion_of_healing.png">',
                'PoHP2':    '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/f/f4/Potion_of_healing_lvl._2.png">',
                'PoEP1':    '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/7/72/Potion_of_energy.png">',
                'fortified':    '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/2/27/Poke.png">',
                'frenzied':     '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/d/d2/Potion_Berserker_rage.png">',
                'demoralized':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/8/8e/Demoralization.png">',
                'Smashing blow-1':  '<img align="top" height="20" src="https://static.wikia.nocookie.net/nonograms-katana/images/d/d4/Smashing_blow.png">',
                'c2c':      '',
                'c2r':      ''
            };

icons['Agility-1'] = icons['AP'];
icons['Hardening-1'] = icons['DEF'];
icons['Hardening-2'] = icons['DEF']+icons['DEF'];
icons['Martial arts-1'] = icons['DMG'];
icons['Martial arts-2'] = icons['DMG']+icons['DMG'];
icons['Martial arts-3'] = icons['DMG']+icons['DMG']+icons['DMG'];
icons['Equipment preparation-1'] = icons['sck'];
icons['Equipment preparation-2'] =icons['sck']+icons['sck'];
icons['Smashing blow-2'] = icons['Smashing blow-1']+icons['Smashing blow-1'];

function fillHeroFromPreset(event) {
    var id = event.srcElement.innerHTML;
    document.getElementById('Level').value = id;
    for (var boost in presets[id]) {
        var boost_level = presets[id][boost];
        document.getElementById(boost).value = boost_level;
    }
    fillHeroStats();
}

function fillHeroStats() {
    var attr = ['hp', 'ep','dmg','def','ap', 'sck', 'c2c', 'c2r'];
    //reset fields to their initial values
    for (var a in attr) {
        document.getElementById('h'+attr[a]).value = document.getElementById('h'+attr[a]).getAttribute('data-init');
    }
    //iterate fields
    var boost_fields = document.getElementById('h_defi').getElementsByTagName('select');
    for (var f=0; f<boost_fields.length; f++) {
        var boost_name = boost_fields[f].id;
        var boost_value = boost_fields[f].value;
        //show boost's icon
        var icon_ph = document.getElementById(boost_name+'-pic');
        var icon_tag = boost_name+'-'+boost_value
        icon_ph.innerHTML = ' '+( icons[icon_tag] ? icons[icon_tag] : '' );
        //add boost's value to the appropriate hero's stats
        var targets = boost_list[boost_name][boost_value];
        for (var t in targets) {
            var field = document.getElementById('h'+t);
            field.value = parseInt(field.value) + targets[t];
        }
    }
    //clear previous results
    document.getElementById('h_calc');
    document.getElementById('e_calc');
}

function filterEnemyList(event) {
    var level = event.srcElement.value;
    var elist = document.getElementById("enemylist").options;
    var lastshown = null;
    var beforelastshown = null;
    for (option in elist) {
        if (elist[option].innerHTML) {
            var show = (level=="" || elist[option].innerHTML.indexOf(" - "+level)>0);
            elist[option].style.display = show ? "" : "none";
            elist[option].selected = "";
            if (show) {
                beforelastshown = lastshown; 
                lastshown = elist[option];
            }
        }
    }
    //adjust selection to include only visible ones
    if (lastshown) {
        if (beforelastshown && (level=='1C' || level=='F2' || level=='F3' || level=='5C' || level=='')) {
            lastshown = beforelastshown;
        }
        lastshown.selected = "selected"
        lastshown.click();
    }
}

function fillEnemyStats(event) {
    var index = event.srcElement.value;
    var attr = ['hp','dmg','def','ap'];
    for (var a in attr) {
        document.getElementById('e'+attr[a]).value = enemy_list[index][attr[a]];
    }
    document.getElementById('hdemo').checked = enemy_list[index].skills && (enemy_list[index].skills.indexOf('*Shapeshifter*')>=0 || enemy_list[index].skills.indexOf('*Demoralization*')>=0);
    document.getElementById('epoke').checked = enemy_list[index].skills && (enemy_list[index].skills.indexOf('*Shielding*')>=0);
    //remove enemy's portrait
    if (document.getElementById('eimage')) {
        document.getElementById('eimage').remove();
    }
    //... and attach it again, if possible
    if (enemy_list[index].image) {
        var eimage = document.createElement('img');
        eimage.src = 'https://static.wikia.nocookie.net/nonograms-katana/images/'+enemy_list[index].image;
        eimage.style = 'width:150px;height:auto';
        eimage.id = 'eimage';
        document.getElementById('e_defi').appendChild(eimage);
    }
}

function calculateCombat() {
    //prepare food selection
    var es = parseInt(document.getElementById('hsck').value);
    var foodlist = { Onigiri:7+es, Flatbread:7+es, Bun:5+es, Muffin:5+es, Bento:5+es, Pasta:5+es, Baklava:7+es, Eggs:5+es, PoHP1:5+es, PoHP2:5+es, PoEP1:5+es, Ambrosia:1+es };
    for (var food in foodlist) {
        document.getElementById(food).setAttribute('data-limit', foodlist[food]);
    }
    var h_out = document.getElementById('h_calc');
    var e_out = document.getElementById('e_calc');
    //get hero stats and apply effects
    var hero = {};
    hero.hpmax = parseInt(document.getElementById('hhp').value);
    hero.epmax = parseInt(document.getElementById('hep').value);
    hero.apmax = parseInt(document.getElementById('hap').value);
    hero.dmg = parseInt(document.getElementById('hdmg').value);
    hero.def = parseInt(document.getElementById('hdef').value);
    if (document.getElementById('hpoke').checked) {
        hero.def+= 4;
    }
    if (document.getElementById('hdemo').checked) {
        hero.def = Math.floor(hero.def * 0.4);
    }
    if (document.getElementById('hberserk').checked) {
        hero.dmg = Math.floor(hero.dmg * 1.4);      //hero's berserk damage rounded down? not confirmed
        hero.apmax+= 2;
    }
    hero.spread = Math.floor(hero.dmg>=15 ? hero.dmg/5 : (hero.dmg>=12 ? 3 : 2));
    hero.critchance = parseInt(document.getElementById('hc2c').value);
    hero.critdmgratio = 2;
    hero.retaliatechance = parseInt(document.getElementById('hc2r').value);
    hero.log = document.getElementById('h_simlog');
    //get enemy stats and apply effects
    var enemy = {};
    enemy.hpmax = parseInt(document.getElementById('ehp').value);
    enemy.apmax = parseInt(document.getElementById('eap').value);
    enemy.dmg = parseInt(document.getElementById('edmg').value);
    enemy.def = parseInt(document.getElementById('edef').value);
    if (document.getElementById('epoke').checked) {
        enemy.def+= 4;
    }
    if (document.getElementById('edemo').checked) {
        enemy.def = Math.floor(enemy.def * 0.4);
    }
    enemy.spread = Math.floor(enemy.dmg>=15 ? enemy.dmg/5 : (enemy.dmg>=12 ? 3 : 2));
    enemy.critchance = parseInt(document.getElementById('hc2c').value);
    enemy.critdmgratio = 1.5;
    enemy.log = document.getElementById('e_simlog');
    //output calculations for the hero
    h_out.innerHTML = '<div><small>Effective AP: ' + hero.apmax + ', DEF: ' + hero.def + ', DMG: ' + hero.dmg + ' &#177;'+hero.spread+'</small></div>';
    var ddmgmin = Math.max( hero.dmg-hero.spread , 1);
    var ddmgmax = hero.dmg+hero.spread;
    var ddmgminc = hero.critdmgratio*ddmgmin;
    var ddmgmaxc = hero.critdmgratio*ddmgmax;
    h_out.innerHTML+= '<div>Damage delivered: ' + ddmgmin + '-' + ddmgmax + ' <small>(when critical: ' + ddmgminc + '-' + ddmgmaxc + ')</small></div>';
    var rdmgmin = Math.max(ddmgmin-enemy.def,1);
    var rdmgmax = Math.max(ddmgmax-enemy.def,1);
    var rdmgminc = Math.max(ddmgminc-enemy.def,2);
    var rdmgmaxc = Math.max(ddmgmaxc-enemy.def,2);
    h_out.innerHTML+= '<div>Damage to enemy: ' + rdmgmin + '-' + rdmgmax + ' <small>(when critical: ' + rdmgminc + '-' + rdmgmaxc + ')</small></div>';
    h_out.innerHTML+= '<div><b>Hits to kill the enemy: ' + Math.ceil(enemy.hpmax/rdmgmax) + '-' + Math.ceil(enemy.hpmax/rdmgmin) + '</b></div>';
    h_out.innerHTML+= '<div>(absolute minimum: ' + Math.ceil(enemy.hpmax/rdmgmaxc) + ')</div>';
    //output calculations for the enemy
    e_out.innerHTML = '<div><small>Effective AP: ' + enemy.apmax + ', DEF: ' + enemy.def + ', DMG: ' + enemy.dmg + ' &#177;'+enemy.spread+'</small></div>';
    ddmgmin = Math.max( enemy.dmg-enemy.spread , 1);
    ddmgmax = enemy.dmg+enemy.spread;
    ddmgminc = Math.floor(enemy.critdmgratio*ddmgmin);
    ddmgmaxc = Math.floor(enemy.critdmgratio*ddmgmax);
    e_out.innerHTML+= '<div>Damage delivered: ' + ddmgmin + '-' + ddmgmax + ' <small>(when critical: ' + ddmgminc + '-' + ddmgmaxc + ')</small></div>';
    rdmgmin = Math.max(ddmgmin-hero.def,1);
    rdmgmax = Math.max(ddmgmax-hero.def,1);
    rdmgminc = Math.max(ddmgminc-hero.def,2);
    rdmgmaxc = Math.max(ddmgmaxc-hero.def,2);
    e_out.innerHTML+= '<div>Damage to hero: ' + rdmgmin + '-' + rdmgmax + ' <small>(when critical: ' + rdmgminc + '-' + rdmgmaxc + ')</small></div>';
    e_out.innerHTML+= '<div><b>Hits to kill the hero: ' + Math.ceil(hero.hpmax/rdmgmax) + '-' + Math.ceil(hero.hpmax/rdmgmin) + '</b></div>';
    e_out.innerHTML+= '<div>(absolute minimum: ' + Math.ceil(hero.hpmax/rdmgmaxc) + ')</div>';
    //SIMULATE
    //assume hero's initiative, setup food reserves
    var attacker = hero;
    attacker.hp = attacker.hpmax;
    attacker.ep = attacker.epmax;
    attacker.ap = attacker.apmax;
    attacker.healing = document.getElementById('heal').checked;
    attacker.smashing = document.getElementById('sbuse').checked ? parseInt(document.getElementById('Smashing blow').value) : 0;
    attacker.food = {};    
    if (attacker.healing) {
        for (var fooditem in food_effects) {
            if (document.getElementById(fooditem).checked) {
                attacker.food[fooditem] = parseInt(document.getElementById(fooditem).getAttribute('data-limit'));
            }
        }
    }
    attacker.counter = 0;
    attacker.log.innerHTML = '';
    //setup enemy
    var defender = enemy;
    defender.hp = defender.hpmax;
    defender.ap = 0;
    defender.counter = 0;
    defender.log.innerHTML = '';
    //healing info
    if (attacker.healing) {
        var out = '<nobr>Food:'
        for (var food in attacker.food) {
            if (attacker.food[food]) {
                out+= ' '+attacker.food[food]+'x'+(icons[food]?icons[food]:food);
            }
        }
        out+= '</nobr><hr>';
        attacker.log.innerHTML+= out;
        defender.log.innerHTML+= 'unlimited '+icons['EP']+' and no food<hr>';
    }        
    //main loop
    var watchdog = 0;
    var roundno = 1;
    while (defender.hp>0 && attacker.hp>0 && watchdog<1000) {
        watchdog+= 1;
        //update stats, show results
        var alog = 'HP:'+attacker.hp+(attacker.epmax?', EP:'+attacker.ep:'')+', AP:'+attacker.ap;
        var dlog = 'HP:'+defender.hp+(defender.epmax?', EP:'+defender.ep:'')+', AP:'+defender.ap;
        //decision is being made
        var action = 'attack'; //default action to be taken
        //replenish health if necessary
        if (attacker.healing && attacker.hpmax-attacker.hp>=10) {
            //find the best food to use
            var bestheal = 0;
            for (var food in food_effects) {
                if (food!='Ambrosia' && food_effects[food].hp && attacker.food[food]>0 && (!food_effects[food].ep || food_effects[food].hp>bestheal) && attacker.hpmax>=attacker.hp+food_effects[food].hp*0.9) {
                    action = food;
                    bestheal = food_effects[food].hp;
                }
            }
        }
        //replenish energy if necessary
        if (attacker.healing && attacker.epmax && (attacker.smashing && attacker.ep<4 || attacker.ep<1)) {
            //find the best food to use
            for (var food in food_effects) {
                if (food_effects[food].ep && (!food_effects[food].hp || food_effects[food].hp<food_effects[food].ep) && attacker.food[food]>0 && attacker.epmax>=attacker.ep+food_effects[food].ep) {
                    action = food;
                }
            }
        }
        //use the food, if so decided
        if (action!="attack") {
            if (food_effects[action].hp) {
                attacker.hp = Math.min(attacker.hp+food_effects[action].hp, attacker.hpmax);
            }
            if (food_effects[action].ep) {
                attacker.ep = Math.min(attacker.ep+food_effects[action].ep, attacker.epmax);
            }
            attacker.ap-= 2;
            attacker.food[action]-= 1;
            alog+= ' => <b style="color:darkred">consumes</b> '+action+' ('+attacker.food[action]+' left)';
            dlog+= ' => (waits)';
        }
        //attack not possible - out of energy and no healing was possible?
        if (action=='attack' && attacker.epmax && (attacker.smashing && attacker.ep<4 || attacker.ep<1) ) {
            attacker.ap-= 3;
            attacker.ep+= 10;
            alog+= ' => <b style="color:goldenrod">Charge of motivation!</b>';
            dlog+= ' => (waits)';
            action = 'CoM';
        }
        //if no other action was taken, fight
        if (action=='attack') {
            //determine damage: base, delivered, received
            var effdmg = attacker.dmg + Math.floor(Math.random()*(attacker.spread+attacker.spread+1))-attacker.spread;
            var smashing = attacker.smashing && attacker.ep>=4 ? attacker.smashing : 0;
            var crit = smashing ? false : Math.random()*100<attacker.critchance; //normal crit is not possible when SB used
            var dmgdelivered = Math.floor(effdmg * (crit ? attacker.critdmgratio : 1) * (smashing ? 1+smashing*0.5 : 1));        //monster's crit damage rounded down? not confirmed
            var dmgreceived = Math.max(dmgdelivered - defender.def, (crit || smashing ? 2 : 1));
            //update stats
            attacker.counter+= 1;
            defender.hp-= dmgreceived;
            attacker.ap-= smashing ? 4 : 3;
            if (attacker.epmax) {
                attacker.ep-= smashing ? 4 : 1;
            }
            alog+= ' => <b>attacks</b> '+(smashing?' <b style="color:limegreen">SB L'+attacker.smashing+'</b>':'')+(crit?' <b style="color:orange">CRIT!</b>':'');
            dlog+= ' => gets hit for: '+dmgreceived;
            //counter-attack?
            if (defender.retaliatechance && Math.random()*100<defender.retaliatechance) {
                dmgreturned = Math.floor(3+3*Math.random());
                dmgreturned = Math.min(dmgreturned, Math.floor(attacker.hpmax*0.25), attacker.hp-1);
                alog+= ', gets counter-hit for: '+dmgreturned;
                attacker.hp-= dmgreturned;
                dlog+= ', <b style="color:blue">counter-attacks</b>';
            }
        }
        //check if still alive (or rescue if possible)
        if (defender.hp<=0) {
            if (defender.healing && defender.food.Ambrosia>0) {
                defender.hp = Math.min(30, defender.hpmax);
                defender.food.Ambrosia-= 1;
                dlog+= ' <b style="color:red">Ambrosia</b> ('+defender.food.Ambrosia+' left)';
            }
            else {
                dlog+= ' <b style="color:magenta">FALLEN</b><br>- defeated in '+attacker.counter+' hit(s), '+roundno+' turn(s)';
            }
        }
        //update logs
        attacker.log.innerHTML+= '<div>'+alog+'</div>';
        defender.log.innerHTML+= '<div>'+dlog+'</div>';
        //when attacker is out of AP, switch sides
        if (attacker.ap<=0) {
            var swap = attacker;
            attacker = defender;
            defender = swap;
            attacker.ap+= attacker.apmax;
            roundno+= 1;
        }
    }
    //end of main loop
    if (hero.healing) {
        var out = '<hr><nobr>Left:';
        var anyleft = 0;
        for (var food in hero.food) {
            if (hero.food[food]) {
                anyleft+= 1;
                out+= ' '+hero.food[food]+'x'+(icons[food]?icons[food]:food);
            }
        }
        if (anyleft==0) {
            out+= ' NOTHING ';
        }
        out+= '</nobr>';
        hero.log.innerHTML+= out;
    }
}

function togglefood() {
    var foodsack = document.getElementById('foodsack');
    if (foodsack.style.display=='none') {
        foodsack.style.display = null;
    }
    else {
        foodsack.style.display = 'none';
    }
}

function setupCombatForm(placeholderId) {
    var target = document.getElementById(placeholderId);
    //general form structure
    var tipstyle = 'color:gray; margin:3px; font-style:italic; font-size: smaller; line-height:1';
    var table = document.createElement('table');
    table.border = 1;
    table.cellSpacing = 0;
    table.cellPadding = 2;
    table.innerHTML = '<tr valign="top"><td id="h_defi">Hero configuration:</td><td id="e_defi">Enemy selection:</td></tr>';
    table.innerHTML+= '<tr valign="top"><td id="h_stat"></td><td id="e_stat"></td></tr>';
    table.innerHTML+= '<tr valign="top"><td id="h_buff"></td><td id="e_buff"></td></tr>';
    var foodsack = '';
    for (var food in food_effects) {
        foodsack+= ' <input type="checkbox" id="'+food+'" data-limit="0" checked="checked">'+(icons[food]?icons[food]:food);
    }
    table.innerHTML+= '<tr><td colspan="2" align="left"><div style="'+tipstyle+'">Special algorithms may be applied to simulate using consumables/skills permitted, e.g. to replenish HP/EP.<br>This is not a part of the game engine, it acts as user would do and may be not optimal.</div><input type="checkbox" id="heal" />Allow using food<span id="foodsack" style="display:none">: '+foodsack+'</span><br><input type="checkbox" id="sbuse" />Use Smashing blow whenever possible</td></tr>';
    table.innerHTML+= '<tr><td colspan="2" align="center"><button id="emu_run">CALCULATE</button></td></tr>';
    table.innerHTML+= '<tr valign="top"><td id="h_calc"></td><td id="e_calc"></td></tr>';
    table.innerHTML+= '<tr valign="top" style="font-size: 66%"><td id="h_simlog"></td><td id="e_simlog"></td></tr>';
	target.appendChild(table);
    document.getElementById('heal').addEventListener('click', togglefood);    
    document.getElementById('emu_run').addEventListener('click', calculateCombat);    
    //stats forms
    document.getElementById('h_stat').innerHTML = '<div style="'+tipstyle+'">Enter/verify attributes of the hero.<br>These values are updated when gear/skils are selected above.</div>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hhp" data-init="19"/> '+icons['HP']+' HP &nbsp; &nbsp; &nbsp; <input size="1" id="hep" data-init="29"/> '+icons['EP']+' EP<br>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hdmg" data-init="5"/> '+icons['DMG']+' DMG<br>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hdef" data-init="2"/> '+icons['DEF']+' DEF<br>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hap" data-init="4"/> '+icons['AP']+' AP<br>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hc2c" data-init="5"/> '+icons['c2c']+' % chance to crit<br>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hc2r" data-init="0" /> '+icons['c2r']+' % chance to reflect damage<br>';
    document.getElementById('h_stat').innerHTML+= '<input size="1" id="hsck" data-init="0" /> '+icons['sck']+' extra space';
    document.getElementById('e_stat').innerHTML = '<div style="'+tipstyle+'">Enter/verify attributes of the enemy.<br>These values are updated when enemy is selected above.</div>';
    document.getElementById('e_stat').innerHTML+= '<input size="1" id="ehp"/> '+icons['HP']+' HP<br>';
    document.getElementById('e_stat').innerHTML+= '<input size="1" id="edmg"/> '+icons['DMG']+' DMG<br>';
    document.getElementById('e_stat').innerHTML+= '<input size="1" id="edef"/> '+icons['DEF']+' DEF<br>';
    document.getElementById('e_stat').innerHTML+= '<input size="1" id="eap"/> '+icons['AP']+' AP<br>';
    document.getElementById('e_stat').innerHTML+= '<input size="1" id="ec2c" value="5"/> '+icons['c2c']+' % chance to crit';
    //buffs forms
    document.getElementById('h_buff').innerHTML = '<div style="'+tipstyle+'">Declare special status of the hero - buffs and debuffs.<br>Some values may change when selecting an enemy.</div>';
    document.getElementById('h_buff').innerHTML+= '<input type="checkbox" id="hpoke"/>'+(icons['fortified']?icons['fortified']+' ':'')+'Hero used "Poke"<br><input type="checkbox" id="hberserk"/>'+(icons['frenzied']?icons['frenzied']+' ':'')+'Hero used "Berserker rage"<br><input type="checkbox" id="hdemo"/>'+(icons['demoralized']?icons['demoralized']+' ':'')+'Has been demoralized by enemy';
    document.getElementById('e_buff').innerHTML = '<div style="'+tipstyle+'">Declare special status of the enemy - buffs and debuffs.<br>Some values may change when selecting an enemy.</div>';
    document.getElementById('e_buff').innerHTML+= '<input type="checkbox" id="edemo"/>'+(icons['demoralized']?icons['demoralized']+' ':'')+'Has been demoralized by hero<br><input type="checkbox" id="epoke"/>'+(icons['DEF']?icons['DEF']+' ':'')+'Used/received defence boost';
    //hero setup form
    var hero_setup = document.getElementById('h_defi');
    //... first preset buttons...
    var preset_bar = document.createElement('div');
    preset_bar.innerHTML = '<div style="'+tipstyle+'">Pick a preset reflecting hero\'s level to quickly fill the form<br>with the best gear and skills available for that level.</div><small>Presets: </small>';
    for (var p in presets) {
        var p_btn = document.createElement('button');
        p_btn.innerHTML = p;
        p_btn.style = 'font-size: 8pt; padding: 0; margin: 1px';
        p_btn.addEventListener('click', fillHeroFromPreset);
        preset_bar.appendChild(p_btn);
    }
    hero_setup.appendChild(preset_bar);
    hero_setup.appendChild(document.createElement('hr'));
    var info2 = document.createElement('div');
    info2.style = tipstyle;
    info2.innerHTML = "Select/verify gear and skills your hero possesses.<br>These values are updated when preset is selected above.";
    hero_setup.appendChild(info2);
    //... then individual gear/skill entries
    for (var boostname in boost_list) {
        //first, unpack a short definition
        if (boost_list[boostname]['repl']) { 
            for (var r=1; r<=boost_list[boostname]['repl']; r++) {
                boost_list[boostname][r] = {};
                for (var attr in boost_list[boostname]['*']) {
                    boost_list[boostname][r][attr] = boost_list[boostname]['*'][attr]=='*' ? r : boost_list[boostname]['*'][attr];
                }
            }
            delete boost_list[boostname]['repl'];
            delete boost_list[boostname]['*'];
        }
        //process the form
        if (boostname=='Helmet' || boostname=='Martial arts') {
            hero_setup.appendChild(document.createElement('hr'));
        }
        var attr_row = document.createElement('div');
        attr_row.innerHTML = (icons[boostname] ? icons[boostname]+' ' : '')+boostname+': ';
        var attr_sel = document.createElement('select');
        attr_sel.id = boostname;
        attr_sel.addEventListener('change', fillHeroStats);
        //introduce list elements
        for (var boost_level in boost_list[boostname]) {
            var option = document.createElement('option');
            option.value = boost_level;
            option.innerHTML = boost_level!=0 ? boost_level : 'no';
            attr_sel.appendChild(option);
        }
        attr_row.appendChild(attr_sel);
        //icon placeholder
        var attr_sel_pic = document.createElement('span');
        attr_sel_pic.id = boostname+'-pic';
        attr_row.appendChild(attr_sel_pic);
        //atribute ready
        hero_setup.appendChild(attr_row);
    }
    //check if extended enemy data is available (replaces hardcoded table)
    var levels = [];
    if (document.getElementById('foestats')) {
        var entries = document.getElementById('foestats').innerHTML.split('~');
        enemy_list = [];
        for (e in entries) {
            if (entries[e]) {
                var fields = entries[e].split("|");
                var ename = fields[0].split(' - ');
                levels[ename[0]] = 1;
                var enemy = {name: ename[1]+' - '+ename[0], hp: fields[1], dmg: fields[2], def: fields[3], ap: fields[4], skills: fields[5], image: fields[6]};
                enemy_list.push(enemy);
            }
        }
    }
    //enemy selection form
    var enemy_selection = document.getElementById('e_defi');
    enemy_selection.innerHTML+= '<div style="'+tipstyle+'">Pick an opponent from the list of known enemies.<br>List may be filtered by selecting dungeon level.</div>';
    //level selection dropdown (optional)
    if (levels) {
        var levelselect = document.createElement('select');
        var opt = document.createElement('option');
        opt.value = "";
        opt.innerHTML = "- any -";
        levelselect.appendChild(opt);
        for (l in levels) {
            var opt = document.createElement('option');
            opt.value = l;
            opt.innerHTML = l;
            levelselect.appendChild(opt);
        }
        levelselect.addEventListener('change', filterEnemyList);
        levelselect.addEventListener('click', filterEnemyList);
        enemy_selection.appendChild(levelselect);
    }
    //enemy selection dropdown
    var enemyselect = document.createElement('select');
    enemyselect.id = "enemylist";
    for (var f in enemy_list) {
        var opt = document.createElement('option');
        opt.value = f;
        opt.innerHTML = enemy_list[f].name;
        enemyselect.appendChild(opt);
    }
    enemyselect.addEventListener('click', fillEnemyStats);
    enemyselect.addEventListener('change', fillEnemyStats);
    enemy_selection.appendChild(enemyselect);
    enemy_selection.appendChild(document.createElement('br'));
    enemy_selection.appendChild(document.createElement('br'));
    //quick fill
    opt.setAttribute("selected","selected");
    levelselect.click();
    if (window.location.search) {
        var autoenemy = decodeURI(window.location.search.split('=')[1]).replaceAll('+',' ');
        var elist = document.getElementById("enemylist").options;
        var lastshown = null;
        for (option in elist) {
            elist[option].selected = '';
            if (elist[option].innerHTML==autoenemy) {
                lastshown = elist[option];
                break;
            }
        }
        if (lastshown) {
            lastshown.selected = "selected"
            lastshown.click();
        }
    }    
    fillHeroStats();
}

/* above combat simulator is now executed on a page that is ready to accept it */

if (document.getElementById("combat_calc")) {
    setupCombatForm("combat_calc");
}