Guest User

Untitled

a guest
Apr 21st, 2018
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.04 KB | None | 0 0
  1. class Node {
  2. constructor(area, itemCount, smallKeyCount, dungeonPrizeCount) {
  3. this.area_ = area;
  4. this.itemCount_ = itemCount;
  5. this.smallKeyCount_ = smallKeyCount;
  6. this.dungeonPrizeCount_ = dungeonPrizeCount;
  7. this.edgesOut_ = [];
  8. }
  9. };
  10.  
  11. function N(a,b,c,d) {
  12. return new Node(a,b,c,d);
  13. }
  14.  
  15. class Edge {
  16. constructor(nodeFrom, nodeTo, requirements, bidirectional) {
  17. this.nodeFrom_ = nodeFrom;
  18. this.nodeTo_ = nodeTo;
  19. this.requirements_ = requirements;
  20. this.bidirectional_ = bidirectional;
  21. }
  22. };
  23.  
  24. function E(nodeFrom, nodeTo, requirements, bidirectional) {
  25. var e = new Edge(Nodes[nodeFrom], Nodes[nodeTo], requirements || [], bidirectional !== false);
  26. Nodes[nodeFrom].edgesOut_.push(e);
  27. if (bidirectional) {
  28. Nodes[nodeTo].edgesOut_.push(e);
  29. }
  30. return e;
  31. }
  32.  
  33. let Items = [
  34. 'L1Sword',
  35. 'L2Sword',
  36. 'L3Sword',
  37. 'L4Sword',
  38. 'Bow',
  39. 'Hammer',
  40. 'Lamp',
  41. 'L1Gloves',
  42. 'L2Gloves',
  43. 'MoonPearl',
  44. 'FireRod',
  45. 'PODKey',
  46. 'PODMap',
  47. 'PODCompass',
  48. 'PODBigKey',
  49. 'EPMap',
  50. 'EPCompass',
  51. 'EPBigKey',
  52. 'EPKey',
  53. 'Boots'
  54. ];
  55.  
  56. let Enemies = {
  57. 'Popo': ['L1Sword', 'L2Sword', 'L3Sword', 'L4Sword', 'Hammer', 'FireRod', 'Bow'],
  58. 'Terrorpin': ['Hammer'],
  59. 'RedMimic': ['Bow'],
  60. 'GreenMimic': ['L1Sword', 'L2Sword', 'L3Sword', 'L4Sword', 'Bow', 'Hammer', 'FireRod'],
  61. 'ArmosKnights': ['L1Sword', 'L2Sword', 'L3Sword', 'L4Sword', 'Bow', 'Hammer'],
  62. 'HelmasaurKing': ['Hammer'],
  63. 'Bubble': [],
  64. 'GreenEyegore': ['L1Sword', 'L2Sword', 'L3Sword', 'L4Sword', 'Hammer', 'Bow'],
  65. 'RedEyegore': ['Bow'],
  66. 'Stalfos': [],
  67. };
  68.  
  69. // N(area, num_items, num_small_keys, num_dungeon_prizes)
  70. let Nodes = [
  71. /* 0 */ N('A'),
  72. /* 1 */ N('U', 1),
  73. /* 2 */ N('LW'),
  74. /* 3 */ N('U'),
  75. /* 4 */ N('U'),
  76. /* 5 */ N('U', 3),
  77. /* 6 */ N('EP', 3),
  78. /* 7 */ N('EP', 1),
  79. /* 8 */ N('EP', 0, 1),
  80. /* 9 */ N('EP', 1),
  81. /* 10 */ N('EP'),
  82. /* 11 */ N('EP', 0, 1),
  83. /* 12 */ N('EP', 1, 0, 1),
  84. /* 13 */ N('DW'),
  85. /* 14 */ N('U'),
  86. /* 15 */ N('U'),
  87. /* 16 */ N('U'),
  88. /* 17 */ N('POD', 1),
  89. /* 18 */ N('POD', 2),
  90. /* 19 */ N('POD', 2),
  91. /* 20 */ N('POD', 1),
  92. /* 21 */ N('POD', 1),
  93. /* 22 */ N('POD', 1),
  94. /* 23 */ N('POD', 2),
  95. /* 24 */ N('POD', 2),
  96. /* 25 */ N('POD'),
  97. /* 26 */ N('POD', 1),
  98. /* 27 */ N('POD', 1, 0, 1),
  99. /* 28 */ N('A', 1)
  100. ];
  101.  
  102. // E(node_from, node_to, requirements)
  103. let Edges = [
  104. E(0, 1),
  105. E(1, 2),
  106. E(2, 3),
  107. E(2, 4),
  108. E(2, 5),
  109. E(2, 6),
  110. E(2, 13, [['Hammer', 'L1Gloves', 'MoonPearl'], ['Hammer', 'L2Gloves', 'MoonPearl']]),
  111. E(6, 7, ['EPBigKey']),
  112. E(6, 8, ['EPDarkRoom1']),
  113. E(6, 10, ['EPDarkRoom2', 'EPBigKey']),
  114. E(8, 9, ['GreenEyegore', 'Stalfos', 'Stalfos', 'Popo', 'Popo', 'Bubble', 'Bubble', 'Bubble', 'Bubble', 'EP Door']),
  115. E(10, 11, ['GreenEyegore']),
  116. E(10, 12, ['RedEyegore', 'RedEyegore', 'RedEyegore', 'Stalfos', 'Stalfos', 'Popo', 'Popo', 'Popo', 'Popo', 'Popo', 'Popo', 'EPDoor', 'ArmosKnights']),
  117. E(13, 14),
  118. E(13, 15),
  119. E(13, 16),
  120. E(13, 17),
  121. E(17, 18, ['PODDoor']),
  122. E(17, 19, ['RedMimic', 'GreenMimic', 'GreenMimic']),
  123. E(18, 19, ['Hover'], false),
  124. E(18, 20, ['PODDoor']),
  125. E(18, 21, ['PODDoor']),
  126. E(19, 18, ['Hammer'], false),
  127. E(19, 27, ['PODDoor', 'PODBigKey', 'RedMimic', 'GreenMimic', 'GreenMimic', 'Bow', 'Hammer', 'Terrorpin', 'Terrorpin', 'Terrorpin', 'Terrorpin', 'Terrorpin', 'Terrorpin', 'PODDarkRoomFinal', 'HelmasaurKing']),
  128. E(21, 22, ['PODDoor']),
  129. E(21, 23, ['PODDark Basement']),
  130. E(21, 24, ['PODDoor', 'PODDarkMaze']),
  131. E(21, 25, [['PODHammerJump'], ['Hover']]),
  132. E(24, 25, ['PODDarkMaze']),
  133. E(25, 24, ['PODDarkMaze']),
  134. E(25, 26, ['PODBigKey']),
  135. E(0, 28, ['Crystal1', 'Crystal2'])
  136. ];
  137.  
  138. let map = {
  139. items: new WeakMap([
  140. [Nodes[ 1], ['L1Sword']],
  141. [Nodes[ 5], ['L2Sword', 'L3Sword', 'L4Sword']],
  142. [Nodes[ 6], ['Bow', 'Hammer', 'Lamp']],
  143. [Nodes[ 7], ['L1Gloves']],
  144. [Nodes[ 8], ['EPKey']],
  145. [Nodes[ 9], ['L2Gloves']],
  146. [Nodes[11], ['EPKey']],
  147. [Nodes[12], ['MoonPearl']],
  148. [Nodes[17], ['FireRod']],
  149. [Nodes[18], ['PODKey', 'PODKey']],
  150. [Nodes[19], ['PODKey', 'PODKey']],
  151. [Nodes[20], ['PODKey']],
  152. [Nodes[21], ['PODKey']],
  153. [Nodes[22], ['PODMap']],
  154. [Nodes[23], ['PODCompass', 'PODBigKey']],
  155. [Nodes[24], ['EPMap', 'EPCompass']],
  156. [Nodes[26], ['EPBigKey']],
  157. [Nodes[27], ['Boots']],
  158. [Nodes[28], ['Triforce']]
  159. ]),
  160. prizes: new WeakMap([
  161. [Nodes[12], 'Crystal1'],
  162. [Nodes[27], 'Crystal2']
  163. ])
  164. };
  165.  
  166. function isValidMap(map) {
  167. // this probably needs better logic.
  168. // we need to support something that can handle very basic boolean logic
  169. // like the dark world entrace below eastern requires:
  170. // Hammer && MoonPearl && (L1Gloves || L2Gloves)
  171. // in the current implementation, this is represented by this:
  172. // ['Hammer', 'MoonPearl', ['L1Gloves', 'L2Gloves']]
  173. // so the first level is assumed to be && and subsequent levels are assumed to be ||.
  174. function isPassable(edge) {
  175. function isPassableSingle(req) {
  176. if (Array.isArray(req)) {
  177. return req.some(isPassableSingle);
  178. }
  179. if (Items.includes(req) || req.match(/Crystal/)) {
  180. if (!items.includes(req)) {
  181. return false;
  182. }
  183. return true;
  184. } else if (Enemies[req]) {
  185. var foo = !Enemies[req].some((v, i, a) => {
  186. return items.includes(v);
  187. });
  188. if (!Enemies[req].length || foo) {
  189. return false;
  190. }
  191. return true;
  192. } else if (req.match(/Dark/)) {
  193. if (!items.includes('Lamp')) {
  194. return false;
  195. }
  196. return true;
  197. } else if (req === 'Hover') {
  198. return false;
  199. } else if (req.match(/Jump/)) {
  200. return false;
  201. } else if (req.match(/Door/)) {
  202. return false;
  203. } else {
  204. throw Error('unknown requirement');
  205. }
  206. return true;
  207. }
  208. return edge.requirements_.every(isPassableSingle);
  209. }
  210.  
  211. let items = [];
  212. let visitedEdges = [];
  213. let availableEdges = [];
  214. let visitedNodes = [];
  215. let availableNodes = [Nodes[0]];
  216.  
  217. while (true) {
  218. while (availableNodes.length) {
  219. let node = availableNodes.pop();
  220. if (visitedNodes.includes(node)) {
  221. continue;
  222. }
  223. visitedNodes.push(node);
  224. if (map.items.has(node)) {
  225. items = items.concat(map.items.get(node));
  226. }
  227. if (map.prizes.has(node)) {
  228. items.push(map.prizes.get(node));
  229. }
  230. for (let i = 0; i < node.edgesOut_.length; i++) {
  231. let edgeOut = node.edgesOut_[i];
  232. if (visitedEdges.includes(edgeOut)) {
  233. continue;
  234. }
  235. if (visitedNodes.includes(edgeOut.nodeFrom_) && visitedNodes.includes(edgeOut.nodeTo_)) {
  236. // need to account for small keys in this situation.
  237. // this is an edge we haven't passed but don't need to because we have already visited both nodes.
  238. // if it has a small key requirement, it needs to be accounted for.
  239. continue;
  240. }
  241. if (node === edgeOut.nodeFrom_ && visitedNodes.includes(edgeOut.nodeTo_)) {
  242. continue;
  243. }
  244. if (node === edgeOut.nodeTo_ && visitedNodes.includes(edgeOut.nodeFrom_)) {
  245. continue;
  246. }
  247. if (isPassable(edgeOut)) {
  248. visitedEdges.push(edgeOut);
  249. if (node === edgeOut.nodeTo_) {
  250. availableNodes.push(edgeOut.nodeFrom_);
  251. } else if (node === edgeOut.nodeFrom_) {
  252. availableNodes.push(edgeOut.nodeTo_);
  253. } else {
  254. throw Error('weird edge thing just happened');
  255. }
  256. } else if (!availableEdges.includes(edgeOut)) {
  257. availableEdges.push(edgeOut);
  258. }
  259. }
  260. }
  261.  
  262. let newAvailableEdges = [];
  263. for (let i = 0; i < availableEdges.length; i++) {
  264. let edge = availableEdges[i];
  265. if (isPassable(edge)) {
  266. visitedEdges.push(edge);
  267. if (!visitedNodes.includes(edge.nodeFrom_)) {
  268. availableNodes.push(edge.nodeFrom_);
  269. }
  270. if (!visitedNodes.includes(edge.nodeTo_)) {
  271. availableNodes.push(edge.nodeTo_);
  272. }
  273. } else {
  274. newAvailableEdges.push(edge);
  275. }
  276. }
  277.  
  278. if (newAvailableEdges.length === availableEdges.length) {
  279. break;
  280. }
  281. availableEdges = newAvailableEdges;
  282. }
  283. return items.includes('Triforce');
  284. }
Add Comment
Please, Sign In to add comment