BvS Candyween Helper

Calculates probabilities of each choice in Candyween houses

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name           BvS Candyween Helper
// @namespace      Garyzx
// @description    Calculates probabilities of each choice in Candyween houses
// @include        http*://*animecubed.com/billy/bvs/villagecandyween.html
// @include        http*://*animecubedgaming.com/billy/bvs/villagecandyween.html
// @version        1.08
// @history        1.08 New domain - animecubedgaming.com - Channel28
// @history        1.07 Now https compatible (Updated by Channel28)
// @history        1.06 Recognise Retail Power (thanks to Terrec)
// @history        1.05 Displays chances without visiting each house
// @history        1.04 Display data at the end, even if ads are turned off (thanks Thosha!)
// @history        1.04 Update probabilities
// @history        1.03 Replace eval() with closures to satisfy Greasemonkey restrictions (thanks to portwizard for finding the problem)
// @history        1.02 Remove debugging output (oops)
// @history        1.01 Auto-select first unvisited house
// @history        1.01 Log Party/Psycho data and format data for forums
// @history        1.01 Allow Candying at Party houses
// @history        1.00 Initial version
// @grant          none
// ==/UserScript==

var exts={};
exts["Decrepit"]="old";
exts["Creepy"]="creepy";
exts["Typical"]="typical";
exts["Spooky"]="spooky";
exts["Bright"]="silly";

var ints={};
ints["Candy"]=["big handfuls", "just giving", "tasty candy"];
ints["Party"]=["rocking party", "Come on in", "new dance"];
ints["Psycho"]=["wangly eye", "claw your way", "trigger a trapdoor"];

var cond={};
cond["Candy"]={Decrepit: 678, Creepy: 766, Typical: 700, Spooky: 691, Bright: 763};
cond["Party"]={Decrepit: 517, Creepy: 476, Typical: 478, Spooky: 444, Bright: 0};
cond["Psycho"]={Decrepit: 0, Creepy: 173, Typical: 165, Spooky: 141, Bright: 167};

var actions={};
actions["Party"]=["Hit On Somebody", "Rock Out", "Mope", "Tell Funny Stories"];
actions["Psycho"]=["Hide In The Closet", "Get An Axe", "Burn the Place Down", "Scream and Cower"];

function normalize(obj){
	var total=0;
	for(var i in obj)
		total+=obj[i];
	for(var i in obj)
		obj[i]/=total;
}

function get(key, def){
	var val;
	if(val=localStorage.getItem("candyween."+key))
		return val;
	return def;
}

function set(key, val){
	localStorage.setItem("candyween."+key, val)
}

var data=get("data", ",;,;,;,;,;,;,;,;,;,").split(";");
for(var n=0; n<10; n++)
	data[n]=data[n].split(",");

if(document.body.innerHTML.match("Visit a House")){
   var table_items = document.evaluate("//form[@name='cw1']/table/tbody/tr/td", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
   for (var i = 0; i < 10; i++){
      for(var n in exts)
         if(table_items.snapshotItem(i).innerHTML.match(exts[n]))
            data[i][0]=n;
   }
   var retail = document.body.textContent.match(/House #(\d+) is a Candy/);
   if(retail) {
      data[retail[1]-1][1]="Candy";
   }
}

if(document.body.innerHTML.match(/>House #[0-9]+<\/font>/)){
	var houseNum=parseInt(document.body.innerHTML.match(/>House #([0-9]+)<\/font>/)[1])-1;
	if(document.body.innerHTML.match("think"))
	for(var i in ints){
		if(document.body.innerHTML.match("IS a "+i))
		data[houseNum][1]=i;
		else if(document.body.innerHTML.match("a "+i))
		data[houseNum][1]="Not "+i;
		}
	for(var i in ints)
	for(var j in ints[i])
	if(document.body.innerHTML.match(ints[i][j]))
	data[houseNum][1]=i;
	set("lastHouse", houseNum);
	set("lastAct", "");
}

if(document.body.innerHTML.match("Pick an Action")){
	for(var n=1; n<=4; n++)
		document.getElementById("spact"+n).addEventListener("focus", function(){
			set("lastAct", this.value);
		}, false);
}

if(get("lastAct")){
	var n=parseInt(get("lastAct"));
	var result="";
	if(document.body.innerHTML.match(/That choice's result:<br><b>[^<]+</))
		result=document.body.innerHTML.match(/That choice's result:<br><b>([^<]+)</)[1];
	else if(document.body.innerHTML.match(/You Got [^!]+!/))
		result=document.body.innerHTML.match(/You Got ([^!]+)!/)[1];
	else if(document.body.innerHTML.match(/4 Time/))
		result="-4 Time";
	if(result){
		set("lastAct", "");
		var games=JSON.parse(get("minigames", "[]"));
		games.push([parseInt(get("lastHouse")), n-1, result]);
		set("minigames", JSON.stringify(games));
	}
}

for(var i in cond)
	normalize(cond[i]);

var probs=[];
for(var n=0; n<10; n++){
	probs[n]={};
	for(var i in ints)
		probs[n][i]=0;
}

var notCandy=[];
for(notCandy[0]=0; notCandy[0]<7; notCandy[0]++)
for(notCandy[1]=notCandy[0]+1; notCandy[1]<8; notCandy[1]++)
for(notCandy[2]=notCandy[1]+1; notCandy[2]<9; notCandy[2]++)
for(notCandy[3]=notCandy[2]+1; notCandy[3]<10; notCandy[3]++)
for(var psycho=0; psycho<4; psycho++){
	var houses=[];
	for(var n=0; n<10; n++)
		houses[n]="Candy";
	for(var n=0; n<4; n++)
		houses[notCandy[n]]="Party";
	houses[notCandy[psycho]]="Psycho";
	var prob=1;
	for(var n=0; n<10; n++){
		if(data[n][0])
			prob*=cond[houses[n]][data[n][0]];
		if(data[n][1]){
			if(data[n][1].match("Not")){
				if(data[n][1].match(houses[n])){
					prob=0;
					break;
				}
			}
			else
				if(!data[n][1].match(houses[n])){
					prob=0;
					break;
				}
		}
	}
	for(var n=0; n<10; n++)
		probs[n][houses[n]]+=prob;
}

for(var n=0; n<10; n++){
	normalize(probs[n]);
	for(var i in probs[n])
		if(probs[n][i]>0.9999)
			data[n][1]=i;
	var body="";
	for(var i in probs[n])
		if(probs[n][i]>0.0001)
			body+=Math.round(probs[n][i]*1000)/10+"% "+i+", ";
	body=body.substr(0, body.length-2);
	var header="?", color="redswitch=[1]";
	if(data[n][0]){
		header=data[n][0];
		color="";
	}
	if(data[n][1]){
		header+=", "+data[n][1];
		if(!data[n][1].match("Not"))
			color="greenswitch=[1]";
	}
	if(document.body.innerHTML.match("Visit a House"))
		document.evaluate("//label[@for='house"+(n+1)+"']", document, null, XPathResult.ANY_TYPE, null).iterateNext().title
				="header=["+header+"] body=["+body+"] "+color;
}

var maximized="";
function maximize(int){
	if(avoiding==int){
		maximized=int;
		avoid(avoiding);
		return;
	}
	var max=0;
	for(var n=0; n<10; n++)
		if(!document.getElementById("house"+(n+1)).disabled && probs[n][int]>max){
			max=probs[n][int];
			document.getElementById("house"+(n+1)).click();
		}
	if(max==0){
		if(avoiding)
			alert("All "+int+" houses are "+avoiding+" houses!");
		else
			alert("No more "+int+" houses!");
	}
	else
		maximized=int;
}

function minimize(int){
	var min=1;
	for(var n=0; n<10; n++)
		if(!document.getElementById("house"+(n+1)).disabled && probs[n][int]<min){
			min=probs[n][int];
			document.getElementById("house"+(n+1)).click();
		}
	if(min==1)
		alert("All remaining houses are "+int+"houses!");
}

var avoiding="";
function avoid(int){
	if(avoiding==int){
		for(var n=0; n<10; n++)
			document.getElementById("house"+(n+1)).disabled=visited[n];
		avoiding="";
		if(maximized)
			window.setTimeout(function() {maximize(maximized);}, 100);
		document.getElementById("avoid"+int).value="Avoid "+int+" houses";
	}
	else{
		avoiding=int;
		for(var n=0; n<10; n++)
			if(probs[n][int]>0.0001){
				document.getElementById("house"+(n+1)).disabled=true;
				document.getElementById("house"+(n+1)).checked=false;
			}
			else
				document.getElementById("house"+(n+1)).disabled=visited[n];
		if(maximized && maximized!=int)
			window.setTimeout(function() {maximize(maximized);}, 100);
		for(var i in ints)
			if(document.getElementById("avoid"+i))
				document.getElementById("avoid"+i).value="Avoid "+i+" houses";
		document.getElementById("avoid"+int).value="Unavoid "+int+" houses";
	}
}

if(document.body.innerHTML.match("Perform")){
	var houseNum=parseInt(document.body.innerHTML.match(/>House #([0-9]+)<\/font>/)[1])-1;
	var results=["Candy", "Party", "Psycho"];
	for(var n=0; n<3; n++){
		document.evaluate("//*[@for='ha"+(n+1)+"']", document, null, XPathResult.ANY_TYPE, null)
				.iterateNext().innerHTML+=" ("+Math.round(probs[houseNum][results[n]]*1000)/10+"%)";
		if(probs[houseNum][results[n]]<0.0001 && !(results[n]=="Candy" && probs[houseNum]["Party"]>0.9999))
			document.getElementById("ha"+(n+1)).disabled=true;
		else if(probs[houseNum][results[n]]>0.9999)
			document.getElementById("ha"+(n+1)).click();
	}
}
else if(document.body.innerHTML.match("Visit")){
	var visited=[];
	for(var n=0; n<10; n++)
		visited[n]=document.getElementById("house"+(n+1)).disabled;
	var div=document.createElement("div");
	document.forms.namedItem("cw1").appendChild(div);
	div.appendChild(document.createElement("br"));
	var table=document.createElement("table");
	for(var n=0; n<2; n++){
		var tr=document.createElement("tr");
		for(var i in ints){
			var td=document.createElement("td");
			var a=document.createElement("input");
			a.type="button";
			if(n==0){
				a.value="Maximize "+i+" chance";
				(function(j){a.addEventListener("click", function(){maximize(j);}, true)})(i);
			}
			else{
				var avoidable=false;
				for(var j=0; j<10; j++)
					if(!document.getElementById("house"+(j+1)).disabled && probs[j][i]<0.0001)
						avoidable=true;
				if(avoidable){
					a.value="Avoid "+i+" houses";
					a.id="avoid"+i;
					(function(j){a.addEventListener("click", function(){avoid(j);}, true)})(i);
				}
				else{
					a.value="Minimize "+i+" chance";
					(function(j){a.addEventListener("click", function(){minimize(j);}, true)})(i);
				}
			}
			td.appendChild(a);
			tr.appendChild(td);
		}
		table.appendChild(tr);
	}
	div.appendChild(table);
	var complete=true, next=-1;
	for(var i=0; i<10; i++)
		if(!data[i][0]){
			complete=false;
			if(next==-1)
				next=i+1;
		}
	if(!complete){
		div.appendChild(document.createElement("br"));
		var note=document.createElement("div");
		note.innerHTML="For optimal results, visit all houses once first.";
		note.style.fontWeight="bold";
		note.style.fontVariant="small-caps";
		note.style.fontStyle="italic";
		div.appendChild(note);
		document.getElementById("house"+next).click();
	}
	div.appendChild(document.createElement("br"));
	var a=document.createElement("a");
	a.innerHTML="Clear data";
	a.href="#";
	a.addEventListener("click", function(){
		if(confirm("Are you sure you want to clear all data?\nThis cannot be undone.")){
			for(var i in data)
				for(var j in data[i])
					data[i][j]="";
			set("data", ",;,;,;,;,;,;,;,;,;,");
			set("minigames", "[]");
			alert("Data cleared.");
		}
	}, true);
	a.style.fontSize="12px";
	a.style.color="black";
	a.style.fontWeight="bold";
	div.appendChild(a);
}
else if(document.body.innerHTML.match("See you")){
	var div=document.createElement("div");
	var area=document.createElement("textarea");
	var minigames=JSON.parse(get("minigames", "[]"));
	var output=[];
	for(var n=0; n<10; n++){
		output[n]=(n+1)+". ";
		if(data[n][0])
			output[n]+=data[n][0];
		if(data[n][1])
			output[n]+=" - "+data[n][1];
	}
	for(var n in minigames)
		output[minigames[n][0]]+=" ("+actions[data[minigames[n][0]][1]][minigames[n][1]]+": "+minigames[n][2]+")";
	area.value="Ally: "+get("ally")+"\n\n";
	for(var n=0; n<10; n++)
		area.value+=output[n]+"\n";
	area.rows=14;
	area.cols=60;
	area.addEventListener("focus", function(){this.select()}, false);
	div.innerHTML="Please <a href='/billy/forum/posting.php?mode=reply&f=36&t=16645' target='_blank'>post</a>"+
			" the below into <a href='/billy/forum/viewtopic.php?f=36&t=16645' target='_blank'>this thread</a>.<br><br>";
	div.appendChild(area);
	document.evaluate("//table[@width=510]/tbody/tr/td",
			document, null, XPathResult.ANY_TYPE, null ).iterateNext().appendChild(div);
}
else if(document.body.innerHTML.match("Choose Partner") || document.body.innerHTML.match("You chose")){
	for(var i in data)
		for(var j in data[i])
			data[i][j]="";
	set("minigames", "[]");
	if(document.body.innerHTML.match("You chose")){
		set("ally", document.body.innerHTML.match(/You chose ([^!]+)!/)[1]);
	}
}

for(var n=0; n<10; n++)
	data[n]=data[n].join(",");
set("data", data.join(";"));