yojimbos_law

spaghetti code battlefield strategy simulator

Nov 24th, 2018
356
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.61 KB | None | 0 0
  1.  
  2. int trials = 10000;
  3. boolean olfacted = false;
  4. int max_banishes = 6;
  5. boolean[int] trial_banishes;
  6. //percent out of 100 that a green smoke bomb drops. base rate is 4.
  7. int drop_rate = 4*(1+20);
  8.  
  9. //maintaining drop rate is nontrivial, I guess.
  10. int bad_drop_rate = 4*(1+10);
  11. //number of green smoke bombs gotten during each trial.
  12. int[int] trial_bombs;
  13.  
  14. int[int] buffer_queue;
  15.  
  16. //similar role of in-game battlefield image but more precise.
  17. int battlefield_state;
  18.  
  19. //now here's the correspondence between battlefield state and kills, assuming the nuns trick and no thanksgarden bullshit.
  20. int[int] state_correspondence = { 2, 2, 1, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2 };
  21.  
  22. //for reference: state_correspondence[i] is the number of kills occurring in the i-th state.
  23. //observe that the sum of the number of kills is 34, as one would expect given familiarity with the battlefield.
  24.  
  25.  
  26. //okay, here's where we define the battlefield's monster distribution. this is a little gross and could probably be nicer if I worked with its transpose.
  27. int[int][int] pre_battlefield_distribution;
  28.  
  29. pre_battlefield_distribution[1] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 };
  30. pre_battlefield_distribution[2] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  31. pre_battlefield_distribution[3] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  32. pre_battlefield_distribution[4] = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
  33. pre_battlefield_distribution[5] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 };
  34. pre_battlefield_distribution[6] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0 };
  35. pre_battlefield_distribution[7] = { 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  36. pre_battlefield_distribution[8] = { 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0 };
  37. pre_battlefield_distribution[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
  38. pre_battlefield_distribution[10] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  39. pre_battlefield_distribution[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  40. pre_battlefield_distribution[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 };
  41. pre_battlefield_distribution[13] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  42. //14 is green ops soldier.
  43. pre_battlefield_distribution[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  44. pre_battlefield_distribution[15] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  45. pre_battlefield_distribution[16] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
  46. pre_battlefield_distribution[17] = { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  47. pre_battlefield_distribution[18] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
  48.  
  49. //in fact, let's take the transpose of that because it's going to be easier later.
  50. int[int][int] battlefield_distribution;
  51.  
  52. foreach i,j in pre_battlefield_distribution{
  53. battlefield_distribution[j][i] = pre_battlefield_distribution[i][j];
  54. }
  55.  
  56. //now we have battlefield_distribution[i] being the array of copies of each monster during battlefield state i.
  57.  
  58. //let's compute the sum of copies in each state.
  59. //this is needed later and will be more efficient to handle here than repeatedly during iteration.
  60.  
  61. int[int] state_copy_sum;
  62. for i from 0 to 21{
  63. foreach j in battlefield_distribution[i]{
  64. state_copy_sum[i] += battlefield_distribution[i][j];
  65. }
  66. }
  67.  
  68.  
  69. //these monsters are probably the best to banish.
  70. //yay heuristics!
  71. boolean[int] banishable;
  72. banishable[1] = false;
  73. banishable[2] = false;
  74. banishable[3] = false;
  75. banishable[4] = false;
  76. banishable[5] = false;
  77. banishable[6] = true;
  78. banishable[7] = false;
  79. banishable[8] = true;
  80. banishable[9] = true;
  81. banishable[10] = true;
  82. banishable[11] = true;
  83. banishable[12] = false;
  84. banishable[13] = false;
  85. banishable[14] = false;
  86. banishable[15] = true;
  87. banishable[16] = false;
  88. banishable[17] = true;
  89. banishable[18] = false;
  90.  
  91. //here's the function that's going to be selecting encounters. It's gr8.
  92. //compute sum of distribution outside of function for efficiency.
  93. int select(int[int] copy_distribution, int distribution_sum){
  94. int selection = -1;
  95. int pre_selection = -1;
  96. boolean in_queue;
  97. boolean is_banished;
  98. int rejection_roll = 4;
  99. if(olfacted && copy_distribution[14] > 0){
  100. //3 from olfaction, 1 from turtle sex, 1 from latte sex
  101. copy_distribution[14] += 5;
  102. distribution_sum += 5;
  103. }
  104.  
  105. //this iterates until we pass a 3/4 rejection roll.
  106. while(selection == -1){
  107. //roll a random number between 0 and [total number of copies] - 1 inclusive, shift to range [1,total]
  108. pre_selection = random(distribution_sum) + 1;
  109. //discern which monster that roll corresponds to.
  110. foreach i in copy_distribution{
  111. //decrement roll by the number of copies corresponding to monster i.
  112. pre_selection -= copy_distribution[i];
  113. //the monster that exhausts this quantity is the one we rolled.
  114. if(pre_selection <= 0){
  115. selection = i;
  116. break;
  117. }
  118. }
  119.  
  120. //only check for rejection and banishing if the thing isn't olfacted.
  121. if(!( selection == 14 && olfacted ) ){
  122. //now we check if the monster is in the queue.
  123. in_queue = false;
  124. for i from 1 to 5{
  125. if(selection == buffer_queue[i]){
  126. in_queue = true;
  127. }
  128. }
  129.  
  130. //if it is, we apply the typical 3/4 rejection rate.
  131. if(in_queue){
  132. rejection_roll = random(4);
  133. //if the roll isn't 1, we reject it and start over.
  134. if(rejection_roll != 1){
  135. selection = -1;
  136. }
  137. }
  138.  
  139. //now we check if the monster is banished
  140. foreach i in trial_banishes{
  141. //if a banished monster is the same monster as the selection, we reject it.
  142. if(trial_banishes[i] && i == selection){
  143. selection = -1;
  144. break;
  145. }
  146. }
  147. }
  148. }
  149.  
  150.  
  151. //shift queue left.
  152. for i from 2 to 5 {
  153. buffer_queue[i-1] = buffer_queue[i];
  154. }
  155.  
  156. //put selection in rightmost queue slot.
  157. buffer_queue[5] = selection;
  158.  
  159. return selection;
  160. }
  161.  
  162. int[int] trial_encounters;
  163. int[int] trial_meatballs;
  164. int[int] copies;
  165. int[int] trial_good_meatballs;
  166. int turns_of_good_meatballs = 10;
  167. boolean[int] running = {true, false};
  168. int remaining_effects;
  169.  
  170. int kills_in_state;
  171. int selected_fight;
  172. int available_banishes;
  173.  
  174. //we olfact it before because wishing/faxing.
  175. olfacted = true;
  176. //this is how long our good +item% lasts
  177. for x from 0 to turns_of_good_meatballs{
  178. //this is whether we run away to preserve our good +item%.
  179. foreach y in running{
  180. //this is how many banishes we can use.
  181. for z from 3 to 6{
  182.  
  183. //clear the maps that record each of our simulations.
  184. clear(trial_good_meatballs);
  185. clear(trial_meatballs);
  186. clear(trial_encounters);
  187. clear(trial_bombs);
  188.  
  189. //do a bunch of simulations with the strategy specified by parameters x,y,z.
  190. for m from 1 to trials{
  191.  
  192. //reset all the stuff from the previous trial.
  193. battlefield_state = 0;
  194. available_banishes = z;
  195. clear(buffer_queue);
  196. //start with empty queue
  197. buffer_queue[1] = -1;
  198. buffer_queue[2] = -1;
  199. buffer_queue[3] = -1;
  200. buffer_queue[4] = -1;
  201. buffer_queue[5] = -1;
  202. //this only matters if you allow 0 to be a monster, which I used to.
  203.  
  204. //clear queue manipulation.
  205. //don't clear olfaction because we're assuming faxed/wished meatball.
  206. //olfacted = false;
  207.  
  208. for i from 1 to 18{
  209. trial_banishes[i] = false;
  210. }
  211.  
  212. //dunno why I do this.
  213. clear(copies);
  214.  
  215. //this is the maximum number of good meatballs we can have. we're going to start decrementing it after state 10 begins.
  216. remaining_effects = x;
  217.  
  218. //let's clear a battlefield.
  219. //these are the 22 battlefield states.
  220. for i from 0 to 21{
  221. kills_in_state = 0;
  222. //kill 1-2 things.
  223. while(kills_in_state < state_correspondence[i]){
  224.  
  225. selected_fight = select(battlefield_distribution[i], state_copy_sum[i]);
  226.  
  227. if(banishable[selected_fight] && !trial_banishes[selected_fight] && available_banishes > 0){
  228.  
  229. //batter up kills the monster if we haven't banished anything yet.
  230. if(available_banishes == max_banishes){
  231. kills_in_state++;
  232. }
  233.  
  234. available_banishes += -1;
  235. trial_banishes[selected_fight] = true;
  236.  
  237. }
  238. else{
  239. //this is where we do dirty things to green ops soldiers.
  240. if(selected_fight == 14){
  241.  
  242. olfacted = true;
  243. if(remaining_effects > 0){
  244. if(random(100) < drop_rate){
  245. trial_bombs[m]++;
  246. }
  247. //two possible green smoke bombs.
  248. if(random(100) < drop_rate){
  249. trial_bombs[m]++;
  250. }
  251. trial_good_meatballs[m]++;
  252. remaining_effects -= 1;
  253. }
  254. else{
  255. if(random(100) < bad_drop_rate){
  256. trial_bombs[m]++;
  257. }
  258. //two possible green smoke bombs.
  259. if(random(100) < bad_drop_rate){
  260. trial_bombs[m]++;
  261. }
  262.  
  263. }
  264. //this gets incremented either way.
  265. trial_meatballs[m]++;
  266. kills_in_state++;
  267. }
  268. else{
  269. //this is where we kill useless monsters or use bombs on them.
  270. //using bombs on them is probably bad, but who knows.
  271. //kills_in_state++;
  272.  
  273.  
  274. //checks whether meatballs are available and whether preserving effects matters.
  275. //this is close enough to practical applications.
  276. if(remaining_effects > 0 && i >= 10 && running[y]){
  277. //use bombs instead of killing.
  278. //allows bombs to go negative because that's just as meaningful (virtually all routes will start by getting 4-8 green smoke bombs from the wished/faxed one).
  279. trial_bombs[m] -= 1;
  280. while(random(10) == 9){
  281. trial_bombs[m] -= 1;
  282. }
  283. }
  284. else{
  285. //just kill as usual.
  286. kills_in_state++;
  287. //decrement effects after reaching state 10.
  288. if(i >= 10 && remaining_effects > 0){
  289. remaining_effects -= 1;
  290. }
  291. }
  292.  
  293. }
  294. }
  295. trial_encounters[m]++;
  296. }
  297. }
  298. if(m%(trials/5) == 0){
  299. //print((m.to_float() / trials.to_float())+" of the way done with "+trials+" trials.");
  300. }
  301. }
  302.  
  303.  
  304. int total_meatballs;
  305.  
  306. foreach i in trial_meatballs{
  307. total_meatballs += trial_meatballs[i];
  308. }
  309. float average = total_meatballs.to_float() / trials.to_float();
  310. print("average: "+average);
  311.  
  312. float variance;
  313.  
  314. foreach i in trial_meatballs{
  315. variance += ( trial_meatballs[i].to_float() - average )**2;
  316. }
  317.  
  318. variance /= trials.to_float();
  319.  
  320. print("sexually transmitted disease: "+(variance**(0.5)));
  321.  
  322.  
  323.  
  324. int total_bombs;
  325.  
  326. foreach i in trial_bombs{
  327. total_bombs += trial_bombs[i];
  328. }
  329.  
  330. average = total_bombs.to_float() / trials.to_float();
  331. print("average bombs: "+average);
  332.  
  333. variance = 0.0;
  334.  
  335. foreach i in trial_bombs{
  336. variance += ( trial_bombs[i].to_float() - average )**2;
  337. }
  338.  
  339. variance /= trials.to_float();
  340.  
  341. print("sexually transmitted disease bombs (gross): "+(variance**(0.5)));
  342.  
  343.  
  344.  
  345. int total_encounters;
  346.  
  347. foreach i in trial_encounters{
  348. total_encounters += trial_encounters[i];
  349. }
  350.  
  351. average = total_encounters.to_float() / trials.to_float();
  352. print("average encounters: "+average);
  353.  
  354. variance = 0.0;
  355.  
  356. foreach i in trial_encounters{
  357. variance += ( trial_encounters[i].to_float() - average )**2;
  358. }
  359.  
  360. variance /= trials.to_float();
  361.  
  362. print("sexually transmitted disease encounters (gross): "+(variance**(0.5)));
  363.  
  364.  
  365. int total_good_meatballs;
  366.  
  367. foreach i in trial_good_meatballs{
  368. total_good_meatballs += trial_good_meatballs[i];
  369. }
  370.  
  371. average = total_good_meatballs.to_float() / trials.to_float();
  372. print("average good meatballs: "+average);
  373.  
  374. variance = 0.0;
  375.  
  376. foreach i in trial_good_meatballs{
  377. variance += ( trial_good_meatballs[i].to_float() - average )**2;
  378. }
  379.  
  380. variance /= trials.to_float();
  381.  
  382. print("sexually transmitted disease good meatballs: "+(variance**(0.5)));
  383.  
  384. print("with "+z+" available banishes, \+"+(drop_rate/4-1)+"00% item for at most "+x+" meatballs (\+"+(bad_drop_rate/4-1)+"00% for the remainder),");
  385. if(running[y]){
  386. print("and running away to preserve effects");
  387. }
  388. else{
  389. print("and not running away to preserve effects");
  390. }
  391. print("================================");
  392. }
  393. }
  394. }
Advertisement
Add Comment
Please, Sign In to add comment