Advertisement
kolpastebin

Crimbo 2014 Factory Simulator.cpp

Dec 19th, 2014
387
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 52.31 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 = true;
  12. const int setting_simulate_floor_min = 1;
  13. const int setting_simulate_floor_max = 3;
  14.  
  15. const bool setting_use_exact_simulation = true; //Calculate the numbers exactly, rather than fiddling with monte carlo. Will not output rooms reached information. Thanks for the idea, Satsuoni!
  16. const bool setting_preoptimise_room_options = true; //Speedup.
  17.  
  18. typedef std::mt19937 std_random_generator_class;
  19.  
  20. enum class robot_capability
  21. {
  22.     blam,
  23.     light,
  24.     pow,
  25.     roll,
  26.     run,
  27.     zap,
  28.     hover,
  29.     lube,
  30.     pinch,
  31.     decode,
  32.     freeze,
  33.     burn
  34. };
  35.  
  36. //Using a map here is slightly inefficient, but we pre-prune capabilities before simulation, so it won't affect performance.
  37. class RobotCapabilities
  38. {
  39.     public:
  40.         void addCapability(const robot_capability & capability);
  41.         void addCapabilities(const RobotCapabilities & capabilities_other);
  42.         bool hasCapability(const robot_capability & capability) const;
  43.         int capabilityAmount(const robot_capability & capability) const;
  44.         bool capabilityWillFulfillOurs(const RobotCapabilities & capabilities_other) const;
  45.     private:
  46.         std::map <robot_capability,int> capabilities_map;
  47. };
  48.  
  49. void RobotCapabilities::addCapability(const robot_capability & capability)
  50. {
  51.     capabilities_map[capability] += 1;
  52. }
  53.  
  54. void RobotCapabilities::addCapabilities(const RobotCapabilities & capabilities_other)
  55. {
  56.     for (auto & iterator : capabilities_other.capabilities_map)
  57.     {
  58.         capabilities_map[iterator.first] += iterator.second;
  59.     }
  60. }
  61.  
  62. bool RobotCapabilities::hasCapability(const robot_capability & capability) const
  63. {
  64.     return capabilityAmount(capability) > 0;
  65. }
  66.  
  67. int RobotCapabilities::capabilityAmount(const robot_capability & capability) const
  68. {
  69.     if (capabilities_map.count(capability) == 0)
  70.         return 0;
  71.     return capabilities_map.find(capability)->second;
  72. }
  73.  
  74. bool RobotCapabilities::capabilityWillFulfillOurs(const RobotCapabilities & capabilities_other) const
  75. {
  76.     for (auto & iterator : capabilities_map)
  77.     {
  78.         if (capabilities_other.capabilityAmount(iterator.first) < iterator.second)
  79.             return false;
  80.     }
  81.     return true;
  82. }
  83.  
  84.  
  85. struct SimulationStateMutable
  86. {
  87.     SimulationStateMutable() : current_hp(0), room(0) {}
  88.     bool operator<(const SimulationStateMutable & rhs) const;
  89.     bool operator==(const SimulationStateMutable & rhs) const;
  90.     int current_hp;
  91.     int room;
  92. };
  93.  
  94. bool SimulationStateMutable::operator<(const SimulationStateMutable & rhs) const
  95. {
  96.     if (room < rhs.room)
  97.         return true;
  98.     if (room == rhs.room)
  99.     {
  100.         if (current_hp < rhs.current_hp)
  101.             return true;
  102.     }
  103.     return false;
  104. }
  105.  
  106. bool SimulationStateMutable::operator==(const SimulationStateMutable & rhs) const
  107. {
  108.     return (current_hp == rhs.current_hp && room == rhs.room);
  109. }
  110.  
  111. struct SimulationStateFixed
  112. {
  113.     template <typename ... T>
  114.     SimulationStateFixed(const int base_hp_in, const T & ... capabilities); //capabilities must be of type robot_capability
  115.     int base_hp;
  116.     RobotCapabilities capabilities;
  117.     int chosen_floor;
  118.     int chosen_maze_strategy_1; //for floor 2, 1 means up, 2 means down
  119.     bool choose_parts_over_schematics;
  120.    
  121.     void addToCapabilities(const SimulationStateFixed & other);
  122.    
  123. };
  124.  
  125. template <typename ... T>
  126. SimulationStateFixed::SimulationStateFixed(const int base_hp_in, const T & ... capabilities_in) : base_hp(base_hp_in)
  127. {
  128.     chosen_maze_strategy_1 = 1;
  129.     choose_parts_over_schematics = false;
  130.     const robot_capability capabilities_in_array[] = { capabilities_in... };
  131.     for (robot_capability capability : capabilities_in_array)
  132.     {
  133.         capabilities.addCapability(capability);
  134.     }
  135. }
  136.  
  137. void SimulationStateFixed::addToCapabilities(const SimulationStateFixed & other)
  138. {
  139.     base_hp += other.base_hp;
  140.     capabilities.addCapabilities(other.capabilities);
  141. }
  142.  
  143. struct RoomOption
  144. {
  145.     RoomOption() : schematics_given(0), parts_given(0), minimum_hp_damage_dealt(0), maximum_hp_damage_dealt(0) {}
  146.    
  147.     //template <typename ... T>
  148.     //RoomOption(int schematics_given_in, double parts_given_in, int hp_damage_dealt_in, T ... capabilities); //capabilities must be of type robot_capability
  149.     template <typename ... T>
  150.     RoomOption(int schematics_given_in, double parts_given_in, int minimum_hp_damage_dealt_in, int maximum_hp_damage_dealt_in, T ... capabilities); //capabilities must be of type robot_capability
  151.    
  152.     RobotCapabilities required_capabilities;
  153.     int schematics_given;
  154.     double parts_given;
  155.     int minimum_hp_damage_dealt;
  156.     int maximum_hp_damage_dealt;
  157.    
  158.     bool capableOfChoosingChoice(const RobotCapabilities & with_capabilities) const;
  159. };
  160.  
  161. /*template <typename ... T>
  162. RoomOption::RoomOption(int schematics_given_in, double 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)
  163. {
  164.     const robot_capability capabilities_in_array[] = { capabilities_in... };
  165.     for (robot_capability capability : capabilities_in_array)
  166.     {
  167.         required_capabilities.addCapability(capability);
  168.     }
  169. }*/
  170.  
  171. template <typename ... T>
  172. RoomOption::RoomOption(int schematics_given_in, double 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)
  173. {
  174.     const robot_capability capabilities_in_array[] = { capabilities_in... };
  175.     for (robot_capability capability : capabilities_in_array)
  176.     {
  177.         required_capabilities.addCapability(capability);
  178.     }
  179. }
  180.  
  181.  
  182. bool RoomOption::capableOfChoosingChoice(const RobotCapabilities & with_capabilities) const
  183. {
  184.     return required_capabilities.capabilityWillFulfillOurs(with_capabilities);
  185. }
  186.  
  187. struct Room
  188. {
  189.     Room();
  190.     Room(std::string name_in, const std::vector <RoomOption> & options_in) : name(name_in), options(options_in) {}
  191.     std::vector <RoomOption> options;
  192.     std::string name;
  193. };
  194.  
  195. struct RoomCollection
  196. {
  197.     std::vector <Room> potential_rooms;
  198. };
  199.  
  200. struct FactoryLayout
  201. {
  202.     std::map <int, RoomCollection> first_area_layout; //room number - 2 is the start
  203.     std::map <int, RoomCollection> second_area_layout_up_path;
  204.     std::map <int, RoomCollection> second_area_layout_down_path;
  205.     std::map <int, RoomCollection> third_area_layout_easy_path;
  206.     std::map <int, RoomCollection> third_area_layout_hard_path;
  207.     std::map <int, RoomCollection> third_area_layout_hard_then_easy_path;
  208. };
  209.  
  210.  
  211. enum class robot_part_location
  212. {
  213.     left_arm,
  214.     right_arm,
  215.     torso,
  216.     propulsion
  217. };
  218.  
  219. struct RobotPart
  220. {
  221.     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) {}
  222.     std::string name;
  223.     robot_part_location location;
  224.     SimulationStateFixed capability_modifiers;
  225. };
  226.  
  227. void simulateOnce(std_random_generator_class & rng_generator, const std::vector <RoomCollection> & area_layout, const SimulationStateFixed & fixed_state, double * parts_found_out, int * schematics_found_out, int * room_ended_at_out)
  228. {
  229.     SimulationStateMutable state = SimulationStateMutable();
  230.     state.current_hp = fixed_state.base_hp;
  231.     state.room = 2;
  232.    
  233.     const bool output_debug = false;
  234.    
  235.     if (output_debug)
  236.         printf("-\n");
  237.     while (state.current_hp > 0)
  238.     {
  239.         if (state.room >= area_layout.size() || state.room < 0)
  240.         {
  241.             break;
  242.         }
  243.         const RoomCollection & room_collection = area_layout[state.room];
  244.        
  245.         if (room_collection.potential_rooms.size() == 0)
  246.         {
  247.             printf("INTERNAL ERROR: Room collection too small.\n");
  248.             break;
  249.         }
  250.         //Generate a room:
  251.         //int picked_id = random() % room_collection.potential_rooms.size();
  252.        
  253.         int picked_id = std::uniform_int_distribution<>(0, (int)room_collection.potential_rooms.size() - 1)(rng_generator);
  254.         const Room & current_room = room_collection.potential_rooms[picked_id];
  255.        
  256.         const RoomOption * chosen_option = 0;
  257.         int chosen_option_score = 0;
  258.         for (const RoomOption & option : current_room.options)
  259.         {
  260.             if (!option.capableOfChoosingChoice(fixed_state.capabilities))
  261.                 continue;
  262.             bool is_better = false;
  263.            
  264.             int score = 0;
  265.             if (fixed_state.choose_parts_over_schematics)
  266.             {
  267.                 score += option.parts_given * 100.0;
  268.                 score += option.schematics_given * 10;
  269.             }
  270.             else
  271.             {
  272.                 score += option.parts_given * 10.0;
  273.                 score += option.schematics_given * 100;
  274.             }
  275.             score -= (option.minimum_hp_damage_dealt + option.maximum_hp_damage_dealt);
  276.            
  277.             //Is this better?
  278.             if (!chosen_option)
  279.                 is_better = true;
  280.             else if (score > chosen_option_score)
  281.                 is_better = true;
  282.            
  283.             if (is_better)
  284.             {
  285.                 chosen_option = &option;
  286.                 chosen_option_score = score;
  287.             }
  288.         }
  289.         if (output_debug)
  290.             printf("\tOn room %i. HP is %i.\n", state.room, state.current_hp);
  291.         if (!chosen_option)
  292.         {
  293.             printf("INTERNAL ERROR: No option.\n");
  294.             break;
  295.         }
  296.         *parts_found_out += chosen_option->parts_given;
  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. struct PathSimulationResult
  316. {
  317.     long double parts_found;
  318.     long double schematics_found;
  319. };
  320.  
  321. PathSimulationResult simulateEntirePath(const std::vector <RoomCollection> & area_layout, const SimulationStateFixed & fixed_state, SimulationStateMutable mutable_state, std::map <SimulationStateMutable, PathSimulationResult> & cached_results)
  322. {
  323.     PathSimulationResult result = PathSimulationResult();
  324.     if (mutable_state.current_hp <= 0)
  325.         return result;
  326.     //Look us up in the cached results:
  327.     if (cached_results.find(mutable_state) != cached_results.end())
  328.     {
  329.         return cached_results[mutable_state];
  330.     }
  331.    
  332.     //Go through each option:
  333.     if (mutable_state.room >= area_layout.size() || mutable_state.room < 0)
  334.     {
  335.         return result;
  336.     }
  337.    
  338.     int options_seen = 0;
  339.     for (const Room & room : area_layout[mutable_state.room].potential_rooms)
  340.     {
  341.         //Pick the choice we want:
  342.         const RoomOption * chosen_option = 0;
  343.         int chosen_option_score = 0;
  344.         for (const RoomOption & option : room.options)
  345.         {
  346.             if (!option.capableOfChoosingChoice(fixed_state.capabilities))
  347.                 continue;
  348.             bool is_better = false;
  349.            
  350.             int score = 0;
  351.             if (fixed_state.choose_parts_over_schematics)
  352.             {
  353.                 score += option.parts_given * 100.0;
  354.                 score += option.schematics_given * 10;
  355.             }
  356.             else
  357.             {
  358.                 score += option.parts_given * 10.0;
  359.                 score += option.schematics_given * 100;
  360.             }
  361.             score -= (option.minimum_hp_damage_dealt + option.maximum_hp_damage_dealt);
  362.            
  363.             //Is this better?
  364.             if (!chosen_option)
  365.                 is_better = true;
  366.             else if (score > chosen_option_score)
  367.                 is_better = true;
  368.            
  369.             if (is_better)
  370.             {
  371.                 chosen_option = &option;
  372.                 chosen_option_score = score;
  373.             }
  374.         }
  375.        
  376.         if (!chosen_option)
  377.             continue;
  378.        
  379.         PathSimulationResult room_result = PathSimulationResult();
  380.         for (int i = chosen_option->minimum_hp_damage_dealt; i <= chosen_option->maximum_hp_damage_dealt; i++)
  381.         {
  382.             room_result.parts_found += chosen_option->parts_given;
  383.             room_result.schematics_found += chosen_option->schematics_given;
  384.            
  385.             SimulationStateMutable altered_state = mutable_state;
  386.             altered_state.room += 1;
  387.             altered_state.current_hp -= i;
  388.             PathSimulationResult result2 = simulateEntirePath(area_layout, fixed_state, altered_state, cached_results);
  389.             room_result.parts_found += result2.parts_found;
  390.             room_result.schematics_found += result2.schematics_found;
  391.         }
  392.         long double divisor = (long double)(chosen_option->maximum_hp_damage_dealt - chosen_option->minimum_hp_damage_dealt + 1);
  393.         if (divisor != 0)
  394.         {
  395.             if (divisor != 1)
  396.             {
  397.                 room_result.parts_found /= divisor;
  398.                 room_result.schematics_found /= divisor;
  399.             }
  400.             result.parts_found += room_result.parts_found;
  401.             result.schematics_found += room_result.schematics_found;
  402.             options_seen++;
  403.         }
  404.     }
  405.    
  406.     if (options_seen > 0)
  407.     {
  408.         long double options_seen_double = (long double)options_seen;
  409.         result.parts_found /= options_seen_double;
  410.         result.schematics_found /= options_seen_double;
  411.     }
  412.    
  413.     if (cached_results.count(mutable_state) == 0)
  414.     {
  415.         cached_results[mutable_state] = result;
  416.     }
  417.     return result;
  418. }
  419.  
  420. 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)
  421. {
  422.     //Create state for this set of parts:
  423.     SimulationStateFixed fixed_state = SimulationStateFixed(0);
  424.     fixed_state.addToCapabilities(part_left_arm.capability_modifiers);
  425.     fixed_state.addToCapabilities(part_right_arm.capability_modifiers);
  426.     fixed_state.addToCapabilities(part_torso.capability_modifiers);
  427.     fixed_state.addToCapabilities(part_propulsion.capability_modifiers);
  428.     fixed_state.chosen_floor = floor_in;
  429.     fixed_state.chosen_maze_strategy_1 = maze_strategy_in;
  430.     fixed_state.choose_parts_over_schematics = pick_parts_over_schematics;
  431.    
  432.     if (fixed_state.chosen_floor == 2 && !fixed_state.capabilities.hasCapability(robot_capability::pinch))
  433.     {
  434.         return;
  435.     }
  436.     if (fixed_state.chosen_floor == 3 && !fixed_state.capabilities.hasCapability(robot_capability::decode))
  437.     {
  438.         return;
  439.     }
  440.    
  441.     std::vector <int> total_rooms_ended_at_frequency;
  442.     //std_random_generator_class rng_generator = std_random_generator_class(std::chrono::high_resolution_clock::now().time_since_epoch().count());
  443.     std_random_generator_class rng_generator = std_random_generator_class(std::random_device()());
  444.     double total_parts_found = 0;
  445.     uint64_t total_schematics_found = 0;
  446.     uint64_t total_rooms_ended_at = 0;
  447.    
  448.    
  449.     const std::map <int, RoomCollection> * area_layout_map = &factory_layout.first_area_layout;
  450.     if (fixed_state.chosen_floor == 2)
  451.     {
  452.         if (fixed_state.chosen_maze_strategy_1 == 1)
  453.             area_layout_map = &factory_layout.second_area_layout_up_path;
  454.         else
  455.             area_layout_map = &factory_layout.second_area_layout_down_path;
  456.     }
  457.     if (fixed_state.chosen_floor == 3)
  458.     {
  459.         if (fixed_state.chosen_maze_strategy_1 == 1)
  460.             area_layout_map = &factory_layout.third_area_layout_easy_path;
  461.         else if (fixed_state.chosen_maze_strategy_1 == 2)
  462.             area_layout_map = &factory_layout.third_area_layout_hard_path;
  463.         else if (fixed_state.chosen_maze_strategy_1 == 3)
  464.             area_layout_map = &factory_layout.third_area_layout_hard_then_easy_path;
  465.     }
  466.     if (area_layout_map->size() == 0)
  467.         return;
  468.    
  469.    
  470.     double average_parts_found = 0.0;
  471.     double average_schematics_found = 0.0;
  472.     double average_rooms_ended_at = 0.0;
  473.     std::vector <RoomCollection> area_layout;
  474.     for (const auto & iterator : *area_layout_map)
  475.     {
  476.         const int & room_id = iterator.first;
  477.         const RoomCollection & room_collection_source = iterator.second;
  478.        
  479.         if (room_id >= area_layout.size())
  480.             area_layout.resize(room_id + 1);
  481.        
  482.         area_layout[room_id] = room_collection_source;
  483.        
  484.         if (setting_preoptimise_room_options)
  485.         {
  486.             //Modify the room. Remove choices we can't choose, and remove the requirements for the ones we can.
  487.             RoomCollection & room_collection_active = area_layout[room_id];
  488.             for (Room & room : room_collection_active.potential_rooms)
  489.             {
  490.                 std::vector <RoomOption> new_options;
  491.                 for (RoomOption & option : room.options)
  492.                 {
  493.                     if (!option.capableOfChoosingChoice(fixed_state.capabilities))
  494.                         continue;
  495.                     option.required_capabilities = RobotCapabilities();
  496.                     new_options.push_back(option);
  497.                 }
  498.                 room.options = new_options;
  499.             }
  500.         }
  501.     }
  502.     if (setting_use_exact_simulation)
  503.     {
  504.         SimulationStateMutable base_mutable_state;
  505.         base_mutable_state.current_hp = fixed_state.base_hp;
  506.         base_mutable_state.room = 2;
  507.        
  508.         std::map <SimulationStateMutable, PathSimulationResult> cached_results;
  509.         PathSimulationResult simulation_result = simulateEntirePath(area_layout, fixed_state, base_mutable_state, cached_results);
  510.        
  511.         average_parts_found = simulation_result.parts_found;
  512.         average_schematics_found = simulation_result.schematics_found;
  513.     }
  514.     else
  515.     {
  516.         //Run simulation:
  517.         for (int i = 0; i < simulation_count; i++)
  518.         {
  519.             double parts_found = 0;
  520.             int schematics_found = 0;
  521.             int room_ended_at = 0;
  522.            
  523.             simulateOnce(rng_generator, area_layout, fixed_state, &parts_found, &schematics_found, &room_ended_at);
  524.             total_parts_found += parts_found;
  525.             total_schematics_found += schematics_found;
  526.             total_rooms_ended_at += room_ended_at;
  527.             if (room_ended_at >= total_rooms_ended_at_frequency.size())
  528.                 total_rooms_ended_at_frequency.resize(room_ended_at + 1);
  529.             total_rooms_ended_at_frequency[room_ended_at] += 1;
  530.         }
  531.         average_parts_found = ((double)total_parts_found) / ((double)simulation_count);
  532.         average_schematics_found = ((double)total_schematics_found) / ((double)simulation_count);
  533.         average_rooms_ended_at = ((double)total_rooms_ended_at) / ((double)simulation_count);
  534.     }
  535.    
  536.    
  537.     int furtherest_room_ended_at = 0;
  538.     for (int room_number = 0; room_number < total_rooms_ended_at_frequency.size(); room_number++)
  539.     {
  540.         int amount = total_rooms_ended_at_frequency[room_number];
  541.         if (amount > 0 && room_number > furtherest_room_ended_at)
  542.             furtherest_room_ended_at = room_number;
  543.        
  544.     }
  545.    
  546.     double chance_of_last_room = 0.0;
  547.    
  548.     if (total_rooms_ended_at_frequency.size() > furtherest_room_ended_at)
  549.         chance_of_last_room = ((double)total_rooms_ended_at_frequency[furtherest_room_ended_at]) / ((double)simulation_count);
  550.     std::string strategy_string = "N/A";
  551.     if (fixed_state.chosen_floor == 2)
  552.     {
  553.         if (fixed_state.chosen_maze_strategy_1 == 1)
  554.             strategy_string = "ascend";
  555.         else
  556.             strategy_string = "descend";
  557.     }
  558.     if (fixed_state.chosen_floor == 3)
  559.     {
  560.         if (fixed_state.chosen_maze_strategy_1 == 1)
  561.             strategy_string = "easy";
  562.         else if (fixed_state.chosen_maze_strategy_1 == 2)
  563.             strategy_string = "hard always";
  564.         else if (fixed_state.chosen_maze_strategy_1 == 3)
  565.             strategy_string = "hard first, easy second";
  566.     }
  567.    
  568.     std::string parts_or_schematics;
  569.     if (fixed_state.choose_parts_over_schematics)
  570.         parts_or_schematics = "parts";
  571.     else
  572.         parts_or_schematics = "schematics";
  573.    
  574.     if (average_parts_found == 0.0 && average_schematics_found == 0.0) //certain options cannot gain anything; level 2 descending, for instance
  575.         return;
  576.    
  577.     if (setting_use_exact_simulation)
  578.         printf("%i\t%s\t%s\t%s\t%s\t%s\t%s\t%f\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);
  579.     else
  580.         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);
  581. }
  582.  
  583. int main(int argc, const char * argv[])
  584. {
  585.     auto start_time = std::chrono::high_resolution_clock::now();
  586.     std::map <robot_part_location, std::vector <RobotPart> > parts_list;
  587.     for (robot_part_location location : {robot_part_location::left_arm, robot_part_location::right_arm, robot_part_location::torso, robot_part_location::propulsion})
  588.     {
  589.         parts_list[location] = std::vector<RobotPart>();
  590.     }
  591.    
  592.     {
  593.         std::vector <RobotPart> parts_list_creating;
  594.        
  595.         //ALL:
  596.         parts_list_creating.push_back(RobotPart("Tiny Fist", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::pow)));
  597.         parts_list_creating.push_back(RobotPart("Bug Zapper", robot_part_location::left_arm, SimulationStateFixed(1,robot_capability::zap)));
  598.         parts_list_creating.push_back(RobotPart("Rodent Gun", robot_part_location::left_arm, SimulationStateFixed(0,robot_capability::blam)));
  599.         parts_list_creating.push_back(RobotPart("Rivet Shocker", robot_part_location::left_arm, SimulationStateFixed(0,robot_capability::zap,robot_capability::pow)));
  600.         parts_list_creating.push_back(RobotPart("Mega Vise", robot_part_location::left_arm, SimulationStateFixed(0,robot_capability::pow,robot_capability::pow)));
  601.         parts_list_creating.push_back(RobotPart("Mobile Girder", robot_part_location::left_arm, SimulationStateFixed(3)));
  602.         parts_list_creating.push_back(RobotPart("Swiss Arm", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::pow, robot_capability::blam, robot_capability::zap)));
  603.         parts_list_creating.push_back(RobotPart("Data Analyzer", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::decode)));
  604.         parts_list_creating.push_back(RobotPart("Maxi-Mag Light", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::light, robot_capability::light, robot_capability::pow)));
  605.         parts_list_creating.push_back(RobotPart("Bit Masher", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::decode, robot_capability::pow)));
  606.         parts_list_creating.push_back(RobotPart("Camera Claw", robot_part_location::left_arm, SimulationStateFixed(0, robot_capability::decode, robot_capability::pinch)));
  607.        
  608.        
  609.         //ALL:
  610.         parts_list_creating.push_back(RobotPart("Ball-Bearing Dispenser", robot_part_location::right_arm, SimulationStateFixed(0, robot_capability::blam)));
  611.         parts_list_creating.push_back(RobotPart("Power Arm", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::zap)));
  612.         parts_list_creating.push_back(RobotPart("Wrecking Ball", robot_part_location::right_arm, SimulationStateFixed(1,robot_capability::pow)));
  613.         parts_list_creating.push_back(RobotPart("Ribbon Manipulator", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::pinch)));
  614.         parts_list_creating.push_back(RobotPart("Power Stapler", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::zap, robot_capability::pinch)));
  615.         parts_list_creating.push_back(RobotPart("Grease Gun", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::lube)));
  616.         parts_list_creating.push_back(RobotPart("Grease / Regular Gun", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::lube,robot_capability::blam)));
  617.         parts_list_creating.push_back(RobotPart("Snow Blower", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::freeze)));
  618.         parts_list_creating.push_back(RobotPart("Candle Lighter", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::burn)));
  619.         parts_list_creating.push_back(RobotPart("Cold Shoulder", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::freeze, robot_capability::pow)));
  620.         parts_list_creating.push_back(RobotPart("Lamp Filler", robot_part_location::right_arm, SimulationStateFixed(0,robot_capability::burn, robot_capability::lube)));
  621.        
  622.         //ALL:
  623.         parts_list_creating.push_back(RobotPart("Basic Head", robot_part_location::torso, SimulationStateFixed(3)));
  624.         parts_list_creating.push_back(RobotPart("Gun Face", robot_part_location::torso, SimulationStateFixed(3,robot_capability::blam)));
  625.         parts_list_creating.push_back(RobotPart("Big Head", robot_part_location::torso, SimulationStateFixed(4)));
  626.         parts_list_creating.push_back(RobotPart("Security Chassis", robot_part_location::torso, SimulationStateFixed(3,robot_capability::light)));
  627.         parts_list_creating.push_back(RobotPart("Military Chassis", robot_part_location::torso, SimulationStateFixed(3,robot_capability::light,robot_capability::blam)));
  628.         parts_list_creating.push_back(RobotPart("Crab Core", robot_part_location::torso, SimulationStateFixed(4,robot_capability::pinch)));
  629.         parts_list_creating.push_back(RobotPart("Dynamo Head", robot_part_location::torso, SimulationStateFixed(4,robot_capability::zap)));
  630.         parts_list_creating.push_back(RobotPart("Cyclopean Torso", robot_part_location::torso, SimulationStateFixed(4,robot_capability::light)));
  631.         parts_list_creating.push_back(RobotPart("Really Big Head", robot_part_location::torso, SimulationStateFixed(5)));
  632.         parts_list_creating.push_back(RobotPart("Nerding Module", robot_part_location::torso, SimulationStateFixed(5, robot_capability::decode)));
  633.         parts_list_creating.push_back(RobotPart("Refrigerator Chassis", robot_part_location::torso, SimulationStateFixed(5, robot_capability::freeze, robot_capability::light)));
  634.        
  635.  
  636.         ///ALL:
  637.         parts_list_creating.push_back(RobotPart("Regular Legs", robot_part_location::propulsion, SimulationStateFixed(0, robot_capability::run)));
  638.         parts_list_creating.push_back(RobotPart("Heavy-Duty Legs", robot_part_location::propulsion, SimulationStateFixed(1, robot_capability::run)));
  639.         parts_list_creating.push_back(RobotPart("Tripod Legs", robot_part_location::propulsion, SimulationStateFixed(0,robot_capability::run,robot_capability::run)));
  640.         parts_list_creating.push_back(RobotPart("Rollerfeet", robot_part_location::propulsion, SimulationStateFixed(0,robot_capability::run,robot_capability::roll)));
  641.         parts_list_creating.push_back(RobotPart("Sim-Simian Feet", robot_part_location::propulsion, SimulationStateFixed(0,robot_capability::run, robot_capability::pinch)));
  642.         parts_list_creating.push_back(RobotPart("High-Speed Fan", robot_part_location::propulsion, SimulationStateFixed(1,robot_capability::hover)));
  643.         parts_list_creating.push_back(RobotPart("Big Wheel", robot_part_location::propulsion, SimulationStateFixed(0, robot_capability::roll, robot_capability::roll)));
  644.         parts_list_creating.push_back(RobotPart("Hoverjack", robot_part_location::propulsion, SimulationStateFixed(2,robot_capability::hover)));
  645.         parts_list_creating.push_back(RobotPart("Gun Legs", robot_part_location::propulsion, SimulationStateFixed(0, robot_capability::run, robot_capability::run, robot_capability::blam)));
  646.         parts_list_creating.push_back(RobotPart("Heavy Treads", robot_part_location::propulsion, SimulationStateFixed(2, robot_capability::roll, robot_capability::pow)));
  647.         parts_list_creating.push_back(RobotPart("Rocket Skirt", robot_part_location::propulsion, SimulationStateFixed(2, robot_capability::hover, robot_capability::burn)));
  648.        
  649.         for (RobotPart part : parts_list_creating)
  650.         {
  651.             parts_list[part.location].push_back(part);
  652.         }
  653.     }
  654.    
  655.     //Note on item distribution:
  656.     //Each parts reward adventure has a different distribution.
  657.     //I've collected some of my data from session logs and found the average probability of credits gained for each choice.
  658.     //Of course, an ideal simulation would actually generate the parts according to those distributions, but I don't think it'll affect the results much? Particularly since we're using exact simulation now.
  659.     //It's still incomplete and approximate, especially for places I rarely visit. (floor 2, floor 3 hard)
  660.     //The constants below are from my personal data set, and are not to be trusted.
  661.     FactoryLayout factory_layout = FactoryLayout();
  662.     {
  663.         //First floor:
  664.         RoomCollection collection_bot;
  665.         RoomCollection collection_obstacle_t1;
  666.         RoomCollection collection_obstacle_t2;
  667.         RoomCollection collection_reward;
  668.        
  669.        
  670.         collection_bot.potential_rooms.push_back(Room("Zippybot", {RoomOption(0, 0, 0, 0, robot_capability::zap), RoomOption(0, 0, 1, 1)}));
  671.         collection_bot.potential_rooms.push_back(Room("Turretbot", {RoomOption(0, 0, 0, 0, robot_capability::blam), RoomOption(0, 0, 1, 1)}));
  672.         collection_bot.potential_rooms.push_back(Room("Mookbot", {RoomOption(0, 0, 0, 0, robot_capability::blam), RoomOption(0, 0, 0, 0, robot_capability::pow), RoomOption(0, 0, 1, 1)}));
  673.         collection_bot.potential_rooms.push_back(Room("Doorbot", {RoomOption(0, 0, 0, 0, robot_capability::pow), RoomOption(0, 0, 0, 0, robot_capability::zap), RoomOption(0, 0, 1, 1)}));
  674.         collection_bot.potential_rooms.push_back(Room("Bulkybot", {RoomOption(0, 0, 0, 0, robot_capability::pow), RoomOption(0, 0, 1, 1)}));
  675.         collection_bot.potential_rooms.push_back(Room("Security Drone", {RoomOption(0, 0, 0, 0, robot_capability::blam), RoomOption(0, 0, 0, 0, robot_capability::zap), RoomOption(0, 0, 1, 1)}));
  676.        
  677.         //FIXME which schematic?
  678.         collection_reward.potential_rooms.push_back(Room("The Dilemma", {RoomOption(1, 0, 0, 0), RoomOption(0, 1.0 * 1.483871, 0, 0)}));
  679.         collection_reward.potential_rooms.push_back(Room("Locker Room", {RoomOption(0, 1.0 * 1.462069, 0, 0)}));
  680.         collection_reward.potential_rooms.push_back(Room("The Unhurt Locker", {RoomOption(0, 1.0 * 2.000000, 0, 0)}));
  681.         collection_reward.potential_rooms.push_back(Room("Office Space", {RoomOption(0, 1.0 * 1.524904, 0, 0), RoomOption(1, 0, 0, 0, robot_capability::pow, robot_capability::pow)})); //office space
  682.         collection_reward.potential_rooms.push_back(Room("The Dark Closet Returns", {RoomOption(0, 1.0 * 1.317073, 0, 0), RoomOption(0, 2.0 * 1.543814, 0, 0, robot_capability::light)}));
  683.         collection_reward.potential_rooms.push_back(Room("Inadequate Copy Room Security", {RoomOption(1, 0, 0, 0)}));
  684.         collection_reward.potential_rooms.push_back(Room("Paperchase", {RoomOption(1, 0, 0, 0)}));
  685.        
  686.         collection_obstacle_t1.potential_rooms.push_back(Room("Conveyor, Convey Thyself", {RoomOption(0, 0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 1, 1)}));
  687.         collection_obstacle_t1.potential_rooms.push_back(Room("The Monster Masher!", {RoomOption(0, 0, 0, 0, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 1, 1)}));
  688.         collection_obstacle_t1.potential_rooms.push_back(Room("Some People Call It A Giant Slingblade", {RoomOption(0, 0, 0, 0, robot_capability::run, robot_capability::run), RoomOption(0, 0, 1, 1)}));
  689.        
  690.         collection_obstacle_t1.potential_rooms.push_back(Room("War of Gears", {RoomOption(0, 0, 0, 0, robot_capability::pow, robot_capability::pow), RoomOption(1, 0, 0, 0, robot_capability::hover), RoomOption(0, 0, 2, 2)}));
  691.         collection_obstacle_t1.potential_rooms.push_back(Room("Crate Expectations", {RoomOption(0, 0, 0, 0, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2, 2)}));
  692.         collection_obstacle_t1.potential_rooms.push_back(Room("Tin Door.  Rusted.", {RoomOption(0, 0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 2.0 * 1.459283, 0, 0, robot_capability::lube), RoomOption(0, 0, 2, 2)}));
  693.        
  694.        
  695.         collection_obstacle_t2.potential_rooms.push_back(Room("Closing Time", {RoomOption(0, 0, 1, 1, robot_capability::run, robot_capability::run), RoomOption(0, 0, 2, 2)}));
  696.         collection_obstacle_t2.potential_rooms.push_back(Room("Gone With the Wind", {RoomOption(0, 0, 1, 1, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2, 2)}));
  697.         collection_obstacle_t2.potential_rooms.push_back(Room("Getting Your Bearings", {RoomOption(0, 0, 1, 1, robot_capability::roll), RoomOption(0, 0, 2, 2)}));
  698.         collection_obstacle_t2.potential_rooms.push_back(Room("Down In Flames", {RoomOption(0, 0, 1, 1, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 2)}));
  699.        
  700.         for (int room_number = 2; room_number < 200; room_number += 4)
  701.         {
  702.             factory_layout.first_area_layout[room_number] = collection_bot;
  703.             factory_layout.first_area_layout[room_number + 1] = collection_obstacle_t1;
  704.             factory_layout.first_area_layout[room_number + 2] = collection_reward;
  705.             factory_layout.first_area_layout[room_number + 3] = collection_obstacle_t2;
  706.         }
  707.         //more, but unlikely to reach
  708.     }
  709.    
  710.     {
  711.         //Second floor:
  712.         RoomCollection collection_bot;
  713.         RoomCollection collection_obstacle;
  714.         RoomCollection collection_up_ladder;
  715.         RoomCollection collection_down_ladder;
  716.         RoomCollection collection_ladder;
  717.        
  718.         //Many data points for the bots:
  719.         collection_bot.potential_rooms.push_back(Room("Bot Your Shield", {RoomOption(0, 0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 2)}));
  720.         collection_bot.potential_rooms.push_back(Room("Whatcha Thinkin'?", {RoomOption(0, 0, 0, 0, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 2, 2)}));
  721.         collection_bot.potential_rooms.push_back(Room("Festively Armed", {RoomOption(0, 0, 0, 0, robot_capability::lube), RoomOption(0, 0, 1, 1)}));
  722.         collection_bot.potential_rooms.push_back(Room("Compugilist", {RoomOption(0, 0, 0, 0, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2, 2)}));
  723.         collection_bot.potential_rooms.push_back(Room("I See You", {RoomOption(0, 0, 0, 0, robot_capability::light), RoomOption(0, 0, 1, 1)}));
  724.        
  725.         collection_obstacle.potential_rooms.push_back(Room("A Vent Horizon", {RoomOption(0, 0, 2, 2, robot_capability::freeze), RoomOption(0, 0, 3, 4)}));
  726.         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)}));
  727.         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)}));
  728.         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)}));
  729.        
  730.         //FIXME rewards need more precise
  731.         collection_up_ladder.potential_rooms.push_back(Room("Still Life With Despair", {RoomOption(0, 1.0 * 2.416667, 0, 0, robot_capability::pinch), RoomOption(1, 0, 0, 0, robot_capability::zap, robot_capability::zap)}));
  732.         collection_up_ladder.potential_rooms.push_back(Room("Hope You Have A Beretta", {RoomOption(1, 0, 0, 0, robot_capability::pinch), RoomOption(0, 1.0 * 3.119048, 0, 0, robot_capability::blam, robot_capability::blam)}));
  733.         collection_up_ladder.potential_rooms.push_back(Room("This Gym Is Much Nicer", {RoomOption(0, 1.0 * 2.409091, 0, 0, robot_capability::pinch), RoomOption(1, 0, 0, 0, robot_capability::pinch)}));
  734.        
  735.         //FIXME unsure about damage:
  736.         collection_down_ladder.potential_rooms.push_back(Room("Pants in High Places", {RoomOption(1, 0, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 3)}));
  737.         collection_down_ladder.potential_rooms.push_back(Room("Humpster Dumpster", {RoomOption(0, 1.0 * 3.636364, 0, 0, robot_capability::lube), RoomOption(0, 0, 2, 3)}));
  738.         collection_down_ladder.potential_rooms.push_back(Room("Cage Match", {RoomOption(1, 0, 0, 0, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 2, 3)}));
  739.         collection_down_ladder.potential_rooms.push_back(Room("Birdbot is the Wordbot", {RoomOption(0, 1.0 * 2.909091, 0, 0, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 3)}));
  740.        
  741.        
  742.         collection_ladder.potential_rooms.push_back(Room("The Corporate Ladder", {RoomOption(0, 0, 0, 0), RoomOption(0, 0, 0, 0)}));
  743.        
  744.        
  745.        
  746.         for (int room_number = 2; room_number < 100; room_number += 4)
  747.         {
  748.             factory_layout.second_area_layout_up_path[room_number] = collection_bot;
  749.             factory_layout.second_area_layout_up_path[room_number + 1] = collection_ladder;
  750.             factory_layout.second_area_layout_up_path[room_number + 2] = collection_up_ladder;
  751.             factory_layout.second_area_layout_up_path[room_number + 3] = collection_obstacle;
  752.            
  753.            
  754.             factory_layout.second_area_layout_down_path[room_number] = collection_bot;
  755.             factory_layout.second_area_layout_down_path[room_number + 1] = collection_ladder;
  756.             factory_layout.second_area_layout_down_path[room_number + 2] = collection_down_ladder;
  757.             factory_layout.second_area_layout_down_path[room_number + 3] = collection_obstacle;
  758.         }
  759.     }
  760.    
  761.     {
  762.         //Third floor:
  763.         RoomCollection collection_bot;
  764.         RoomCollection collection_choice;
  765.         RoomCollection collection_easy_reward;
  766.         RoomCollection collection_hard_room_1;
  767.         RoomCollection collection_hard_room_2;
  768.         RoomCollection collection_obstacle;
  769.        
  770.         //FIXME this data is largely my personal assumptions, DO NOT RELY ON:
  771.        
  772.         //zap/zap range assumed
  773.         collection_bot.potential_rooms.push_back(Room("Dorkbot 4000", {RoomOption(0, 0, 0, 0, robot_capability::decode, robot_capability::decode), RoomOption(0, 0, 1, 2, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 2, 3)}));
  774.         collection_bot.potential_rooms.push_back(Room("Et Tu, Brutebot?", {RoomOption(0, 0, 0, 0, robot_capability::pow, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 1, 2, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 2, 3)}));
  775.         //blam/blam/blam missing, blam/blam missing
  776.         collection_bot.potential_rooms.push_back(Room("Gunception", {RoomOption(0, 0, 0, 0, robot_capability::blam, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 1, 2, robot_capability::blam, robot_capability::blam), RoomOption(0, 0, 2, 3)}));
  777.         //pinch/pinch missing, FREE ASSUMED
  778.         collection_bot.potential_rooms.push_back(Room("I See What You Saw", {RoomOption(0, 0, 0, 0, robot_capability::light, robot_capability::light), RoomOption(0, 0, 1, 2, robot_capability::pinch, robot_capability::pinch), RoomOption(0, 0, 2, 3)}));
  779.         collection_bot.potential_rooms.push_back(Room("Unfinished Business", {RoomOption(0, 0, 0, 0, robot_capability::burn), RoomOption(0, 0, 1, 2, robot_capability::lube), RoomOption(0, 0, 2, 3)}));
  780.        
  781.        
  782.         //collection_easy_reward - Too Few Cooks,  Clear Cut Decision,  Messy, Messy
  783.         //Rewards measured from each choice:
  784.         collection_easy_reward.potential_rooms.push_back(Room("Clear Cut Decision", {RoomOption(1, 0, 0, 0), RoomOption(0, 2.0 * 2.598985, 0, 0)}));
  785.         collection_easy_reward.potential_rooms.push_back(Room("Too Few Cooks", {RoomOption(1, 0, 0, 0, robot_capability::freeze), RoomOption(0, 1.0 * 3.716981, 0, 0)}));
  786.         collection_easy_reward.potential_rooms.push_back(Room("Messy, Messy", {RoomOption(1, 0, 0, 0), RoomOption(0, 1.0 * 3.767068, 0, 0, robot_capability::burn)}));
  787.        
  788.         //collection_hard_room_1
  789.         //FIXME POW/POW/POW ASSUMED
  790.         collection_hard_room_1.potential_rooms.push_back(Room("Ultrasecurity Megabot", {RoomOption(0, 0, 1, 2, robot_capability::decode, robot_capability::decode), RoomOption(0, 0, 3, 4, robot_capability::pow, robot_capability::pow, robot_capability::pow), RoomOption(0, 0, 5, 6)}));
  791.         //FIXME LIGHT/LIGHT, PINCH/PINCH, FREE?
  792.         collection_hard_room_1.potential_rooms.push_back(Room("The Big Guns", {RoomOption(0, 0, 1, 2, robot_capability::light, robot_capability::light), RoomOption(0, 0, 3, 4, robot_capability::pinch, robot_capability::pinch), RoomOption(0, 0, 5, 6)}));
  793.         //FIXME freeze/freeze, zap/zap, free?
  794.         collection_hard_room_1.potential_rooms.push_back(Room("Flameybot", {RoomOption(0, 0, 1, 2, robot_capability::freeze, robot_capability::freeze), RoomOption(0, 0, 3, 4, robot_capability::zap, robot_capability::zap), RoomOption(0, 0, 5, 6)}));
  795.        
  796.         //collection_hard_room_2 - Phony
  797.         collection_hard_room_2.potential_rooms.push_back(Room("Phony", {RoomOption(1, 0, 0, 0), RoomOption(0, 5, 0, 0)}));
  798.        
  799.         //collection_obstacle - Fire! Fire! Fire!, Freeze!, What a Grind
  800.         //FIXME DAMAGE RANGES NEED SPADING
  801.         collection_obstacle.potential_rooms.push_back(Room("Fire! Fire! Fire!", {RoomOption(0, 0, 2, 3, robot_capability::run, robot_capability::run), RoomOption(0, 0, 3, 4, robot_capability::freeze, robot_capability::freeze), RoomOption(0, 0, 4, 5)}));
  802.         //FIXME DAMAGE RANGES NEED SPADING
  803.         collection_obstacle.potential_rooms.push_back(Room("Freeze!", {RoomOption(0, 0, 2, 3, robot_capability::roll, robot_capability::roll), RoomOption(0, 0, 3, 4, robot_capability::burn, robot_capability::burn), RoomOption(0, 0, 4, 5)}));
  804.         //FIXME DAMAGE RANGES NEED SPADING
  805.         collection_obstacle.potential_rooms.push_back(Room("What a Grind", {RoomOption(0, 0, 2, 3, robot_capability::hover), RoomOption(0, 0, 3, 4, robot_capability::lube), RoomOption(0, 0, 4, 5)}));
  806.        
  807.         collection_choice.potential_rooms.push_back(Room("Risk vs. Reward", {RoomOption(0, 0, 0, 0), RoomOption(0, 0, 0, 0)}));
  808.        
  809.        
  810.         for (int room_number = 2; room_number < 100; room_number += 4)
  811.         {
  812.             factory_layout.third_area_layout_easy_path[room_number] = collection_bot;
  813.             factory_layout.third_area_layout_easy_path[room_number + 1] = collection_choice;
  814.             factory_layout.third_area_layout_easy_path[room_number + 2] = collection_easy_reward;
  815.             factory_layout.third_area_layout_easy_path[room_number + 3] = collection_obstacle;
  816.         }
  817.        
  818.         for (int room_number = 2; room_number < 100; room_number += 5)
  819.         {
  820.             factory_layout.third_area_layout_hard_path[room_number] = collection_bot;
  821.             factory_layout.third_area_layout_hard_path[room_number + 1] = collection_choice;
  822.             factory_layout.third_area_layout_hard_path[room_number + 2] = collection_hard_room_1;
  823.             factory_layout.third_area_layout_hard_path[room_number + 3] = collection_hard_room_2;
  824.             factory_layout.third_area_layout_hard_path[room_number + 4] = collection_obstacle;
  825.         }
  826.        
  827.         factory_layout.third_area_layout_hard_then_easy_path[2] = collection_bot;
  828.         factory_layout.third_area_layout_hard_then_easy_path[3] = collection_choice;
  829.         factory_layout.third_area_layout_hard_then_easy_path[4] = collection_hard_room_1;
  830.         factory_layout.third_area_layout_hard_then_easy_path[5] = collection_hard_room_2;
  831.         factory_layout.third_area_layout_hard_then_easy_path[6] = collection_obstacle;
  832.         for (int room_number = 7; room_number < 100; room_number += 4)
  833.         {
  834.             factory_layout.third_area_layout_hard_then_easy_path[room_number] = collection_bot;
  835.             factory_layout.third_area_layout_hard_then_easy_path[room_number + 1] = collection_choice;
  836.             factory_layout.third_area_layout_hard_then_easy_path[room_number + 2] = collection_easy_reward;
  837.             factory_layout.third_area_layout_hard_then_easy_path[room_number + 3] = collection_obstacle;
  838.         }
  839.        
  840.     }
  841.    
  842.     if (false) //Output part-giving rooms instead.
  843.     {
  844.         std::map <std::string, bool> seen_names;
  845.         for (const auto & map : {factory_layout.first_area_layout, factory_layout.second_area_layout_up_path, factory_layout.second_area_layout_down_path, factory_layout.third_area_layout_easy_path, factory_layout.third_area_layout_hard_path, factory_layout.third_area_layout_hard_then_easy_path})
  846.         {
  847.             for (const auto & iterator : map)
  848.             {
  849.                 const RoomCollection & collection = iterator.second;
  850.                
  851.                 for (const Room & room : collection.potential_rooms)
  852.                 {
  853.                     for (const RoomOption & option : room.options)
  854.                     {
  855.                         if (option.parts_given > 0.0)
  856.                         //if ((option.parts_given > 0.0 || option.schematics_given > 0.0) && room.options.size() > 1)
  857.                             seen_names[room.name] = true;
  858.                     }
  859.                 }
  860.             }
  861.         }
  862.         printf("Part-giving rooms:\n");
  863.         for (const auto & iterator : seen_names)
  864.         {
  865.             const std::string & name = iterator.first;
  866.             printf("%s\n", name.c_str());
  867.         }
  868.         return 0;
  869.     }
  870.    
  871.     if (setting_use_exact_simulation)
  872.         printf("Floor\tStrategy\tChoose parts or schematics?\tLeft arm\tRight arm\tTorso\tPropulsion\tAverage credits found\tAverage schematics found\n");
  873.     else
  874.         printf("Floor\tStrategy\tChoose parts or schematics?\tLeft arm\tRight arm\tTorso\tPropulsion\tAverage credits found\tAverage schematics found\tAverage rooms ended at\tFurthest room ended at\tLikelyhood of reaching that room\n");
  875.     unsigned int simulation_count = 10000000;
  876.     simulation_count = 1000000;
  877.     //simulation_count = 100000000;
  878.    
  879.     if (false)
  880.     {
  881.         //Former debug:
  882.         simulation_count = 10000000;
  883.         //Camera Claw   Cold Shoulder   Nerding Module  Rocket Skirt
  884.         simulateAllAndOutput(factory_layout, simulation_count, parts_list[robot_part_location::left_arm][10], parts_list[robot_part_location::right_arm][9], parts_list[robot_part_location::torso][9], parts_list[robot_part_location::propulsion][10], 1, 1, true);
  885.         return 0;
  886.     }
  887.    
  888.     if (!setting_use_exact_simulation) //individualised threading, faster for monte carlo
  889.     {
  890.         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)
  891.         //essentially, a bunch of these executions terminate early and show up in our queue and count against our limit
  892.         //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
  893.         //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
  894.         std::queue <std::thread> active_threads;
  895.        
  896.         for (RobotPart part_left_arm : parts_list[robot_part_location::left_arm])
  897.         {
  898.             for (RobotPart part_right_arm : parts_list[robot_part_location::right_arm])
  899.             {
  900.                 for (RobotPart part_torso : parts_list[robot_part_location::torso])
  901.                 {
  902.                     for (RobotPart part_propulsion : parts_list[robot_part_location::propulsion])
  903.                     {
  904.                         for (int floor = setting_simulate_floor_min; floor <= setting_simulate_floor_max; floor++)
  905.                         {
  906.                             int max_strategy = 1;
  907.                             if (floor == 2)
  908.                                 max_strategy = 2;
  909.                             if (floor == 3)
  910.                                 max_strategy = 3;
  911.                             for (int strategy = 1; strategy <= max_strategy; strategy++)
  912.                             {
  913.                                 if (active_threads.size() >= wanted_thread_count)
  914.                                 {
  915.                                     active_threads.front().join();
  916.                                     active_threads.pop();
  917.                                 }
  918.                                 if (setting_simulate_schematics_as_well)
  919.                                     active_threads.push(std::thread(simulateAllAndOutput, factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, strategy, false));
  920.                                 active_threads.push(std::thread(simulateAllAndOutput, factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, strategy, true));
  921.                             }
  922.                         }
  923.                     }
  924.                 }
  925.             }
  926.         }
  927.         while (active_threads.size() > 0)
  928.         {
  929.             active_threads.front().join();
  930.             active_threads.pop();
  931.         }
  932.     }
  933.     else
  934.     {
  935.         for (RobotPart part_left_arm : parts_list[robot_part_location::left_arm])
  936.         {
  937.             for (RobotPart part_right_arm : parts_list[robot_part_location::right_arm])
  938.             {
  939.                 for (RobotPart part_torso : parts_list[robot_part_location::torso])
  940.                 {
  941.                     for (RobotPart part_propulsion : parts_list[robot_part_location::propulsion])
  942.                     {
  943.                         for (int floor = setting_simulate_floor_min; floor <= setting_simulate_floor_max; floor++)
  944.                         {
  945.                             int max_strategy = 1;
  946.                             if (floor == 2)
  947.                                 max_strategy = 2;
  948.                             if (floor == 3)
  949.                                 max_strategy = 3;
  950.                             for (int strategy = 1; strategy <= max_strategy; strategy++)
  951.                             {
  952.                                 if (setting_simulate_schematics_as_well)
  953.                                     simulateAllAndOutput(factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, strategy, false);
  954.                                 simulateAllAndOutput(factory_layout, simulation_count, part_left_arm, part_right_arm, part_torso, part_propulsion, floor, strategy, true);
  955.                             }
  956.                         }
  957.                     }
  958.                 }
  959.             }
  960.         }
  961.     }
  962.    
  963.     auto end_time = std::chrono::high_resolution_clock::now();
  964.     double computation_time = std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time).count();
  965.     printf("Computed in %f seconds.\n", computation_time);
  966.    
  967.     return 0;
  968. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement