BvS Candyween Helper

Calculates probabilities of each choice in Candyween houses

  1. // ==UserScript==
  2. // @name BvS Candyween Helper
  3. // @namespace Garyzx
  4. // @description Calculates probabilities of each choice in Candyween houses
  5. // @include http*://*animecubed.com/billy/bvs/villagecandyween.html
  6. // @include http*://*animecubedgaming.com/billy/bvs/villagecandyween.html
  7. // @version 1.08
  8. // @history 1.08 New domain - animecubedgaming.com - Channel28
  9. // @history 1.07 Now https compatible (Updated by Channel28)
  10. // @history 1.06 Recognise Retail Power (thanks to Terrec)
  11. // @history 1.05 Displays chances without visiting each house
  12. // @history 1.04 Display data at the end, even if ads are turned off (thanks Thosha!)
  13. // @history 1.04 Update probabilities
  14. // @history 1.03 Replace eval() with closures to satisfy Greasemonkey restrictions (thanks to portwizard for finding the problem)
  15. // @history 1.02 Remove debugging output (oops)
  16. // @history 1.01 Auto-select first unvisited house
  17. // @history 1.01 Log Party/Psycho data and format data for forums
  18. // @history 1.01 Allow Candying at Party houses
  19. // @history 1.00 Initial version
  20. // @grant none
  21. // ==/UserScript==
  22.  
  23. var exts={};
  24. exts["Decrepit"]="old";
  25. exts["Creepy"]="creepy";
  26. exts["Typical"]="typical";
  27. exts["Spooky"]="spooky";
  28. exts["Bright"]="silly";
  29.  
  30. var ints={};
  31. ints["Candy"]=["big handfuls", "just giving", "tasty candy"];
  32. ints["Party"]=["rocking party", "Come on in", "new dance"];
  33. ints["Psycho"]=["wangly eye", "claw your way", "trigger a trapdoor"];
  34.  
  35. var cond={};
  36. cond["Candy"]={Decrepit: 678, Creepy: 766, Typical: 700, Spooky: 691, Bright: 763};
  37. cond["Party"]={Decrepit: 517, Creepy: 476, Typical: 478, Spooky: 444, Bright: 0};
  38. cond["Psycho"]={Decrepit: 0, Creepy: 173, Typical: 165, Spooky: 141, Bright: 167};
  39.  
  40. var actions={};
  41. actions["Party"]=["Hit On Somebody", "Rock Out", "Mope", "Tell Funny Stories"];
  42. actions["Psycho"]=["Hide In The Closet", "Get An Axe", "Burn the Place Down", "Scream and Cower"];
  43.  
  44. function normalize(obj){
  45. var total=0;
  46. for(var i in obj)
  47. total+=obj[i];
  48. for(var i in obj)
  49. obj[i]/=total;
  50. }
  51.  
  52. function get(key, def){
  53. var val;
  54. if(val=localStorage.getItem("candyween."+key))
  55. return val;
  56. return def;
  57. }
  58.  
  59. function set(key, val){
  60. localStorage.setItem("candyween."+key, val)
  61. }
  62.  
  63. var data=get("data", ",;,;,;,;,;,;,;,;,;,").split(";");
  64. for(var n=0; n<10; n++)
  65. data[n]=data[n].split(",");
  66.  
  67. if(document.body.innerHTML.match("Visit a House")){
  68. var table_items = document.evaluate("//form[@name='cw1']/table/tbody/tr/td", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  69. for (var i = 0; i < 10; i++){
  70. for(var n in exts)
  71. if(table_items.snapshotItem(i).innerHTML.match(exts[n]))
  72. data[i][0]=n;
  73. }
  74. var retail = document.body.textContent.match(/House #(\d+) is a Candy/);
  75. if(retail) {
  76. data[retail[1]-1][1]="Candy";
  77. }
  78. }
  79.  
  80. if(document.body.innerHTML.match(/>House #[0-9]+<\/font>/)){
  81. var houseNum=parseInt(document.body.innerHTML.match(/>House #([0-9]+)<\/font>/)[1])-1;
  82. if(document.body.innerHTML.match("think"))
  83. for(var i in ints){
  84. if(document.body.innerHTML.match("IS a "+i))
  85. data[houseNum][1]=i;
  86. else if(document.body.innerHTML.match("a "+i))
  87. data[houseNum][1]="Not "+i;
  88. }
  89. for(var i in ints)
  90. for(var j in ints[i])
  91. if(document.body.innerHTML.match(ints[i][j]))
  92. data[houseNum][1]=i;
  93. set("lastHouse", houseNum);
  94. set("lastAct", "");
  95. }
  96.  
  97. if(document.body.innerHTML.match("Pick an Action")){
  98. for(var n=1; n<=4; n++)
  99. document.getElementById("spact"+n).addEventListener("focus", function(){
  100. set("lastAct", this.value);
  101. }, false);
  102. }
  103.  
  104. if(get("lastAct")){
  105. var n=parseInt(get("lastAct"));
  106. var result="";
  107. if(document.body.innerHTML.match(/That choice's result:<br><b>[^<]+</))
  108. result=document.body.innerHTML.match(/That choice's result:<br><b>([^<]+)</)[1];
  109. else if(document.body.innerHTML.match(/You Got [^!]+!/))
  110. result=document.body.innerHTML.match(/You Got ([^!]+)!/)[1];
  111. else if(document.body.innerHTML.match(/4 Time/))
  112. result="-4 Time";
  113. if(result){
  114. set("lastAct", "");
  115. var games=JSON.parse(get("minigames", "[]"));
  116. games.push([parseInt(get("lastHouse")), n-1, result]);
  117. set("minigames", JSON.stringify(games));
  118. }
  119. }
  120.  
  121. for(var i in cond)
  122. normalize(cond[i]);
  123.  
  124. var probs=[];
  125. for(var n=0; n<10; n++){
  126. probs[n]={};
  127. for(var i in ints)
  128. probs[n][i]=0;
  129. }
  130.  
  131. var notCandy=[];
  132. for(notCandy[0]=0; notCandy[0]<7; notCandy[0]++)
  133. for(notCandy[1]=notCandy[0]+1; notCandy[1]<8; notCandy[1]++)
  134. for(notCandy[2]=notCandy[1]+1; notCandy[2]<9; notCandy[2]++)
  135. for(notCandy[3]=notCandy[2]+1; notCandy[3]<10; notCandy[3]++)
  136. for(var psycho=0; psycho<4; psycho++){
  137. var houses=[];
  138. for(var n=0; n<10; n++)
  139. houses[n]="Candy";
  140. for(var n=0; n<4; n++)
  141. houses[notCandy[n]]="Party";
  142. houses[notCandy[psycho]]="Psycho";
  143. var prob=1;
  144. for(var n=0; n<10; n++){
  145. if(data[n][0])
  146. prob*=cond[houses[n]][data[n][0]];
  147. if(data[n][1]){
  148. if(data[n][1].match("Not")){
  149. if(data[n][1].match(houses[n])){
  150. prob=0;
  151. break;
  152. }
  153. }
  154. else
  155. if(!data[n][1].match(houses[n])){
  156. prob=0;
  157. break;
  158. }
  159. }
  160. }
  161. for(var n=0; n<10; n++)
  162. probs[n][houses[n]]+=prob;
  163. }
  164.  
  165. for(var n=0; n<10; n++){
  166. normalize(probs[n]);
  167. for(var i in probs[n])
  168. if(probs[n][i]>0.9999)
  169. data[n][1]=i;
  170. var body="";
  171. for(var i in probs[n])
  172. if(probs[n][i]>0.0001)
  173. body+=Math.round(probs[n][i]*1000)/10+"% "+i+", ";
  174. body=body.substr(0, body.length-2);
  175. var header="?", color="redswitch=[1]";
  176. if(data[n][0]){
  177. header=data[n][0];
  178. color="";
  179. }
  180. if(data[n][1]){
  181. header+=", "+data[n][1];
  182. if(!data[n][1].match("Not"))
  183. color="greenswitch=[1]";
  184. }
  185. if(document.body.innerHTML.match("Visit a House"))
  186. document.evaluate("//label[@for='house"+(n+1)+"']", document, null, XPathResult.ANY_TYPE, null).iterateNext().title
  187. ="header=["+header+"] body=["+body+"] "+color;
  188. }
  189.  
  190. var maximized="";
  191. function maximize(int){
  192. if(avoiding==int){
  193. maximized=int;
  194. avoid(avoiding);
  195. return;
  196. }
  197. var max=0;
  198. for(var n=0; n<10; n++)
  199. if(!document.getElementById("house"+(n+1)).disabled && probs[n][int]>max){
  200. max=probs[n][int];
  201. document.getElementById("house"+(n+1)).click();
  202. }
  203. if(max==0){
  204. if(avoiding)
  205. alert("All "+int+" houses are "+avoiding+" houses!");
  206. else
  207. alert("No more "+int+" houses!");
  208. }
  209. else
  210. maximized=int;
  211. }
  212.  
  213. function minimize(int){
  214. var min=1;
  215. for(var n=0; n<10; n++)
  216. if(!document.getElementById("house"+(n+1)).disabled && probs[n][int]<min){
  217. min=probs[n][int];
  218. document.getElementById("house"+(n+1)).click();
  219. }
  220. if(min==1)
  221. alert("All remaining houses are "+int+"houses!");
  222. }
  223.  
  224. var avoiding="";
  225. function avoid(int){
  226. if(avoiding==int){
  227. for(var n=0; n<10; n++)
  228. document.getElementById("house"+(n+1)).disabled=visited[n];
  229. avoiding="";
  230. if(maximized)
  231. window.setTimeout(function() {maximize(maximized);}, 100);
  232. document.getElementById("avoid"+int).value="Avoid "+int+" houses";
  233. }
  234. else{
  235. avoiding=int;
  236. for(var n=0; n<10; n++)
  237. if(probs[n][int]>0.0001){
  238. document.getElementById("house"+(n+1)).disabled=true;
  239. document.getElementById("house"+(n+1)).checked=false;
  240. }
  241. else
  242. document.getElementById("house"+(n+1)).disabled=visited[n];
  243. if(maximized && maximized!=int)
  244. window.setTimeout(function() {maximize(maximized);}, 100);
  245. for(var i in ints)
  246. if(document.getElementById("avoid"+i))
  247. document.getElementById("avoid"+i).value="Avoid "+i+" houses";
  248. document.getElementById("avoid"+int).value="Unavoid "+int+" houses";
  249. }
  250. }
  251.  
  252. if(document.body.innerHTML.match("Perform")){
  253. var houseNum=parseInt(document.body.innerHTML.match(/>House #([0-9]+)<\/font>/)[1])-1;
  254. var results=["Candy", "Party", "Psycho"];
  255. for(var n=0; n<3; n++){
  256. document.evaluate("//*[@for='ha"+(n+1)+"']", document, null, XPathResult.ANY_TYPE, null)
  257. .iterateNext().innerHTML+=" ("+Math.round(probs[houseNum][results[n]]*1000)/10+"%)";
  258. if(probs[houseNum][results[n]]<0.0001 && !(results[n]=="Candy" && probs[houseNum]["Party"]>0.9999))
  259. document.getElementById("ha"+(n+1)).disabled=true;
  260. else if(probs[houseNum][results[n]]>0.9999)
  261. document.getElementById("ha"+(n+1)).click();
  262. }
  263. }
  264. else if(document.body.innerHTML.match("Visit")){
  265. var visited=[];
  266. for(var n=0; n<10; n++)
  267. visited[n]=document.getElementById("house"+(n+1)).disabled;
  268. var div=document.createElement("div");
  269. document.forms.namedItem("cw1").appendChild(div);
  270. div.appendChild(document.createElement("br"));
  271. var table=document.createElement("table");
  272. for(var n=0; n<2; n++){
  273. var tr=document.createElement("tr");
  274. for(var i in ints){
  275. var td=document.createElement("td");
  276. var a=document.createElement("input");
  277. a.type="button";
  278. if(n==0){
  279. a.value="Maximize "+i+" chance";
  280. (function(j){a.addEventListener("click", function(){maximize(j);}, true)})(i);
  281. }
  282. else{
  283. var avoidable=false;
  284. for(var j=0; j<10; j++)
  285. if(!document.getElementById("house"+(j+1)).disabled && probs[j][i]<0.0001)
  286. avoidable=true;
  287. if(avoidable){
  288. a.value="Avoid "+i+" houses";
  289. a.id="avoid"+i;
  290. (function(j){a.addEventListener("click", function(){avoid(j);}, true)})(i);
  291. }
  292. else{
  293. a.value="Minimize "+i+" chance";
  294. (function(j){a.addEventListener("click", function(){minimize(j);}, true)})(i);
  295. }
  296. }
  297. td.appendChild(a);
  298. tr.appendChild(td);
  299. }
  300. table.appendChild(tr);
  301. }
  302. div.appendChild(table);
  303. var complete=true, next=-1;
  304. for(var i=0; i<10; i++)
  305. if(!data[i][0]){
  306. complete=false;
  307. if(next==-1)
  308. next=i+1;
  309. }
  310. if(!complete){
  311. div.appendChild(document.createElement("br"));
  312. var note=document.createElement("div");
  313. note.innerHTML="For optimal results, visit all houses once first.";
  314. note.style.fontWeight="bold";
  315. note.style.fontVariant="small-caps";
  316. note.style.fontStyle="italic";
  317. div.appendChild(note);
  318. document.getElementById("house"+next).click();
  319. }
  320. div.appendChild(document.createElement("br"));
  321. var a=document.createElement("a");
  322. a.innerHTML="Clear data";
  323. a.href="#";
  324. a.addEventListener("click", function(){
  325. if(confirm("Are you sure you want to clear all data?\nThis cannot be undone.")){
  326. for(var i in data)
  327. for(var j in data[i])
  328. data[i][j]="";
  329. set("data", ",;,;,;,;,;,;,;,;,;,");
  330. set("minigames", "[]");
  331. alert("Data cleared.");
  332. }
  333. }, true);
  334. a.style.fontSize="12px";
  335. a.style.color="black";
  336. a.style.fontWeight="bold";
  337. div.appendChild(a);
  338. }
  339. else if(document.body.innerHTML.match("See you")){
  340. var div=document.createElement("div");
  341. var area=document.createElement("textarea");
  342. var minigames=JSON.parse(get("minigames", "[]"));
  343. var output=[];
  344. for(var n=0; n<10; n++){
  345. output[n]=(n+1)+". ";
  346. if(data[n][0])
  347. output[n]+=data[n][0];
  348. if(data[n][1])
  349. output[n]+=" - "+data[n][1];
  350. }
  351. for(var n in minigames)
  352. output[minigames[n][0]]+=" ("+actions[data[minigames[n][0]][1]][minigames[n][1]]+": "+minigames[n][2]+")";
  353. area.value="Ally: "+get("ally")+"\n\n";
  354. for(var n=0; n<10; n++)
  355. area.value+=output[n]+"\n";
  356. area.rows=14;
  357. area.cols=60;
  358. area.addEventListener("focus", function(){this.select()}, false);
  359. div.innerHTML="Please <a href='/billy/forum/posting.php?mode=reply&f=36&t=16645' target='_blank'>post</a>"+
  360. " the below into <a href='/billy/forum/viewtopic.php?f=36&t=16645' target='_blank'>this thread</a>.<br><br>";
  361. div.appendChild(area);
  362. document.evaluate("//table[@width=510]/tbody/tr/td",
  363. document, null, XPathResult.ANY_TYPE, null ).iterateNext().appendChild(div);
  364. }
  365. else if(document.body.innerHTML.match("Choose Partner") || document.body.innerHTML.match("You chose")){
  366. for(var i in data)
  367. for(var j in data[i])
  368. data[i][j]="";
  369. set("minigames", "[]");
  370. if(document.body.innerHTML.match("You chose")){
  371. set("ally", document.body.innerHTML.match(/You chose ([^!]+)!/)[1]);
  372. }
  373. }
  374.  
  375. for(var n=0; n<10; n++)
  376. data[n]=data[n].join(",");
  377. set("data", data.join(";"));