Meteoid Path Finder

Provides pathfinding for the mini-map in KoL's mini-game Meteoid.

  1. // ==UserScript==
  2. // @name Meteoid Path Finder
  3. // @namespace kol.interface.unfinished
  4. // @description Provides pathfinding for the mini-map in KoL's mini-game Meteoid.
  5. // @include http://*kingdomofloathing.com/choice.php*
  6. // @include http://127.0.0.1:*/choice.php*
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @grant GM_xmlhttpRequest
  10. // @version 1.01
  11. // ==/UserScript==
  12.  
  13. // Version 1.01
  14. // - add @grant
  15. // Version 1.0
  16.  
  17. function doAction(vars,callback,time) {
  18. GM_xmlhttpRequest({
  19. method: "POST",
  20. url: "http://" + location.host + "/choice.php",
  21. headers: {"Content-type": "application/x-www-form-urlencoded"},
  22. data: vars,
  23. onload: function(response){
  24. var d = document.getElementById('meteoidresult');
  25. if (!d) {
  26. var p = document.body.firstChild;
  27. while (p.nextSibling && p.tagName!='CENTER') {
  28. p = p.nextSibling;
  29. }
  30. d = document.createElement('center');
  31. d.setAttribute('id','meteoidresult');
  32. p.parentNode.replaceChild(d,p);
  33. }
  34. d.innerHTML = response.responseText;
  35. if (callback)
  36. setTimeout(callback,200);
  37. //location.reload();
  38. }
  39. });
  40. }
  41.  
  42. function press(input,callback) {
  43. input.setAttribute('style','color:red;');
  44. var f = input.parentNode;
  45. var ps = document.evaluate('.//input',f,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
  46. var args = '';
  47. for (var i=ps.snapshotLength-1;i>=0;i--) {
  48. var p = ps.snapshotItem(i);
  49. var n = p.getAttribute('name');
  50. if (n) {
  51. if (args)
  52. args += '&';
  53. args += n+'='+encodeURI(p.getAttribute('value'));
  54. }
  55. }
  56. doAction(args,callback);
  57. }
  58.  
  59. var map;
  60.  
  61. function check() {
  62. if (document.evaluate( '//b[text()="Meteoid"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue) {
  63. var opt = document.evaluate( '//td[@bgcolor="pink"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
  64. if (opt.singleNodeValue) {
  65. // found the minimap
  66. var t = opt.singleNodeValue.parentNode;
  67. while (t && t.tagName!='TABLE')
  68. t = t.parentNode;
  69. if (t) {
  70. t = t.parentNode;
  71. while (t && t.tagName!='TABLE')
  72. t = t.parentNode;
  73. if (t) {
  74. var tx = Number(GM_getValue('targetx','-1'));
  75. var ty = Number(GM_getValue('targety','-1'));
  76. if (tx>=0 && ty>=0) {
  77. parseMap(t);
  78. if (tx==map.you[0] && ty==map.you[1]) {
  79. GM_setValue('targetx','-1');
  80. GM_setValue('targety','-1');
  81. parseMap(t,true);
  82. } else
  83. move(map.you[0],map.you[1],tx,ty);
  84. } else
  85. parseMap(t,true);
  86. //printMap();
  87. }
  88. }
  89. }
  90. }
  91. }
  92.  
  93. function printMap() {
  94. var line='';
  95. for (var y=0;y<5;y++) {
  96. for (var x=0;x<5;x++) {
  97. var c = map[y][x];
  98. line +='\t'+c;
  99. }
  100. line +='\n';
  101. }
  102. }
  103.  
  104. function parseMap(t,add) {
  105. var ps = document.evaluate('.//td[@align="center"]',t,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
  106. var a = [];
  107. for (var i=0;i<ps.snapshotLength;i++) {
  108. a[i] = ps.snapshotItem(i);
  109. }
  110. map = [];
  111. var x=0,y=0;
  112. for (var i=0;i<a.length;i++) {
  113. var td = a[i];
  114. var row;
  115. if (x==0)
  116. row = [];
  117. else
  118. row = map[y];
  119. if (td.getAttribute('bgcolor')=='pink') {
  120. var symbol = td.innerHTML;
  121. if (symbol)
  122. symbol = symbol.replace(/<[^>]*>/g,'');
  123. if (symbol=='*')
  124. map.you = [x,y];
  125. else if (add) {
  126. td.setAttribute('cx',x);
  127. td.setAttribute('cy',y);
  128. td.parentNode.parentNode.parentNode.setAttribute('title','Click to move to here.');
  129. td.addEventListener('click',moveTo,false);
  130. }
  131. var n = 0;
  132. // check for left neighbour
  133. if (x>0 && row[x-1]) {
  134. if (connects(td,-1,0))
  135. n |= 1;
  136. }
  137. // check for right neighbour
  138. if (x<4) {
  139. if (connects(td,1,0))
  140. n |= 2;
  141. }
  142. // check for top neighbour
  143. if (y>0 && map[y-1][x]) {
  144. if (connects(td,0,-1))
  145. n |= 4;
  146. }
  147. // check for bottom neighbour
  148. if (y<4) {
  149. if (connects(td,0,1))
  150. n |= 8;
  151. }
  152. if (n==0) n |= 16;
  153. row[x] = n;
  154. } else
  155. row[x] = 0;
  156. map[y] = row;
  157. x++;
  158. if (x>4) {
  159. x = 0;
  160. y++;
  161. }
  162. }
  163. }
  164.  
  165. function moveTo(e) {
  166. var tx = this.getAttribute('cx');
  167. var ty = this.getAttribute('cy');
  168. this.removeEventListener('click',moveTo,false);
  169. move(map.you[0],map.you[1],tx,ty);
  170. }
  171.  
  172. var dir;
  173.  
  174. function clone(obj) {
  175. var clone = {};
  176. clone.prototype = obj.prototype;
  177. for (property in obj) clone[property] = obj[property];
  178. return clone;
  179. }
  180.  
  181. function move(fx,fy,tx,ty) {
  182. // find next step
  183. dir = '';
  184. var s = search(Number(map.you[0]),Number(map.you[1]),{},tx,ty,0);
  185. if (dir) {
  186. GM_setValue('targetx',tx);
  187. GM_setValue('targety',ty);
  188. var input;
  189. input = document.evaluate('//input[@value="'+dir+'"]',document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
  190. if (input.singleNodeValue)
  191. press(input.singleNodeValue,check);
  192. } else {
  193. GM_setValue('targetx','-1');
  194. GM_setValue('targety','-1');
  195. }
  196. }
  197.  
  198. function search(x,y,done,tx,ty,dist) {
  199. if (x==tx && y==ty) {
  200. return dist;
  201. }
  202. var mx = 10000000;
  203. var d = clone(done);
  204. dist = Number(dist)+1;
  205. d[x+','+y] = true;
  206. // left
  207. if (map[y][x] & 1) {
  208. var m = (x-1)+','+y;
  209. if (!d[m]) {
  210. var c = search(x-1,y,d,tx,ty,dist);
  211. if (c<mx) {
  212. mx = c;
  213. dir = 'Left';
  214. }
  215. }
  216. }
  217. // right
  218. if (map[y][x] & 2) {
  219. var m = (Number(x)+1)+','+y;
  220. if (!d[m]) {
  221. var c = search(x+1,y,d,tx,ty,dist);
  222. if (c<mx) {
  223. mx = c;
  224. dir = 'Right';
  225. }
  226. }
  227. }
  228. // up
  229. if (map[y][x] & 4) {
  230. var m = x+','+(y-1);
  231. if (!d[m]) {
  232. var c = search(x,y-1,d,tx,ty,dist);
  233. if (c<mx) {
  234. mx = c;
  235. //dir = '&nbsp;&nbsp;Up&nbsp;&nbsp;';
  236. dir = '\u00A0\u00A0Up\u00A0\u00A0';
  237. }
  238. }
  239. }
  240. // down
  241. if (map[y][x] & 8) {
  242. var m = x+','+(Number(y)+1);
  243. if (!d[m]) {
  244. var c = search(x,y+1,d,tx,ty,dist);
  245. if (c<mx) {
  246. mx = c;
  247. dir = 'Down';
  248. }
  249. }
  250. }
  251. return mx;
  252. }
  253.  
  254. function connects(td,xd,yd) {
  255. if (xd==0) {
  256. if (yd<0) {
  257. var tr = td.parentNode.previousSibling;
  258. td = tr.firstChild.nextSibling;
  259. if (td.getAttribute('bgcolor')=='pink')
  260. return true;
  261. return false;
  262. } else { // yd>0
  263. var tr = td.parentNode.nextSibling;
  264. td = tr.firstChild.nextSibling;
  265. if (td.getAttribute('bgcolor')=='pink')
  266. return true;
  267. return false;
  268. }
  269. } else if (xd<0) {
  270. td = td.previousSibling;
  271. if (td.getAttribute('bgcolor')=='pink')
  272. return true;
  273. return false;
  274. } // xd>0
  275. td = td.nextSibling;
  276. if (td.getAttribute('bgcolor')=='pink')
  277. return true;
  278. return false;
  279. }
  280.  
  281. function getState() {
  282. var s = GM_getValue('state',0);
  283. if (s>=path.length) s = 0;
  284. return s;
  285. }
  286.  
  287. function setState(s) {
  288. GM_setValue('state',s);
  289. }
  290.  
  291. check();