Advertisement
aaaaaa123456789

firefight's simulator

May 28th, 2013
106
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdlib.h>
  2. #include <string.h>
  3.  
  4. typedef struct {
  5.   long double hitChance;
  6.   unsigned char maxDamage;
  7.   unsigned char hitPoints;
  8. } PlayerInfo;
  9.  
  10. typedef struct {
  11.   long double win;
  12.   long double lose;
  13.   long double draw;
  14. } Odds;
  15.  
  16. const Odds error = {0, 0, 0};
  17.  
  18. static void turnsOdds(unsigned char, long double *, long double **, unsigned *, long double);
  19. static void hitsOdds(unsigned char, long double, long double *);
  20. static void multiplyVector(long double *, long double *, long double);
  21. static void addVector(long double *, long double *);
  22. static long double totalOdds(long double *);
  23. static long double currentError(long double *, unsigned char);
  24. static void expand(long double **, unsigned, unsigned);
  25. static Odds calculateFor(long double *, long double *, unsigned);
  26.  
  27. Odds calculateOdds (PlayerInfo p1, PlayerInfo p2, long double threshold) {
  28.   unsigned t1, t2;
  29.   long double * odds1;
  30.   long double * odds2;
  31.   long double hitodds1[12];
  32.   long double hitodds2[12];
  33.   unsigned turns;
  34.   if ((p1.hitChance < 0) || (p1.hitChance > 1)) return error;
  35.   if ((p2.hitChance < 0) || (p2.hitChance > 1)) return error;
  36.   if ((!p1.maxDamage) || (p1.maxDamage > 11)) return error;
  37.   if ((!p2.maxDamage) || (p2.maxDamage > 11)) return error;
  38.   if (p1.hitPoints > 99) return error;
  39.   if (p2.hitPoints > 99) return error;
  40.   if ((threshold <= 0) || (threshold >= 1)) return error;
  41.   hitsOdds(p1.maxDamage, p1.hitChance, hitodds1);
  42.   hitsOdds(p2.maxDamage, p2.hitChance, hitodds2);
  43.   turnsOdds(p2.hitPoints, hitodds1, &odds1, &t1, threshold);
  44.   turnsOdds(p1.hitPoints, hitodds2, &odds2, &t2, threshold);
  45.   if (t1 < t2) {
  46.     expand(&odds1, t1, t2);
  47.     turns = t2;
  48.   } else if (t2 < t1) {
  49.     expand(&odds2, t2, t1);
  50.     turns = t1;
  51.   } else
  52.     turns = t1;
  53.   Odds result = calculateFor(odds1, odds2, turns);
  54.   free(odds1);
  55.   free(odds2);
  56.   long double totalError = 1;
  57.   totalError -= result.win;
  58.   totalError -= result.lose;
  59.   totalError -= result.draw;
  60.   if ((totalError * totalError) > (threshold * threshold * 10)) return calculateOdds(p1, p2, threshold / 10);
  61.   result.draw += totalError;
  62.   return result;
  63. }
  64.  
  65. static void turnsOdds (unsigned char opponentHP, long double * hitOdds, long double ** result, unsigned * resultSize, long double threshold) {
  66.   unsigned turns = 0;
  67.   long double * turnOdds = malloc(sizeof(long double));
  68.   *turnOdds = 1;
  69.   long double damageDealtA[111];
  70.   long double damageDealtB[111];
  71.   unsigned char current = 0;
  72.   long double * damageDealt;
  73.   long double * damageDealtPrev;
  74.   memset(damageDealtA, 0, 111 * sizeof(long double));
  75.   *damageDealtA = 1;
  76.   unsigned currentTurn;
  77.   long double curDamage[12];
  78.   unsigned char curHP;
  79.   do {
  80.     currentTurn = turns;
  81.     turns += 20;
  82.     turnOdds = realloc(turnOdds, sizeof(long double) * (turns + 1));
  83.     for (currentTurn ++; currentTurn <= turns; currentTurn ++) {
  84.       damageDealtPrev = current ? damageDealtB : damageDealtA;
  85.       damageDealt = current ? damageDealtA : damageDealtB;
  86.       memset(damageDealt, 0, 111 * sizeof(long double));
  87.       for (curHP = 0; curHP < opponentHP; curHP ++) {
  88.         multiplyVector(curDamage, hitOdds, damageDealtPrev[curHP]);
  89.         addVector(damageDealt + curHP, curDamage);
  90.       }
  91.       turnOdds[currentTurn] = totalOdds(damageDealt + opponentHP);
  92.       current = !current;
  93.     }
  94.     damageDealt = current ? damageDealtA : damageDealtB;
  95.     *turnOdds = currentError(damageDealt, opponentHP);
  96.   } while (*turnOdds >= threshold);
  97.   *result = turnOdds;
  98.   *resultSize = turns;
  99. }
  100.  
  101. static void hitsOdds (unsigned char maxDamage, long double hitChance, long double * result) {
  102.   *result = 1 - hitChance;
  103.   long double x = hitChance / maxDamage;
  104.   unsigned char pos;
  105.   for (pos = 1; pos <= maxDamage; pos ++) result[pos] = x;
  106.   for (; pos <= 11; pos ++) result[pos] = 0;
  107. }
  108.  
  109. static void multiplyVector (long double * result, long double * src, long double value) {
  110.   unsigned char pos;
  111.   for (pos = 0; pos < 12; pos ++)
  112.     result[pos] = src[pos] * value;
  113. }
  114.  
  115. static void addVector (long double * dst, long double * src) {
  116.   unsigned char pos;
  117.   for (pos = 0; pos < 12; pos ++)
  118.     dst[pos] += src[pos];
  119. }
  120.  
  121. static long double totalOdds (long double * damageOdds) {
  122.   long double total = 0;
  123.   unsigned char pos;
  124.   for (pos = 0; pos < 12; pos ++)
  125.     total += damageOdds[pos];
  126.   return total;
  127. }
  128.  
  129. static long double currentError (long double * damageOdds, unsigned char maxDamage) {
  130.   long double total = 0;
  131.   unsigned char pos;
  132.   for (pos = 0; pos < maxDamage; pos ++)
  133.     total += damageOdds[pos];
  134.   return total;
  135. }
  136.  
  137. static void expand (long double ** turnOdds, unsigned from, unsigned to) {
  138.   *turnOdds = realloc(*turnOdds, sizeof(long double) * (to + 1));
  139.   unsigned pos;
  140.   for (pos = from + 1; pos <= to; pos ++)
  141.     (*turnOdds)[pos] = 0;
  142. }
  143.  
  144. static Odds calculateFor (long double * turnOdds1, long double * turnOdds2, unsigned turns) {
  145.   long double r0 = 0, r1 = 0, r2 = 0;
  146.   unsigned turn1, turn2;
  147.   for (turn1 = 1; turn1 <= turns; turn1 ++) {
  148.     for (turn2 = 1; turn2 < turn1; turn2 ++)
  149.       r2 += turnOdds1[turn1] * turnOdds2[turn2];
  150.     r0 += turnOdds1[turn1] * turnOdds2[turn1];
  151.     for (turn2 = turn1 + 1; turn2 <= turns; turn2 ++)
  152.       r1 += turnOdds1[turn1] * turnOdds2[turn2];
  153.     r1 += turnOdds1[turn1] * (*turnOdds2);
  154.   }
  155.   for (turn2 = 1; turn2 <= turns; turn2 ++)
  156.     r2 += turnOdds2[turn2] * (*turnOdds1);
  157.   r0 += (*turnOdds1) * (*turnOdds2);
  158.   return (Odds) {.win = r1, .lose = r2, .draw = r0};
  159. }
Advertisement
RAW Paste Data Copied
Advertisement