yojimbos_law

battlefield strategy simulator.

Dec 4th, 2018
502
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.79 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. if(running[y]){
  181. //this is how many banishes we can use.
  182. for z from 3 to 6{
  183.  
  184. //clear the maps that record each of our simulations.
  185. clear(trial_good_meatballs);
  186. clear(trial_meatballs);
  187. clear(trial_encounters);
  188. clear(trial_bombs);
  189.  
  190. //do a bunch of simulations with the strategy specified by parameters x,y,z.
  191. for m from 1 to trials{
  192.  
  193. //reset all the stuff from the previous trial.
  194. battlefield_state = 0;
  195. available_banishes = z;
  196. clear(buffer_queue);
  197. //start with empty queue
  198. buffer_queue[1] = -1;
  199. buffer_queue[2] = -1;
  200. buffer_queue[3] = -1;
  201. buffer_queue[4] = -1;
  202. buffer_queue[5] = -1;
  203. //this only matters if you allow 0 to be a monster, which I used to.
  204.  
  205. //clear queue manipulation.
  206. //don't clear olfaction because we're assuming faxed/wished meatball.
  207. //olfacted = false;
  208.  
  209. for i from 1 to 18{
  210. trial_banishes[i] = false;
  211. }
  212.  
  213. //dunno why I do this.
  214. clear(copies);
  215.  
  216. //this is the maximum number of good meatballs we can have. we're going to start decrementing it after state 10 begins.
  217. remaining_effects = x;
  218.  
  219. //let's clear a battlefield.
  220. //these are the 22 battlefield states.
  221. for i from 0 to 21{
  222. kills_in_state = 0;
  223. //kill 1-2 things.
  224. while(kills_in_state < state_correspondence[i]){
  225.  
  226. selected_fight = select(battlefield_distribution[i], state_copy_sum[i]);
  227.  
  228. if(banishable[selected_fight] && i < 10 && available_banishes == z){
  229.  
  230. //batter up kills the monster if we haven't banished anything yet.
  231. kills_in_state++;
  232. available_banishes += -1;
  233. trial_banishes[selected_fight] = true;
  234.  
  235. }
  236. else{
  237. //this is where we do dirty things to green ops soldiers.
  238. if(selected_fight == 14){
  239.  
  240. //set olfaction here if not doing it preemptively above.
  241. //olfacted = true;
  242. if(remaining_effects > 0){
  243. if(random(100) < drop_rate){
  244. trial_bombs[m]++;
  245. }
  246. //two possible green smoke bombs.
  247. if(random(100) < drop_rate){
  248. trial_bombs[m]++;
  249. }
  250. trial_good_meatballs[m]++;
  251. remaining_effects -= 1;
  252. }
  253. else{
  254. if(random(100) < bad_drop_rate){
  255. trial_bombs[m]++;
  256. }
  257. //two possible green smoke bombs.
  258. if(random(100) < bad_drop_rate){
  259. trial_bombs[m]++;
  260. }
  261.  
  262. }
  263. //this gets incremented either way.
  264. trial_meatballs[m]++;
  265. kills_in_state++;
  266. }
  267. else{
  268. //this is where we kill useless monsters or use bombs on them.
  269. //using bombs on them is probably bad, but who knows.
  270. //kills_in_state++;
  271.  
  272.  
  273. //checks whether meatballs are available and whether preserving effects matters.
  274. //this is close enough to practical applications.
  275. if(remaining_effects > 0 && i >= 10 && running[y] && available_banishes > 0 && banishable[selected_fight] ){
  276. /*
  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.  
  285. available_banishes += -1;
  286. trial_banishes[selected_fight] = true;
  287. }
  288. else{
  289. //just kill as usual.
  290. kills_in_state++;
  291. //decrement effects after reaching state 10.
  292. if(i >= 10 && remaining_effects > 0){
  293. remaining_effects -= 1;
  294. }
  295. }
  296.  
  297. }
  298. }
  299. trial_encounters[m]++;
  300. }
  301. }
  302. if(m%(trials/5) == 0){
  303. //print((m.to_float() / trials.to_float())+" of the way done with "+trials+" trials.");
  304. }
  305. }
  306.  
  307.  
  308. int total_meatballs;
  309.  
  310. foreach i in trial_meatballs{
  311. total_meatballs += trial_meatballs[i];
  312. }
  313. float average = total_meatballs.to_float() / trials.to_float();
  314. print("average: "+average);
  315.  
  316. float variance;
  317.  
  318. foreach i in trial_meatballs{
  319. variance += ( trial_meatballs[i].to_float() - average )**2;
  320. }
  321.  
  322. variance /= trials.to_float();
  323.  
  324. print("sexually transmitted disease: "+(variance**(0.5)));
  325.  
  326.  
  327.  
  328. int total_bombs;
  329.  
  330. foreach i in trial_bombs{
  331. total_bombs += trial_bombs[i];
  332. }
  333.  
  334. average = total_bombs.to_float() / trials.to_float();
  335. print("average bombs: "+average);
  336.  
  337. variance = 0.0;
  338.  
  339. foreach i in trial_bombs{
  340. variance += ( trial_bombs[i].to_float() - average )**2;
  341. }
  342.  
  343. variance /= trials.to_float();
  344.  
  345. print("sexually transmitted disease bombs (gross): "+(variance**(0.5)));
  346.  
  347.  
  348.  
  349. int total_encounters;
  350.  
  351. foreach i in trial_encounters{
  352. total_encounters += trial_encounters[i];
  353. }
  354.  
  355. average = total_encounters.to_float() / trials.to_float();
  356. print("average encounters: "+average);
  357.  
  358. variance = 0.0;
  359.  
  360. foreach i in trial_encounters{
  361. variance += ( trial_encounters[i].to_float() - average )**2;
  362. }
  363.  
  364. variance /= trials.to_float();
  365.  
  366. print("sexually transmitted disease encounters (gross): "+(variance**(0.5)));
  367.  
  368.  
  369. int total_good_meatballs;
  370.  
  371. foreach i in trial_good_meatballs{
  372. total_good_meatballs += trial_good_meatballs[i];
  373. }
  374.  
  375. average = total_good_meatballs.to_float() / trials.to_float();
  376. print("average good meatballs: "+average);
  377.  
  378. variance = 0.0;
  379.  
  380. foreach i in trial_good_meatballs{
  381. variance += ( trial_good_meatballs[i].to_float() - average )**2;
  382. }
  383.  
  384. variance /= trials.to_float();
  385.  
  386. print("sexually transmitted disease good meatballs: "+(variance**(0.5)));
  387.  
  388. 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),");
  389. if(running[y]){
  390. print("and running away to preserve effects");
  391. }
  392. else{
  393. print("and not running away to preserve effects");
  394. }
  395. print("================================");
  396. }
  397. }
  398. }
  399. }
Advertisement
Add Comment
Please, Sign In to add comment