Advertisement
kolpastebin

Crimbo 2014 Mining.ash

Dec 9th, 2014
1,246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.26 KB | None | 0 0
  1. since r15020;
  2.  
  3. boolean setting_farm_tailings_after_fuel_rods = false; //This will intentionally farm out tailings once you have enough crimbonium to match the number of cylindrical molds you have. Almost certainly a bad idea with the mining oil change.
  4.  
  5. boolean setting_debug_one_at_a_time = false;
  6. /*
  7. WARNING: This script will use up all of your Oily Legs effect. It won't mine without that effect.
  8. This script will attempt to mine crimbonium as efficiently as it can, without spending turns.
  9. It targets the largest group of crimbonium it can find, and mines for that. Once there's no more crimbonium, it changes caverns.
  10. It also tries to avoid cave-ins on the way, but only if it's possible without taking a longer path.
  11. Will equip the xiblaxian holo-wrist-puter if necessary.
  12. It does have some ineffiencies - there are certain spots that will be more likely to contain crimbonium than others, in certain situations. But that would require a more complicated implementation so it doesn't do that. Apologies. (the exact situation is that you'd want to target spots that have more promising spots "behind" it, as they're more likely to be part of the group than edge pieces.)
  13.  
  14. It restores HP using Doc Galatik for ten meat. Seems the cheapest option.
  15.  
  16. Also the script outputs lots of debug text to watch.
  17.  
  18. This script is in the public domain.
  19. */
  20.  
  21. string [int][int] __mine_layout;
  22. //X, Y conversion formula is y * 8 + x
  23. //X and Y vary from 0 to 7, top-left dominate
  24. //Usable area is x = [1, 6] and y = [1, 7]
  25.  
  26. int mineComboPositionForXY(int x, int y)
  27. {
  28. return y * 8 + x;
  29. }
  30.  
  31. int abs(int v)
  32. {
  33. if (v < 0)
  34. return -v;
  35. return v;
  36. }
  37.  
  38. boolean mineComboPositionsAreAdjacent(int combo_position_1, int combo_position_2)
  39. {
  40. //Adjacent means above, below, left of, or right of.
  41.  
  42. int x_1 = combo_position_1 % 8;
  43. int x_2 = combo_position_2 % 8;
  44.  
  45. int y_1 = combo_position_1 / 8;
  46. int y_2 = combo_position_2 / 8;
  47.  
  48. if (y_1 == y_2)
  49. {
  50. //same row
  51. if (x_1 == x_2 - 1)
  52. return true;
  53. if (x_1 == x_2 + 1)
  54. return true;
  55. }
  56. if (x_1 == x_2)
  57. {
  58. //same column
  59. if (y_1 == y_2 - 1)
  60. return true;
  61. if (y_1 == y_2 + 1)
  62. return true;
  63. }
  64.  
  65. return false;
  66. }
  67.  
  68. int manhattanDistanceBetweenComboPositions(int combo_position_1, int combo_position_2)
  69. {
  70. int x_1 = combo_position_1 % 8;
  71. int x_2 = combo_position_2 % 8;
  72.  
  73. int y_1 = combo_position_1 / 8;
  74. int y_2 = combo_position_2 / 8;
  75.  
  76. return abs(x_2 - x_1) + abs(y_2 - y_1);
  77. }
  78.  
  79. void listAppend(string [int] list, string entry)
  80. {
  81. int position = list.count();
  82. while (list contains position)
  83. position += 1;
  84. list[position] = entry;
  85. }
  86.  
  87. void listAppend(int [int] list, int entry)
  88. {
  89. int position = list.count();
  90. while (list contains position)
  91. position += 1;
  92. list[position] = entry;
  93. }
  94.  
  95. void listAppend(int [int][int] list, int [int] entry)
  96. {
  97. int position = list.count();
  98. while (list contains position)
  99. position += 1;
  100. list[position] = entry;
  101. }
  102.  
  103. void listAppendList(int [int] list, int [int] entries)
  104. {
  105. foreach key in entries
  106. list.listAppend(entries[key]);
  107. }
  108.  
  109. boolean listEqualsList(int [int] l1, int [int] l2)
  110. {
  111. //if (l1 == l2) return true; //not sure how this works
  112. if (l1.count() != l2.count()) return false;
  113. foreach key, entry in l1
  114. {
  115. if (!(l2 contains key))
  116. return false;
  117. if (l1[key] != l2[key])
  118. return false;
  119. }
  120. return true;
  121. }
  122.  
  123. string listJoinComponents(string [int] list, string joining_string, string and_string)
  124. {
  125. buffer result;
  126. boolean first = true;
  127. int number_seen = 0;
  128. foreach i in list
  129. {
  130. if (first)
  131. {
  132. result.append(list[i]);
  133. first = false;
  134. }
  135. else
  136. {
  137. if (!(list.count() == 2 && and_string.length() > 0))
  138. result.append(joining_string);
  139. if (and_string.length() > 0 && number_seen == list.count() - 1)
  140. {
  141. result.append(" ");
  142. result.append(and_string);
  143. result.append(" ");
  144. }
  145. result.append(list[i]);
  146. }
  147. number_seen = number_seen + 1;
  148. }
  149. return result.to_string();
  150. }
  151.  
  152. string listJoinComponents(string [int] list, string joining_string)
  153. {
  154. return listJoinComponents(list, joining_string, "");
  155. }
  156.  
  157. void queryMineLayout(int mine_id)
  158. {
  159. string [int] base_layout;
  160.  
  161. string mine_page_text = visit_url("mining.php?mine=" + mine_id);
  162. string [int][int] page_matches = group_string(mine_page_text, "alt='([^\\(]*) \\(([0-7]),([0-7])\\)'");
  163.  
  164. if (page_matches.count() == 0)
  165. {
  166. abort("Unable to parse mine.");
  167. return;
  168. }
  169.  
  170. foreach key in page_matches
  171. {
  172. string [int] match = page_matches[key];
  173. string type = match[1];
  174. int x = match[2].to_int();
  175. int y = match[3].to_int();
  176. int a_converted_position_in_venice_italy = mineComboPositionForXY(x, y);
  177.  
  178. base_layout[a_converted_position_in_venice_italy] = type;
  179. //print_html("(" + x + ", " + y + " - " + a_converted_position_in_venice_italy + "): " + type);
  180. }
  181.  
  182. //Now the property:
  183. string layout_property_value = get_property("mineLayout" + mine_id);
  184.  
  185. string [int][int] layout_matches = layout_property_value.group_string("#([0-9]*)<img src=\"[^\"]*\" alt=\"([^\"]*)\"[^>]*>");
  186.  
  187. foreach key in layout_matches
  188. {
  189. string [int] match = layout_matches[key];
  190. int position = match[1].to_int();
  191. string type = match[2];
  192. //print_html(position + ": " + type);
  193. if (base_layout[position] != "Open Cavern")
  194. {
  195. abort("parse error");
  196. return;
  197. }
  198. base_layout[position] = type;
  199. }
  200.  
  201. __mine_layout[mine_id] = base_layout;
  202. //print_html("__mine_layout = " + __mine_layout.to_json());
  203. }
  204.  
  205. int [int][int] findSetMatches(int mine_id)
  206. {
  207. //FIXME other than nugget of Crimbonium
  208. int [int][int] area_sets;
  209. for y from 1 to 7
  210. {
  211. for x from 1 to 6
  212. {
  213. int combo_position = mineComboPositionForXY(x, y);
  214. string type = __mine_layout[mine_id][combo_position];
  215. if (!(type == "Promising Chunk of Wall" || type == "nugget of Crimbonium"))
  216. continue;
  217. //Make a single set of us. We'll combine later.
  218. int [int] single_set;
  219. single_set.listAppend(combo_position);
  220. area_sets.listAppend(single_set);
  221. }
  222. }
  223. //Combine sets that are adjacent to each other.
  224. while (true)
  225. {
  226. boolean should_combine = false;
  227. int c1_to_combine = -1;
  228. int c2_to_combine = -1;
  229. foreach c1_key1 in area_sets
  230. {
  231. foreach c1_key2 in area_sets[c1_key1]
  232. {
  233. int combo_position_1 = area_sets[c1_key1][c1_key2];
  234. foreach c2_key1 in area_sets
  235. {
  236. if (c2_key1 == c1_key1)
  237. continue;
  238. foreach c2_key2 in area_sets[c2_key1]
  239. {
  240. int combo_position_2 = area_sets[c2_key1][c2_key2];
  241. if (mineComboPositionsAreAdjacent(combo_position_1, combo_position_2))
  242. {
  243. should_combine = true;
  244. break;
  245. }
  246. }
  247. if (should_combine)
  248. {
  249. c1_to_combine = c1_key1;
  250. c2_to_combine = c2_key1;
  251. break;
  252. }
  253. }
  254. if (should_combine)
  255. break;
  256. }
  257. if (should_combine)
  258. break;
  259. }
  260. if (should_combine)
  261. {
  262. area_sets[c1_to_combine].listAppendList(area_sets[c2_to_combine]);
  263. remove area_sets[c2_to_combine];
  264. }
  265. else //no more
  266. break;
  267. }
  268.  
  269. //Re-order the keys properly:
  270. int [int][int] area_sets_result;
  271. foreach key in area_sets
  272. {
  273. area_sets_result.listAppend(area_sets[key]);
  274. }
  275. area_sets = area_sets_result;
  276.  
  277.  
  278. print_html("area_sets = " + area_sets.to_json());
  279. return area_sets;
  280. }
  281.  
  282. int [int][int] __flsm_area_sets;
  283. int [int] findLargestSetMatch(int mine_id)
  284. {
  285. int [int][int] area_sets = findSetMatches(mine_id);
  286. __flsm_area_sets = area_sets;
  287.  
  288. int largest_count = 0;
  289. foreach key in area_sets
  290. {
  291. largest_count = MAX(area_sets[key].count(), largest_count);
  292. }
  293. foreach key in area_sets
  294. {
  295. if (area_sets[key].count() == largest_count)
  296. return area_sets[key];
  297. }
  298.  
  299. int [int] empty;
  300. return empty;
  301. }
  302.  
  303. boolean [int] __probable_cave_ins;
  304. int [int] findNotYetMinedAreasOfCrimbonium()
  305. {
  306. boolean should_mine_out_area = (setting_farm_tailings_after_fuel_rods && $item[cylindrical mold].available_amount() <= $item[nugget of crimbonium].available_amount());
  307. if (true)
  308. {
  309. boolean [int] empty;
  310. __probable_cave_ins = empty;
  311. }
  312. int mine_id = 5;
  313.  
  314. int crimbonium_count = 0;
  315. for y from 1 to 7
  316. {
  317. for x from 1 to 6
  318. {
  319. int combo_position = mineComboPositionForXY(x, y);
  320. string type = __mine_layout[mine_id][combo_position];
  321. if (type != "nugget of Crimbonium")
  322. continue;
  323. crimbonium_count += 1;
  324. }
  325. }
  326. if (crimbonium_count >= 6 && !should_mine_out_area)
  327. {
  328. int [int] empty;
  329. return empty;
  330. }
  331.  
  332. int [int] largest_set_match = findLargestSetMatch(mine_id);
  333. print_html("largest_set_match = " + largest_set_match.to_json());
  334.  
  335.  
  336. //Find cave-ins:
  337. foreach key in __flsm_area_sets
  338. {
  339. if (listEqualsList(__flsm_area_sets[key], largest_set_match))
  340. {
  341. continue;
  342. }
  343. foreach key2, combo_position in __flsm_area_sets[key]
  344. {
  345. __probable_cave_ins[combo_position] = true;
  346. }
  347. }
  348. print_html("__probable_cave_ins = " + __probable_cave_ins.to_json());
  349.  
  350.  
  351. int [int] result;
  352. if (crimbonium_count < 6)
  353. {
  354. foreach key, combo_position in largest_set_match
  355. {
  356. string type = __mine_layout[mine_id][combo_position];
  357. if (type == "Promising Chunk of Wall")
  358. result.listAppend(combo_position);
  359.  
  360. }
  361. }
  362. if (should_mine_out_area && result.count() == 0)
  363. {
  364. for y from 1 to 7
  365. {
  366. for x from 1 to 6
  367. {
  368. int combo_position = mineComboPositionForXY(x, y);
  369. string type = __mine_layout[mine_id][combo_position];
  370. if ((type == "Rocky Wall") && !__probable_cave_ins[combo_position])
  371. result.listAppend(combo_position);
  372. }
  373. }
  374. }
  375.  
  376. return result;
  377. }
  378.  
  379. int [int] findEmptyMiningSpots(int mine_id)
  380. {
  381. int [int] results;
  382. for y from 1 to 7
  383. {
  384. for x from 1 to 6
  385. {
  386. int combo_position = mineComboPositionForXY(x, y);
  387. string type = __mine_layout[mine_id][combo_position];
  388. if (!(type == "Promising Chunk of Wall" || type == "Rocky Wall"))
  389. results.listAppend(combo_position);
  390. }
  391. }
  392. return results;
  393. }
  394.  
  395. int [int] pathFromSpotToSpot(int combo_position_1, int combo_position_2)
  396. {
  397. int [int] result;
  398. if (combo_position_1 == combo_position_2)
  399. return result;
  400.  
  401. int current_position = combo_position_1;
  402. int breakout = 100;
  403. while (current_position != combo_position_2 && breakout > 0)
  404. {
  405. breakout -= 1;
  406. int spot_x = combo_position_2 % 8;
  407. int empty_x = current_position % 8;
  408.  
  409. int spot_y = combo_position_2 / 8;
  410. int empty_y = current_position / 8;
  411.  
  412. int x_delta = spot_x - empty_x;
  413. int y_delta = spot_y - empty_y;
  414. if (y_delta < 0)
  415. {
  416. current_position = mineComboPositionForXY(empty_x, empty_y - 1);
  417. }
  418. else if (y_delta > 0)
  419. {
  420. current_position = mineComboPositionForXY(empty_x, empty_y + 1);
  421. }
  422. else if (x_delta < 0)
  423. {
  424. current_position = mineComboPositionForXY(empty_x - 1, empty_y);
  425. }
  426. else if (x_delta > 0)
  427. {
  428. current_position = mineComboPositionForXY(empty_x + 1, empty_y);
  429. }
  430. else
  431. break;
  432. result.listAppend(current_position);
  433. }
  434.  
  435. return result;
  436. }
  437.  
  438. int caveInCountFromSpotToSpot(int combo_position_1, int combo_position_2)
  439. {
  440. int cave_in_count = 0;
  441. int [int] path = pathFromSpotToSpot(combo_position_1, combo_position_2);
  442. foreach key, combo_position in path
  443. {
  444. if (__probable_cave_ins contains combo_position)
  445. cave_in_count += 1;
  446. }
  447. //print_html("shortest_path = " + path.to_json());
  448. //print_html("cave_in_count = " + cave_in_count);
  449. return cave_in_count;
  450. }
  451.  
  452. int pickPositionToMineToReachOneOfTheseSpots(int mine_id, int [int] spots)
  453. {
  454. //We go through each spot, and find the [spot, empty space] combination with the shortest manhattan distance.
  455. //Then pick the mining direction that heads towards that spot.
  456.  
  457. int [int] mine_empty_spots = findEmptyMiningSpots(mine_id);
  458. print_html("mine_empty_spots = " + mine_empty_spots.to_json());
  459.  
  460. int spot_position = -1;
  461. int empty_position = -1;
  462. int cached_manhattan_distance = -1;
  463. int cached_cave_ins = -1;
  464.  
  465. foreach key, combo_position_spot in spots
  466. {
  467. foreach key2, combo_position_empty in mine_empty_spots
  468. {
  469. int manhattan_distance = manhattanDistanceBetweenComboPositions(combo_position_spot, combo_position_empty);
  470. int cave_ins = -1;
  471.  
  472. boolean should_replace = false;
  473. if (cached_manhattan_distance == -1)
  474. should_replace = true;
  475. else if (manhattan_distance < cached_manhattan_distance)
  476. should_replace = true;
  477. else if (manhattan_distance == cached_manhattan_distance)
  478. {
  479. cave_ins = caveInCountFromSpotToSpot(combo_position_spot, combo_position_empty);
  480. if (cave_ins < cached_cave_ins)
  481. should_replace = true;
  482. }
  483.  
  484. if (should_replace)
  485. {
  486. spot_position = combo_position_spot;
  487. empty_position = combo_position_empty;
  488. cached_manhattan_distance = manhattan_distance;
  489. if (cave_ins == -1)
  490. cave_ins = caveInCountFromSpotToSpot(combo_position_spot, combo_position_empty);
  491. cached_cave_ins = cave_ins;
  492. }
  493. }
  494. }
  495.  
  496. print_html("Best combination from " + empty_position + " to " + spot_position + " (distance " + cached_manhattan_distance + ", " + cached_cave_ins + " known cave-ins)");
  497. //Now determine how to mine for that:
  498.  
  499. int spot_x = spot_position % 8;
  500. int empty_x = empty_position % 8;
  501.  
  502. int spot_y = spot_position / 8;
  503. int empty_y = empty_position / 8;
  504.  
  505. int x_delta = spot_x - empty_x;
  506. int y_delta = spot_y - empty_y;
  507.  
  508. //print_html("x_delta = " + x_delta + ", y_delta = " + y_delta);
  509. //Very simple. Mine up, then across:
  510. if (y_delta < 0)
  511. {
  512. return mineComboPositionForXY(empty_x, empty_y - 1);
  513. }
  514. else if (y_delta > 0)
  515. {
  516. return mineComboPositionForXY(empty_x, empty_y + 1);
  517. }
  518. else if (x_delta < 0)
  519. {
  520. return mineComboPositionForXY(empty_x - 1, empty_y);
  521. }
  522. else if (x_delta > 0)
  523. {
  524. return mineComboPositionForXY(empty_x + 1, empty_y);
  525. }
  526.  
  527. return -1;
  528. }
  529.  
  530. void HPCheck()
  531. {
  532. if (my_hp() == 0)
  533. {
  534. if (my_meat() < 10)
  535. {
  536. abort("No meat to restore HP to mine.");
  537. return;
  538. }
  539. cli_execute("galaktik hp 1");
  540. }
  541. }
  542.  
  543. boolean __need_to_switch_to_backup = false;
  544. boolean __mining_init_inited = false;
  545. void MiningInit()
  546. {
  547. if (__mining_init_inited)
  548. return;
  549. __mining_init_inited = true;
  550.  
  551. if (!is_wearing_outfit("High-Radiation Mining Gear"))
  552. {
  553. if (!have_outfit("High-Radiation Mining Gear"))
  554. {
  555. abort("Need High-Radiation Mining Gear outfit first.");
  556. return;
  557. }
  558. __need_to_switch_to_backup = true;
  559. cli_execute("outfit save Backup");
  560. cli_execute("outfit High-Radiation Mining Gear");
  561. }
  562. if (!is_wearing_outfit("High-Radiation Mining Gear"))
  563. {
  564. if (__need_to_switch_to_backup)
  565. cli_execute("outfit Backup");
  566. abort("Unable to wear mining gear?");
  567. return;
  568. }
  569.  
  570. if ($item[xiblaxian holo-wrist-puter].available_amount() > 0 && $item[xiblaxian holo-wrist-puter].equipped_amount() == 0)
  571. {
  572. if (!__need_to_switch_to_backup)
  573. {
  574. cli_execute("outfit save Backup");
  575. __need_to_switch_to_backup = true;
  576. }
  577. cli_execute("equip acc1 xiblaxian holo-wrist-puter");
  578. }
  579. }
  580.  
  581. void main()
  582. {
  583. if (my_inebriety() > inebriety_limit())
  584. {
  585. print_html("You are too mine to drunk.");
  586. return;
  587. }
  588. int starting_adventures = my_adventures();
  589. HPCheck();
  590. boolean just_tried_changing_cavern = false;
  591.  
  592. int starting_oily_legs_turns = $effect[oily legs].have_effect();
  593.  
  594. boolean [item] items_to_track = $items[peppermint tailings, nugget of crimbonium, xiblaxian crystal];
  595.  
  596. int [item] starting_item_amounts;
  597. foreach it in items_to_track
  598. {
  599. starting_item_amounts[it] = it.item_amount();
  600. }
  601.  
  602. int dynamite_closeted = 0;
  603. if ($item[minin' dynamite].item_amount() > 0) //'
  604. {
  605. print_html("Closeting minin' dynamite for safety...");
  606. dynamite_closeted = $item[minin' dynamite].item_amount();
  607. put_closet(dynamite_closeted, $item[minin' dynamite]);
  608. }
  609.  
  610. int max_loops = $effect[oily legs].have_effect() * 2 + 1;
  611.  
  612. while ($effect[oily legs].have_effect() > 0 && ($effect[crimbonar].have_effect() > 0 || $effect[object detection].have_effect() > 0) && max_loops > 0)
  613. {
  614. max_loops -= 1;
  615. if (my_adventures() != starting_adventures) //in case effect tracking is off
  616. {
  617. print_html("We spent a turn by accident! Apologies. Stopping.");
  618. break;
  619. }
  620. MiningInit();
  621. queryMineLayout(5);
  622.  
  623. int [int] areas_still_to_mine = findNotYetMinedAreasOfCrimbonium();
  624. print_html("areas_still_to_mine = " + areas_still_to_mine.to_json());
  625. if (areas_still_to_mine.count() == 0)
  626. {
  627. if (setting_debug_one_at_a_time)
  628. {
  629. print_html("Time to change caverns.");
  630. break;
  631. }
  632. if (just_tried_changing_cavern)
  633. {
  634. abort("Problems changing cavern.");
  635. return;
  636. }
  637. print_html("Changing caverns...");
  638. visit_url("mining.php?mine=5&reset=1&pwd");
  639. just_tried_changing_cavern = true;
  640. continue;
  641. }
  642. just_tried_changing_cavern = false;
  643.  
  644. int mining_position = pickPositionToMineToReachOneOfTheseSpots(5, areas_still_to_mine);
  645. if (mining_position < 0)
  646. {
  647. abort("Unable to find a spot to mine. Apologies.");
  648. return;
  649. }
  650. print_html("mining_position = " + mining_position);
  651. visit_url("mining.php?mine=5&which=" + mining_position + "&pwd");
  652. HPCheck();
  653. if (setting_debug_one_at_a_time)
  654. break;
  655. }
  656. if (__need_to_switch_to_backup)
  657. cli_execute("outfit Backup");
  658.  
  659. string [int] found_types;
  660. foreach it in items_to_track
  661. {
  662. int amount_gained = it.item_amount() - starting_item_amounts[it];
  663. if (amount_gained <= 0)
  664. continue;
  665. if (amount_gained == 1)
  666. found_types.listAppend(amount_gained + " " + it);
  667. else
  668. found_types.listAppend(amount_gained + " " + it.plural);
  669. }
  670. if (found_types.count() > 0)
  671. {
  672. string line = "Found " + found_types.listJoinComponents(", ", "and") + " over " + starting_oily_legs_turns + " mining attempt";
  673. if (starting_oily_legs_turns > 1)
  674. line += "s";
  675. line += ".";
  676. print_html(line);
  677. }
  678.  
  679. if (dynamite_closeted > 0)
  680. {
  681. take_closet(dynamite_closeted, $item[minin' dynamite]); //'
  682. }
  683. if ($effect[oily legs].have_effect() == 0)
  684. print_html("Out of the oily legs effect.");
  685. else if (!($effect[crimbonar].have_effect() > 0 || $effect[object detection].have_effect() > 0))
  686. print_html("Out of the crimbonar/object detection effect.");
  687. if ($item[flask of mining oil].available_amount() > 0)
  688. print_html($item[flask of mining oil].available_amount() + " flasks of mining oil available. Use them for more mining!");
  689. else
  690. print_html("Head to the mining camp for more mining oil.");
  691. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement