Advertisement
Guest User

Tainted code

a guest
Dec 20th, 2014
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 40.39 KB | None | 0 0
  1. //Simulates the KOL Crimbo 2014 factory. Poorly...
  2. //This source code is in the public domain.
  3. #include <iostream>
  4. #include <vector>
  5. #include <map>
  6. #include <thread>
  7. #include <random>
  8. #include <chrono> //! crono! wake up, crono!
  9. #include <queue>
  10.  
  11. const bool setting_simulate_schematics_as_well = false;
  12. const int setting_simulate_floor_min = 1;
  13. const int setting_simulate_floor_max = 3;
  14.  
  15. enum class robot_capability
  16. {
  17. blam,
  18. light,
  19. pow,
  20. roll,
  21. run,
  22. zap,
  23. hover,
  24. lube,
  25. pinch,
  26. decode,
  27. freeze,
  28. MAX_CAPABILITY
  29. };
  30.  
  31. //This should be changed to use a fixed array, from 0 to MAX_CAPABILITY. Much faster that way, but slightly unsafe.
  32. class RobotCapabilities
  33. {
  34. public:
  35. void addCapability(const robot_capability & capability);
  36. void addCapabilities(const RobotCapabilities & capabilities_other);
  37. bool hasCapability(const robot_capability & capability) const;
  38. int capabilityAmount(const robot_capability & capability) const;
  39. bool capabilityWillFulfillOurs(const RobotCapabilities & capabilities_other) const;
  40. private:
  41. std::map <robot_capability,int> capabilities_map;
  42. };
  43.  
  44. void RobotCapabilities::addCapability(const robot_capability & capability)
  45. {
  46. capabilities_map[capability] += 1;
  47. }
  48.  
  49. void RobotCapabilities::addCapabilities(const RobotCapabilities & capabilities_other)
  50. {
  51. for (auto & iterator : capabilities_other.capabilities_map)
  52. {
  53. capabilities_map[iterator.first] += iterator.second;
  54. }
  55. }
  56.  
  57. bool RobotCapabilities::hasCapability(const robot_capability & capability) const
  58. {
  59. return capabilityAmount(capability) > 0;
  60. }
  61.  
  62. int RobotCapabilities::capabilityAmount(const robot_capability & capability) const
  63. {
  64. if (capabilities_map.count(capability) == 0)
  65. return 0;
  66. return capabilities_map.find(capability)->second;
  67. }
  68.  
  69. bool RobotCapabilities::capabilityWillFulfillOurs(const RobotCapabilities & capabilities_other) const
  70. {
  71. for (auto & iterator : capabilities_map)
  72. {
  73. if (capabilities_other.capabilityAmount(iterator.first) < iterator.second)
  74. return false;
  75. }
  76. return true;
  77. }
  78.  
  79.  
  80. struct SimulationStateMutable
  81. {
  82. SimulationStateMutable() : current_hp(0), schematics_recovered(0), items_recovered(0), room(0) {}
  83. int current_hp;
  84. int schematics_recovered;
  85. int items_recovered;
  86. int room;
  87. };
  88.  
  89. struct SimulationStateFixed
  90. {
  91. template <typename ... T>
  92. SimulationStateFixed(const int base_hp_in, const T & ... capabilities); //capabilities must be of type robot_capability
  93. int base_hp;
  94. RobotCapabilities capabilities;
  95. int chosen_floor;
  96. int chosen_maze_strategy_1; //for floor 2, 1 means up, 2 means down
  97. bool choose_parts_over_schematics;
  98.  
  99. void addToCapabilities(const SimulationStateFixed & other);
  100.  
  101. };
  102.  
  103. template <typename ... T>
  104. SimulationStateFixed::SimulationStateFixed(const int base_hp_in, const T & ... capabilities_in) : base_hp(base_hp_in)
  105. {
  106. chosen_maze_strategy_1 = 1;
  107. choose_parts_over_schematics = false;
  108. const robot_capability capabilities_in_array[] = { capabilities_in... };
  109. for (robot_capability capability : capabilities_in_array)
  110. {
  111. capabilities.addCapability(capability);
  112. }
  113. }
  114.  
  115. void SimulationStateFixed::addToCapabilities(const SimulationStateFixed & other)
  116. {
  117. base_hp += other.base_hp;
  118. capabilities.addCapabilities(other.capabilities);
  119. }
  120.  
  121. struct RoomOption
  122. {
  123. RoomOption() : schematics_given(0), parts_given(0), minimum_hp_damage_dealt(0), maximum_hp_damage_dealt(0) {}
  124.  
  125. template <typename ... T>
  126. RoomOption(int schematics_given_in, int parts_given_in, int hp_damage_dealt_in, T ... capabilities); //capabilities must be of type robot_capability
  127. template <typename ... T>
  128. RoomOption(int schematics_given_in, int parts_given_in, int minimum_hp_damage_dealt_in, int maximum_hp_damage_dealt_in, T ... capabilities);
  129.  
  130. RobotCapabilities required_capabilities;
  131. int schematics_given;
  132. int parts_given;
  133. int minimum_hp_damage_dealt;
  134. int maximum_hp_damage_dealt;
  135.  
  136. bool capableOfChoosingChoice(const RobotCapabilities & with_capabilities) const;
  137. int capabilities[static_cast<int>(robot_capability::MAX_CAPABILITY)];
  138. };
  139.  
  140. template <typename ... T>
  141. RoomOption::RoomOption(int schematics_given_in, int parts_given_in, int hp_damage_dealt_in, T ... capabilities_in) : schematics_given(schematics_given_in), parts_given(parts_given_in), minimum_hp_damage_dealt(hp_damage_dealt_in), maximum_hp_damage_dealt(hp_damage_dealt_in)
  142. {
  143. const robot_capability capabilities_in_array[] = { capabilities_in... };
  144. for (robot_capability capability : capabilities_in_array)
  145. {
  146. required_capabilities.addCapability(capability);
  147. }
  148. }
  149.  
  150. template <typename ... T>
  151. RoomOption::RoomOption(int schematics_given_in, int parts_given_in, int minimum_hp_damage_dealt_in, int maximum_hp_damage_dealt_in, T ... capabilities_in) : schematics_given(schematics_given_in), parts_given(parts_given_in), minimum_hp_damage_dealt(minimum_hp_damage_dealt_in), maximum_hp_damage_dealt(maximum_hp_damage_dealt_in)
  152. {
  153.  
  154. const robot_capability capabilities_in_array[] = { capabilities_in... };
  155. for (robot_capability capability : capabilities_in_array)
  156. {
  157. required_capabilities.addCapability(capability);
  158. }
  159. }
  160.  
  161.  
  162. bool RoomOption::capableOfChoosingChoice(const RobotCapabilities & with_capabilities) const
  163. {
  164. return required_capabilities.capabilityWillFulfillOurs(with_capabilities);
  165. }
  166.  
  167. struct Room
  168. {
  169. Room();
  170. Room(std::string name_in, const std::vector <RoomOption> & options_in) : name(name_in), options(options_in) {}
  171. std::vector <RoomOption> options;
  172. std::string name;
  173. };
  174.  
  175. struct RoomCollection
  176. {
  177. std::vector <Room> potential_rooms;
  178. };
  179.  
  180. struct FactoryLayout
  181. {
  182. std::map <int, RoomCollection> first_area_layout; //room number - 2 is the start
  183. std::map <int, RoomCollection> second_area_layout_up_path;
  184. std::map <int, RoomCollection> second_area_layout_down_path;
  185. std::map <int, RoomCollection> third_area_layout;
  186. };
  187.  
  188.  
  189. enum class robot_part_location
  190. {
  191. left_arm,
  192. right_arm,
  193. torso,
  194. propulsion
  195. };
  196.  
  197. struct RobotPart
  198. {
  199. RobotPart(const std::string & name_in, const robot_part_location & location_in, const SimulationStateFixed & capability_modifiers_in) : name(name_in), location(location_in), capability_modifiers(capability_modifiers_in) {}
  200. std::string name;
  201. robot_part_location location;
  202. SimulationStateFixed capability_modifiers;
  203. };
  204. struct possible_outcome
  205. {
  206. double probability;
  207. int hp;
  208. double schematics;
  209. double items;
  210. };
  211.  
  212. void simulateOnce(std::mt19937 & rng_generator, const FactoryLayout & factory_layout, const SimulationStateFixed & fixed_state, int * parts_found_out, int * schematics_found_out, int * room_ended_at_out)
  213. {
  214. //Note that it would be much faster to replace area_layout with a pre-computed vector that already knows which options we can choose. By around 30%.
  215. //But, that can cause simulation error if not done properly, so...
  216. SimulationStateMutable state = SimulationStateMutable();
  217. state.current_hp = fixed_state.base_hp;
  218. state.room = 2;
  219.  
  220. const std::map <int, RoomCollection> * area_layout = &factory_layout.first_area_layout;
  221. if (fixed_state.chosen_floor == 2)
  222. {
  223. if (fixed_state.chosen_maze_strategy_1 == 1)
  224. area_layout = &factory_layout.second_area_layout_up_path;
  225. else
  226. area_layout = &factory_layout.second_area_layout_down_path;
  227. }
  228. if (fixed_state.chosen_floor == 3)
  229. area_layout = &factory_layout.third_area_layout;
  230.  
  231. const bool output_debug = false;
  232.  
  233. if (output_debug)
  234. printf("-\n");
  235. while (state.current_hp > 0)
  236. {
  237. if (area_layout->count(state.room) == 0)
  238. {
  239. break;
  240. }
  241. const RoomCollection & room_collection = area_layout->find(state.room)->second;
  242.  
  243. if (room_collection.potential_rooms.size() == 0)
  244. {
  245. printf("INTERNAL ERROR: Room collection too small.\n");
  246. break;
  247. }
  248. //Generate a room:
  249. //int picked_id = random() % room_collection.potential_rooms.size();
  250.  
  251. int picked_id = std::uniform_int_distribution<>(0, (int)room_collection.potential_rooms.size() - 1)(rng_generator);
  252. const Room & current_room = room_collection.potential_rooms[picked_id];
  253.  
  254. const RoomOption * chosen_option = 0;
  255. int chosen_option_score = 0;
  256. for (const RoomOption & option : current_room.options)
  257. {
  258. if (!option.capableOfChoosingChoice(fixed_state.capabilities))
  259. continue;
  260. bool is_better = false;
  261.  
  262. int score = 0;
  263. if (fixed_state.choose_parts_over_schematics)
  264. {
  265. score += option.parts_given * 100;
  266. score += option.schematics_given * 10;
  267. }
  268. else
  269. {
  270. score += option.parts_given * 10;
  271. score += option.schematics_given * 100;
  272. }
  273. score -= (option.minimum_hp_damage_dealt + option.maximum_hp_damage_dealt);
  274.  
  275. //Is this better?
  276. if (!chosen_option)
  277. is_better = true;
  278. else if (score > chosen_option_score)
  279. is_better = true;
  280.  
  281. if (is_better)
  282. {
  283. chosen_option = &option;
  284. chosen_option_score = score;
  285. }
  286. }
  287. if (output_debug)
  288. printf("\tOn room %i. HP is %i.\n", state.room, state.current_hp);
  289. if (!chosen_option)
  290. {
  291. printf("INTERNAL ERROR: No option.\n");
  292. break;
  293. }
  294. if (chosen_option->parts_given > 0)
  295. *parts_found_out += chosen_option->parts_given;
  296. if (chosen_option->schematics_given > 0)
  297. *schematics_found_out += chosen_option->schematics_given;
  298. if (chosen_option->maximum_hp_damage_dealt != 0)
  299. {
  300. if (output_debug)
  301. printf("\t\tGenerating random HP damage in range [%i, %i]\n", chosen_option->minimum_hp_damage_dealt, chosen_option->maximum_hp_damage_dealt);
  302. int damage_done = std::uniform_int_distribution<>(chosen_option->minimum_hp_damage_dealt, chosen_option->maximum_hp_damage_dealt)(rng_generator);
  303. state.current_hp -= damage_done;
  304. if (output_debug)
  305. printf("\t\tTook %i damage.\n", damage_done);
  306. }
  307.  
  308. if (state.current_hp > 0)
  309. state.room += 1;
  310. }
  311.  
  312. *room_ended_at_out = state.room;
  313. }
  314.  
  315.  
  316. std::vector<possible_outcome> estimateRoom( const FactoryLayout & factory_layout, const SimulationStateFixed & fixed_state, int room, possible_outcome currentState)
  317. {
  318. //Note that it would be much faster to replace area_layout with a pre-computed vector that already knows which options we can choose. By around 30%.
  319. //But, that can cause simulation error if not done properly, so...
  320. std::vector<possible_outcome> ret;
  321. bool output_debug=false;
  322. SimulationStateMutable state = SimulationStateMutable();
  323. state.current_hp = fixed_state.base_hp;
  324. state.room = room+2;
  325.  
  326. const std::map <int, RoomCollection> * area_layout = &factory_layout.first_area_layout;
  327. if (fixed_state.chosen_floor == 2)
  328. {
  329. if (fixed_state.chosen_maze_strategy_1 == 1)
  330. area_layout = &factory_layout.second_area_layout_up_path;
  331. else
  332. area_layout = &factory_layout.second_area_layout_down_path;
  333. }
  334. if (fixed_state.chosen_floor == 3)
  335. area_layout = &factory_layout.third_area_layout;
  336.  
  337.  
  338.  
  339. const RoomCollection & room_collection = area_layout->find(state.room)->second;
  340. if (area_layout->count(state.room) == 0)
  341. {
  342. return ret;
  343. }
  344. if (room_collection.potential_rooms.size() == 0)
  345. {
  346. printf("INTERNAL ERROR: Room collection too small.\n");
  347. return ret;
  348. }
  349. double room_probability=1.0/(double)room_collection.potential_rooms.size();
  350. for(unsigned int i=0;i<room_collection.potential_rooms.size();i++)
  351. {
  352. const Room & current_room = room_collection.potential_rooms[i];
  353. int chosen_option_score = 0;
  354. const RoomOption * chosen_option = 0;
  355.  
  356. for (const RoomOption & option : current_room.options)
  357. {
  358. if (!option.capableOfChoosingChoice(fixed_state.capabilities))
  359. continue;
  360. bool is_better = false;
  361.  
  362. int score = 0;
  363. if (fixed_state.choose_parts_over_schematics)
  364. {
  365. score += option.parts_given * 100;
  366. score += option.schematics_given * 10;
  367. }
  368. else
  369. {
  370. score += option.parts_given * 10;
  371. score += option.schematics_given * 100;
  372. }
  373. score -= (option.minimum_hp_damage_dealt + option.maximum_hp_damage_dealt);
  374.  
  375. //Is this better?
  376. if (!chosen_option)
  377. is_better = true;
  378. else if (score > chosen_option_score)
  379. is_better = true;
  380.  
  381. if (is_better)
  382. {
  383. chosen_option = &option;
  384. chosen_option_score = score;
  385. }
  386. }
  387. if (output_debug)
  388. printf("\tOn room %i. HP is %i.\n", state.room, state.current_hp);
  389. if (!chosen_option)
  390. {
  391. printf("INTERNAL ERROR: No option.\n");
  392. return ret;
  393. }
  394. double num_damages=1.0/(double)(chosen_option->maximum_hp_damage_dealt-chosen_option->minimum_hp_damage_dealt+1);
  395. for(int i=chosen_option->minimum_hp_damage_dealt;i<=chosen_option->maximum_hp_damage_dealt;i++)
  396. {
  397. possible_outcome newOutcome=possible_outcome();
  398. newOutcome.hp=currentState.hp-i;
  399. newOutcome.probability=currentState.probability*room_probability*num_damages;
  400. newOutcome.schematics=currentState.schematics+chosen_option->schematics_given;
  401. newOutcome.items=currentState.items+chosen_option->parts_given;
  402. ret.push_back(newOutcome);
  403. }
  404. }
  405. return ret;
  406. }
  407.  
  408. std::vector<possible_outcome> collapseTreeByHP(std::vector<possible_outcome> tree)
  409. {
  410. std::map <int,possible_outcome> temp;
  411. std::vector <possible_outcome> ret;
  412. for(std::vector<possible_outcome>::size_type i = 0; i != tree.size(); i++)
  413. {
  414. std::map<int,possible_outcome>::iterator fnd=temp.find(tree[i].hp);
  415. if(fnd==temp.end())//not found
  416. {
  417. possible_outcome nil;
  418. nil.hp=tree[i].hp;
  419. nil.probability=0;
  420. nil.schematics=0;
  421. nil.items=0;
  422. temp[tree[i].hp]=nil;
  423. }
  424. temp[tree[i].hp].probability+=tree[i].probability;
  425. temp[tree[i].hp].schematics+=tree[i].probability*tree[i].schematics;
  426. temp[tree[i].hp].items+=tree[i].probability*tree[i].items;
  427. }
  428.  
  429. for( std::map <int,possible_outcome> ::iterator it = temp.begin(); it != temp.end(); ++it ) {
  430. possible_outcome to_adj=it->second;
  431. to_adj.items/=to_adj.probability;
  432. to_adj.schematics/=to_adj.probability;
  433. ret.push_back(to_adj );
  434. }
  435. return ret;
  436. }
  437. void simulateAllAndOutput(const FactoryLayout & factory_layout, const unsigned int simulation_count, const RobotPart & part_left_arm, const RobotPart & part_right_arm, const RobotPart & part_torso, const RobotPart & part_propulsion, const int floor_in, const int maze_strategy_in, const bool pick_parts_over_schematics)
  438. {
  439. //Create state for this set of parts:
  440. SimulationStateFixed fixed_state = SimulationStateFixed(0);
  441. fixed_state.addToCapabilities(part_left_arm.capability_modifiers);
  442. fixed_state.addToCapabilities(part_right_arm.capability_modifiers);
  443. fixed_state.addToCapabilities(part_torso.capability_modifiers);
  444. fixed_state.addToCapabilities(part_propulsion.capability_modifiers);
  445. fixed_state.chosen_floor = floor_in;
  446. fixed_state.chosen_maze_strategy_1 = maze_strategy_in;
  447. fixed_state.choose_parts_over_schematics = pick_parts_over_schematics;
  448.  
  449. if (fixed_state.chosen_floor == 2 && !fixed_state.capabilities.hasCapability(robot_capability::pinch))
  450. {
  451. return;
  452. }
  453. if (fixed_state.chosen_floor == 3 && !fixed_state.capabilities.hasCapability(robot_capability::decode))
  454. {
  455. return;
  456. }
  457.  
  458. std::vector <int> total_rooms_ended_at_frequency;
  459. std::mt19937 rng_generator = std::mt19937(std::chrono::high_resolution_clock::now().time_since_epoch().count());
  460. uint64_t total_parts_found = 0;
  461. uint64_t total_schematics_found = 0;
  462. uint64_t total_rooms_ended_at = 0;
  463. //Run simulation:
  464. std::vector <possible_outcome> tree;
  465. possible_outcome root;
  466. root.probability=1;
  467. root.hp=fixed_state.base_hp;
  468. root.schematics=0;
  469. root.items=0;
  470. tree.push_back(root);
  471.  
  472. int croom=0;
  473. double average_parts_found = 0;
  474. double average_schematics_found = 0;
  475. double average_rooms_ended_at = 0;
  476. int furtherest_room_ended_at = 0;
  477. double chance_of_last_room =0;
  478. while(tree.size()>0)
  479. {
  480. furtherest_room_ended_at++;
  481. croom++;
  482. std::vector <possible_outcome> newTree;
  483. chance_of_last_room =0;
  484. //go forward one room, checking for all possibilities
  485. for(std::vector<possible_outcome>::size_type i = 0; i != tree.size(); i++)
  486. {
  487. chance_of_last_room+=tree[i].probability;
  488. std::vector<possible_outcome> newOnes=estimateRoom( factory_layout, fixed_state, croom, tree[i]);
  489. // printf("NewSize: %d\n",newOnes.size());
  490. newTree.insert(newTree.end(),newOnes.begin(),newOnes.end());
  491. }
  492. newTree=collapseTreeByHP(newTree);
  493. tree.clear();
  494. for(std::vector<possible_outcome>::size_type i = 0; i != newTree.size(); i++)
  495. {
  496. if(newTree[i].hp<=0)//we are dead, collect results
  497. {
  498. average_parts_found+=newTree[i].items*newTree[i].probability;
  499. average_schematics_found+=newTree[i].schematics*newTree[i].probability;
  500. average_rooms_ended_at=croom*newTree[i].probability;
  501. }
  502. else //still ok, go to next round
  503. {
  504. tree.push_back(newTree[i]);
  505. }
  506. }
  507.  
  508. }
  509.  
  510.  
  511. std::string strategy_string = "N/A";
  512. if (fixed_state.chosen_floor == 2)
  513. {
  514. if (fixed_state.chosen_maze_strategy_1 == 1)
  515. strategy_string = "ascend";
  516. else
  517. strategy_string = "descend";
  518. }
  519.  
  520. std::string parts_or_schematics;
  521. if (fixed_state.choose_parts_over_schematics)
  522. parts_or_schematics = "parts";
  523. else
  524. parts_or_schematics = "schematics";
  525.  
  526. printf("%i\t%s\t%s\t%s\t%s\t%s\t%s\t%f\t%f\t%f\t%i\t%f\n", fixed_state.chosen_floor, strategy_string.c_str(), parts_or_schematics.c_str(), part_left_arm.name.c_str(), part_right_arm.name.c_str(), part_torso.name.c_str(), part_propulsion.name.c_str(), average_parts_found, average_schematics_found, average_rooms_ended_at, furtherest_room_ended_at, chance_of_last_room);
  527. }
  528.  
  529. int main(int argc, const char * argv[])
  530. {
  531. auto start_time = std::chrono::high_resolution_clock::now();
  532. std::map <robot_part_location, std::vector <RobotPart> > parts_list;
  533. for (robot_part_location location : {robot_part_location::left_arm, robot_part_location::right_arm, robot_part_location::torso, robot_part_location::propulsion})
  534. {
  535. parts_list[location] = std::vector<RobotPart>();
  536. }
  537.  
  538. {
  539. std::vector <RobotPart> parts_list_creating;
  540.  
  541. parts_list_creating.push_back(RobotPart("Tiny Fist", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::pow)));
  542. parts_list_creating.push_back(RobotPart("Bug Zapper", robot_part_location::left_arm, SimulationStateFixed(1,robot_capability::zap)));
  543. parts_list_creating.push_back(RobotPart("Rodent Gun", robot_part_location::left_arm, SimulationStateFixed(0,robot_capability::blam)));
  544. parts_list_creating.push_back(RobotPart("Rivet Shocker", robot_part_location::left_arm, SimulationStateFixed(0,robot_capability::zap,robot_capability::pow)));
  545. parts_list_creating.push_back(RobotPart("Mega Vise", robot_part_location::left_arm, SimulationStateFixed(0,robot_capability::pow,robot_capability::pow)));
  546. parts_list_creating.push_back(RobotPart("Mobile Girder", robot_part_location::left_arm, SimulationStateFixed(3)));
  547. parts_list_creating.push_back(RobotPart("Swiss Arm", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::pow, robot_capability::blam, robot_capability::zap)));
  548.  
  549. parts_list_creating.push_back(RobotPart("Ball-Bearing Dispenser", robot_part_location::right_arm, SimulationStateFixed(0, robot_capability::blam)));
  550. parts_list_creating.push_back(RobotPart("Power Arm", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::zap)));
  551. parts_list_creating.push_back(RobotPart("Wrecking Ball", robot_part_location::right_arm, SimulationStateFixed(1,robot_capability::pow)));
  552. parts_list_creating.push_back(RobotPart("Ribbon Manipulator", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::pinch)));
  553. parts_list_creating.push_back(RobotPart("Grease / Regular Gun", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::lube,robot_capability::blam)));
  554. parts_list_creating.push_back(RobotPart("Grease Gun", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::lube)));
  555. parts_list_creating.push_back(RobotPart("Power Stapler", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::zap, robot_capability::pinch)));
  556. parts_list_creating.push_back(RobotPart("Snow Blower", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::freeze)));
  557.  
  558. parts_list_creating.push_back(RobotPart("Basic Head", robot_part_location::torso, SimulationStateFixed(3)));
  559. parts_list_creating.push_back(RobotPart("Gun Face", robot_part_location::torso, SimulationStateFixed(3,robot_capability::blam)));
  560. parts_list_creating.push_back(RobotPart("Big Head", robot_part_location::torso, SimulationStateFixed(4)));
  561. parts_list_creating.push_back(RobotPart("Security Chassis", robot_part_location::torso, SimulationStateFixed(3,robot_capability::light)));
  562. parts_list_creating.push_back(RobotPart("Military Chassis", robot_part_location::torso, SimulationStateFixed(3,robot_capability::light,robot_capability::blam)));
  563. parts_list_creating.push_back(RobotPart("Crab Core", robot_part_location::torso, SimulationStateFixed(4,robot_capability::pinch)));
  564. parts_list_creating.push_back(RobotPart("Cyclopean Torso", robot_part_location::torso, SimulationStateFixed(4,robot_capability::light)));
  565. parts_list_creating.push_back(RobotPart("Dynamo Head", robot_part_location::torso, SimulationStateFixed(4,robot_capability::zap)));
  566.  
  567. parts_list_creating.push_back(RobotPart("Regular Legs", robot_part_location::propulsion, SimulationStateFixed(0, robot_capability::run)));
  568. parts_list_creating.push_back(RobotPart("Heavy-Duty Legs", robot_part_location::propulsion, SimulationStateFixed(1, robot_capability::run)));
  569. parts_list_creating.push_back(RobotPart("Tripod Legs", robot_part_location::propulsion, SimulationStateFixed(0,robot_capability::run,robot_capability::run)));
  570. parts_list_creating.push_back(RobotPart("Rollerfeet", robot_part_location::propulsion, SimulationStateFixed(0,robot_capability::run,robot_capability::roll)));
  571. parts_list_creating.push_back(RobotPart("Hoverjack", robot_part_location::propulsion, SimulationStateFixed(2,robot_capability::hover)));
  572. parts_list_creating.push_back(RobotPart("Sim-Simian Feet", robot_part_location::propulsion, SimulationStateFixed(0,robot_capability::run, robot_capability::pinch)));
  573. parts_list_creating.push_back(RobotPart("High-Speed Fan", robot_part_location::propulsion, SimulationStateFixed(1,robot_capability::hover)));
  574. parts_list_creating.push_back(RobotPart("Big Wheel", robot_part_location::propulsion, SimulationStateFixed(0, robot_capability::roll, robot_capability::roll)));
  575.  
  576. for (RobotPart part : parts_list_creating)
  577. {
  578. parts_list[part.location].push_back(part);
  579. }
  580. }
  581.  
  582. FactoryLayout factory_layout = FactoryLayout();
  583. {
  584. RoomCollection collection_bot;
  585. RoomCollection collection_obstacle_t1;
  586. RoomCollection collection_obstacle_t2;
  587. RoomCollection collection_reward;
  588.  
  589.  
  590. collection_bot.potential_rooms.push_back(Room("Zippybot", {RoomOption(0, 0, 0, robot_capability::zap), RoomOption(0, 0, 1)}));
  591. collection_bot.potential_rooms.push_back(Room("Turretbot", {RoomOption(0, 0, 0, robot_capability::blam), RoomOption(0, 0, 1)}));
  592. collection_bot.potential_rooms.push_back(Room("Mookbot", {RoomOption(0, 0, 0, robot_capability::blam), RoomOption(0, 0, 0, robot_capability::pow), RoomOption(0, 0, 1)}));
  593. collection_bot.potential_rooms.push_back(Room("Doorbot", {RoomOption(0, 0, 0, robot_capability::pow), RoomOption(0, 0, 0, robot_capability::zap), RoomOption(0, 0, 1)}));
  594. collection_bot.potential_rooms.push_back(Room("Bulkybot", {RoomOption(0, 0, 0, robot_capability::pow), RoomOption(0, 0, 1)}));
  595. collection_bot.potential_rooms.push_back(Room("Security Drone", {RoomOption(0, 0, 0, robot_capability::blam), RoomOption(0, 0, 0, robot_capability::zap), RoomOption(0, 0, 1)}));
  596.  
  597. //FIXME which schematic?
  598. collection_reward.potential_rooms.push_back(Room("The Dilemma", {RoomOption(1, 0, 0), RoomOption(0, 1, 0)}));
  599. collection_reward.potential_rooms.push_back(Room("Locker Room", {RoomOption(0, 1, 0)}));
  600. collection_reward.potential_rooms.push_back(Room("The Unhurt Locker", {RoomOption(0, 1, 0)}));
  601. collection_reward.potential_rooms.push_back(Room("Office Space", {RoomOption(0, 1, 0), RoomOption(1, 0, 0, robot_capability::pow, robot_capability::pow)})); //office space
  602. collection_reward.potential_rooms.push_back(Room("The Dark Closet Returns", {RoomOption(0, 1, 0), RoomOption(0, 2, 0, robot_capability::light)}));
  603. collection_reward.potential_rooms.push_back(Room("Inadequate Copy Room Security", {RoomOption(1, 0, 0)}));
  604. collection_reward.potential_rooms.push_back(Room("Paperchase", {RoomOption(1, 0, 0)}));
  605.  
  606. collection_obstacle_t1.potential_rooms.push_back(Room("Conveyor, Convey Thyself", {RoomOption(0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 1)}));
  607. collection_obstacle_t1.potential_rooms.push_back(Room("The Monster Masher!", {RoomOption(0, 0, 0, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 1)}));
  608. collection_obstacle_t1.potential_rooms.push_back(Room("Some People Call It A Giant Slingblade", {RoomOption(0, 0, 0, robot_capability::run, robot_capability::run), RoomOption(0, 0, 1)}));
  609.  
  610. collection_obstacle_t1.potential_rooms.push_back(Room("War of Gears", {RoomOption(0, 0, 0, robot_capability::pow, robot_capability::pow), RoomOption(1,0,0,robot_capability::hover), RoomOption(0, 0, 2)}));
  611. collection_obstacle_t1.potential_rooms.push_back(Room("Crate Expectations", {RoomOption(0, 0, 0, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2)}));
  612. collection_obstacle_t1.potential_rooms.push_back(Room("Tin Door. Rusted.", {RoomOption(0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0,2,0,robot_capability::lube), RoomOption(0, 0, 2)})); //free is 2 damage, lube gives 2 items
  613.  
  614.  
  615. collection_obstacle_t2.potential_rooms.push_back(Room("Closing Time", {RoomOption(0, 0, 1, robot_capability::run, robot_capability::run), RoomOption(0, 0, 2)}));
  616. collection_obstacle_t2.potential_rooms.push_back(Room("Gone With the Wind", {RoomOption(0, 0, 1, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2)}));
  617. collection_obstacle_t2.potential_rooms.push_back(Room("Getting Your Bearings", {RoomOption(0, 0, 1, robot_capability::roll), RoomOption(0, 0, 2)}));
  618. collection_obstacle_t2.potential_rooms.push_back(Room("Down In Flames", {RoomOption(0, 0, 1, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2)}));
  619.  
  620. for (int room_number = 2; room_number < 100; room_number += 4)
  621. {
  622. factory_layout.first_area_layout[room_number] = collection_bot;
  623. factory_layout.first_area_layout[room_number + 1] = collection_obstacle_t1;
  624. factory_layout.first_area_layout[room_number + 2] = collection_reward;
  625. factory_layout.first_area_layout[room_number + 3] = collection_obstacle_t2;
  626. }
  627. //more, but unlikely to reach
  628. }
  629.  
  630. {
  631. //Second floor:
  632. RoomCollection collection_bot;
  633. RoomCollection collection_obstacle;
  634. RoomCollection collection_up_ladder;
  635. RoomCollection collection_down_ladder;
  636. RoomCollection collection_ladder;
  637.  
  638. //Many data points for the bots:
  639. collection_bot.potential_rooms.push_back(Room("Bot Your Shield", {RoomOption(0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 2)}));
  640. collection_bot.potential_rooms.push_back(Room("Whatcha Thinkin'?", {RoomOption(0, 0, 0, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 2, 2)}));
  641. collection_bot.potential_rooms.push_back(Room("Festively Armed", {RoomOption(0, 0, 0, robot_capability::lube), RoomOption(0, 0, 1, 1)}));
  642. collection_bot.potential_rooms.push_back(Room("Compugilist", {RoomOption(0, 0, 0, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2, 2)}));
  643. collection_bot.potential_rooms.push_back(Room("I See You", {RoomOption(0, 0, 0, robot_capability::light), RoomOption(0, 0, 1, 1)}));
  644.  
  645. collection_obstacle.potential_rooms.push_back(Room("A Vent Horizon", {RoomOption(0, 0, 2, 2, robot_capability::freeze), RoomOption(0, 0, 3, 4)}));
  646. collection_obstacle.potential_rooms.push_back(Room("Off The Rails", {RoomOption(0, 0, 2, 2, robot_capability::roll, robot_capability::roll), RoomOption(0, 0, 3, 4)}));
  647. collection_obstacle.potential_rooms.push_back(Room("The Floor is Like Lava", {RoomOption(0, 0, 2, 2, robot_capability::hover), RoomOption(0, 0, 3, 4)}));
  648. collection_obstacle.potential_rooms.push_back(Room("A Pressing Concern", {RoomOption(0, 0, 2, 2, robot_capability::run,robot_capability::run), RoomOption(0, 0, 3, 4)}));
  649.  
  650. //FIXME rewards need more precise
  651. collection_up_ladder.potential_rooms.push_back(Room("Still Life With Despair", {RoomOption(0, 1, 0, robot_capability::pinch), RoomOption(1, 0, 0, robot_capability::zap, robot_capability::zap)}));
  652. collection_up_ladder.potential_rooms.push_back(Room("Hope You Have A Beretta", {RoomOption(1, 0, 0, robot_capability::pinch), RoomOption(0, 1, 0, robot_capability::blam, robot_capability::blam)}));
  653. collection_up_ladder.potential_rooms.push_back(Room("This Gym Is Much Nicer", {RoomOption(0, 1, 0, robot_capability::pinch), RoomOption(1, 0, 0, robot_capability::pinch)}));
  654.  
  655. //FIXME unsure about damage:
  656. collection_down_ladder.potential_rooms.push_back(Room("Pants in High Places", {RoomOption(1, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 3)}));
  657. collection_down_ladder.potential_rooms.push_back(Room("Humpster Dumpster", {RoomOption(0, 1, 0, robot_capability::lube), RoomOption(0, 0, 2, 3)}));
  658. collection_down_ladder.potential_rooms.push_back(Room("Cage Match", {RoomOption(1, 0, 0, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 2, 3)}));
  659. collection_down_ladder.potential_rooms.push_back(Room("Birdbot is the Wordbot", {RoomOption(0, 1, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 3)}));
  660.  
  661.  
  662. collection_ladder.potential_rooms.push_back(Room("The Corporate Ladder", {RoomOption(0, 0, 0), RoomOption(0, 0, 0)}));
  663.  
  664.  
  665.  
  666. for (int room_number = 2; room_number < 100; room_number += 4)
  667. {
  668. factory_layout.second_area_layout_up_path[room_number] = collection_bot;
  669. factory_layout.second_area_layout_up_path[room_number + 1] = collection_ladder;
  670. factory_layout.second_area_layout_up_path[room_number + 2] = collection_up_ladder;
  671. factory_layout.second_area_layout_up_path[room_number + 3] = collection_obstacle;
  672.  
  673.  
  674. factory_layout.second_area_layout_down_path[room_number] = collection_bot;
  675. factory_layout.second_area_layout_down_path[room_number + 1] = collection_ladder;
  676. factory_layout.second_area_layout_down_path[room_number + 2] = collection_down_ladder;
  677. factory_layout.second_area_layout_down_path[room_number + 3] = collection_obstacle;
  678. }
  679. }
  680.  
  681. printf("Floor\tStrategy\tChoose parts or schematics?\tLeft arm\tRight arm\tTorso\tPropulsion\tAverage parts found\tAverage schematics found\tAverage rooms ended at\tFurthest room ended at\tLikelyhood of reaching that room\n");
  682. unsigned int simulation_count = 10000000;
  683. simulation_count = 1000000;
  684. //simulation_count = 100000000;
  685.  
  686. if (false)
  687. {
  688. //Former debug:
  689. simulation_count = 10000000;
  690. //Bug Zapper Wrecking Ball Military Chassis Regular Legs
  691. simulateAllAndOutput(factory_layout, simulation_count, parts_list[robot_part_location::left_arm][1], parts_list[robot_part_location::right_arm][2], parts_list[robot_part_location::torso][4], parts_list[robot_part_location::propulsion][0], 1, 1, true);
  692. return 0;
  693. }
  694.  
  695. if (true) //individualised threading, faster
  696. {
  697. unsigned int wanted_thread_count = std::thread::hardware_concurrency() + 8; //HACK to use full CPU because we're not using a work queue (and should)
  698. //essentially, a bunch of these executions terminate early and show up in our queue and count against our limit
  699. //doing this correctly requires a proper work queue, but honestly I am not familiar enough with C++ to implement that the correct way, and pthread's semaphores didn't work too well on OS X last I tried
  700. //so instead, we just spawn a bunch of extra threads we don't need to, to saturate the CPU. this will likely affect performance and is a bad decision
  701. std::queue <std::thread> active_threads;
  702.  
  703. for (RobotPart part_left_arm : parts_list[robot_part_location::left_arm])
  704. {
  705. for (RobotPart part_right_arm : parts_list[robot_part_location::right_arm])
  706. {
  707. for (RobotPart part_torso : parts_list[robot_part_location::torso])
  708. {
  709. for (RobotPart part_propulsion : parts_list[robot_part_location::propulsion])
  710. {
  711. for (int floor = setting_simulate_floor_min; floor <= setting_simulate_floor_max; floor++)
  712. {
  713. int max_strategy = 1;
  714. if (floor == 2)
  715. max_strategy = 2;
  716. for (int strategy = 1; strategy <= max_strategy; strategy++)
  717. {
  718. if (active_threads.size() >= wanted_thread_count)
  719. {
  720. active_threads.front().join();
  721. active_threads.pop();
  722. }
  723. if (setting_simulate_schematics_as_well)
  724. active_threads.push(std::thread(simulateAllAndOutput, factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, strategy, false));
  725. active_threads.push(std::thread(simulateAllAndOutput, factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, strategy, true));
  726. }
  727. }
  728. }
  729. }
  730. }
  731. }
  732. while (active_threads.size() > 0)
  733. {
  734. active_threads.front().join();
  735. active_threads.pop();
  736. }
  737. }
  738. else
  739. {
  740. for (RobotPart part_left_arm : parts_list[robot_part_location::left_arm])
  741. {
  742. for (RobotPart part_right_arm : parts_list[robot_part_location::right_arm])
  743. {
  744. for (RobotPart part_torso : parts_list[robot_part_location::torso])
  745. {
  746. for (RobotPart part_propulsion : parts_list[robot_part_location::propulsion])
  747. {
  748. for (int floor = 1; floor < 3; floor++)
  749. {
  750. if (setting_simulate_schematics_as_well)
  751. simulateAllAndOutput(factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, 1, false);
  752. simulateAllAndOutput(factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, 1, true);
  753. }
  754. }
  755. }
  756. }
  757. }
  758. }
  759.  
  760. auto end_time = std::chrono::high_resolution_clock::now();
  761. double computation_time = std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time).count();
  762. printf("Computed in %f seconds.\n", computation_time);
  763.  
  764. return 0;
  765. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement