Wordman/WyldMagicMath

From Exalted - Unofficial Wiki
Jump to: navigation, search

This page contains more nerdy detail of the math used to select the point totals needed for various circles of sorcery in the Wyld Magic system.

The points needed for each circle were determined using the average number of points per card drawn. For the first draw of the deck, this is computed as follows:

Card Number In Deck Points Per Card Points Possible in Whole Deck
Ace 4 1 4
Two 4 2 8
Three 4 3 12
Four 4 4 16
Five 4 5 20
Six 4 6 24
Seven 4 7 28
Eight 4 8 32
Nine 4 9 36
Ten 4 10 40
Jack 4 0 0
Queen 4 0 0
King 4 0 0
Joker 2 0 0
Total 54 220
Average points per card: 4.074

Even though the math changes as cards are removed from the deck, we'll stick with basic assumption that four points will be generated per card drawn. So based on this, figure out costs for each circle:

  • A minimally competent terrestrial sorcerer has Essence 3 and Occult 3.
  • Doing nothing but channeling, he can choose three cards per action.
  • Three cards would provide a bit more than 12 points.
  • Under canon exalted, a terrestrial spell needs two rounds to cast (one for channeling, one for casting).
  • Two rounds his of channeling would provide 24 points on average, from six cards.
  • To make the average terrestrial spell take two rounds to cast, the point value would need to be greater than 12 but less than 24.
  • Consider the following to figure out where in that range to set the limit:
    • On average, only a quarter of the cards will be diamonds. Very roughly, this would mean 6 diamond points.
    • Presumably, the average case would contain some lower average of, say, spade points, because spade face cards would more often be used to cancel spade points than diamond face cards would be used to cancel diamonds (which should basically never happen).
    • The maximum of one round of this sorcerer's channeling would be 30 points.
    • What percentage of three card hands generate more than 12 points?
    • What percentage of three cards generate more than 12 diamond points?
    • What percentage of three card hands generate more than 12 points when non-diamond face cards cancel the highest card they can?

Three Cards

http://rpg.divnull.com/exalted/images/wyldcard3.png

Total Face Negated Diamonds Total % Face Negated % Diamonds %
0 Points 1,368 7,308 76,488 0.94% 5.04% 52.70%
1 Points 1,896 3,408 5,604 1.31% 2.35% 3.86%
2 Points 2,400 3,696 5,604 1.65% 2.55% 3.86%
3 Points 3,264 4,290 5,868 2.25% 2.96% 4.04%
4 Points 3,888 4,698 5,868 2.68% 3.24% 4.04%
5 Points 4,872 5,412 6,132 3.36% 3.73% 4.23%
6 Points 5,640 5,964 6,138 3.89% 4.11% 4.23%
7 Points 6,744 6,798 6,402 4.65% 4.68% 4.41%
8 Points 7,632 7,470 6,408 5.26% 5.15% 4.42%
9 Points 8,880 8,448 6,678 6.12% 5.82% 4.60%
10 Points 9,888 9,240 6,684 6.81% 6.37% 4.61%
11 Points 9,360 7,470 1,350 6.45% 5.15% 0.93%
12 Points 9,168 7,494 1,098 6.32% 5.16% 0.76%
13 Points 9,168 7,656 1,104 6.32% 5.28% 0.76%
14 Points 8,712 7,416 846 6.00% 5.11% 0.58%
15 Points 8,472 7,338 852 5.84% 5.06% 0.59%
16 Points 7,752 6,834 588 5.34% 4.71% 0.41%
17 Points 7,248 6,492 588 4.99% 4.47% 0.41%
18 Points 6,288 5,748 324 4.33% 3.96% 0.22%
19 Points 5,520 5,142 318 3.80% 3.54% 0.22%
20 Points 4,296 4,134 48 2.96% 2.85% 0.03%
21 Points 3,288 3,288 42 2.27% 2.27% 0.03%
22 Points 2,640 2,640 30 1.82% 1.82% 0.02%
23 Points 2,112 2,112 24 1.46% 1.46% 0.02%
24 Points 1,608 1,608 18 1.11% 1.11% 0.01%
25 Points 1,200 1,200 12 0.83% 0.83% 0.01%
26 Points 816 816 6 0.56% 0.56% 0.00%
27 Points 552 552 6 0.38% 0.38% 0.00%
28 Points 288 288 0 0.20% 0.20% 0.00%
29 Points 144 144 0 0.10% 0.10% 0.00%
30 Points 24 24 0 0.02% 0.02% 0.00%
Mode 10 10 0
Median 12 11 1
Mean 12.424343 11.462502 3.106086
Permutations 145,128

Four Cards

http://rpg.divnull.com/exalted/images/wyldcard4.png

Total Face Negated Diamonds Total % Face Negated % Diamonds %
0 Points 8,424 172,584 3,019,224 0.12% 2.39% 41.82%
1 Points 21,888 91,656 305,952 0.30% 1.27% 4.24%
2 Points 33,264 106,488 305,952 0.46% 1.48% 4.24%
3 Points 53,568 134,784 328,368 0.74% 1.87% 4.55%
4 Points 71,688 152,256 328,368 0.99% 2.11% 4.55%
5 Points 99,072 183,312 350,784 1.37% 2.54% 4.86%
6 Points 126,096 205,368 351,840 1.75% 2.84% 4.87%
7 Points 161,664 240,288 374,256 2.24% 3.33% 5.18%
8 Points 197,352 266,904 375,312 2.73% 3.70% 5.20%
9 Points 243,264 307,632 398,784 3.37% 4.26% 5.52%
10 Points 288,816 340,008 399,864 4.00% 4.71% 5.54%
11 Points 322,944 318,624 117,384 4.47% 4.41% 1.63%
12 Points 350,088 321,576 97,104 4.85% 4.45% 1.35%
13 Points 379,008 334,728 98,184 5.25% 4.64% 1.36%
14 Points 396,048 334,488 76,872 5.49% 4.63% 1.06%
15 Points 414,528 343,680 77,952 5.74% 4.76% 1.08%
16 Points 418,728 337,512 55,608 5.80% 4.68% 0.77%
17 Points 422,400 338,592 55,632 5.85% 4.69% 0.77%
18 Points 411,696 324,216 33,288 5.70% 4.49% 0.46%
19 Points 397,824 314,448 32,256 5.51% 4.36% 0.45%
20 Points 367,752 287,616 8,832 5.09% 3.98% 0.12%
21 Points 334,272 264,720 7,776 4.63% 3.67% 0.11%
22 Points 301,152 244,992 5,712 4.17% 3.39% 0.08%
23 Points 268,416 223,488 4,608 3.72% 3.10% 0.06%
24 Points 234,072 199,728 3,552 3.24% 2.77% 0.05%
25 Points 200,832 175,128 2,448 2.78% 2.43% 0.03%
26 Points 167,040 149,328 1,368 2.31% 2.07% 0.02%
27 Points 137,280 125,400 1,296 1.90% 1.74% 0.02%
28 Points 107,448 100,968 216 1.49% 1.40% 0.00%
29 Points 82,944 79,704 144 1.15% 1.10% 0.00%
30 Points 61,152 60,504 120 0.85% 0.84% 0.00%
31 Points 45,312 45,312 72 0.63% 0.63% 0.00%
32 Points 33,240 33,240 48 0.46% 0.46% 0.00%
33 Points 23,424 23,424 24 0.32% 0.32% 0.00%
34 Points 15,936 15,936 24 0.22% 0.22% 0.00%
35 Points 9,984 9,984 0 0.14% 0.14% 0%
36 Points 5,880 5,880 0 0.08% 0.08% 0%
37 Points 3,072 3,072 0 0.04% 0.04% 0%
38 Points 1,248 1,248 0 0.02% 0.02% 0%
39 Points 384 384 0 0.01% 0.01% 0%
40 Points 24 24 0 0.00% 0.00% 0%
Mode 17 15 0
Median 17 15 2
Mean 16.691567 14.92254 4.172892
Permutations 7,219,224

Five Cards

http://rpg.divnull.com/exalted/images/wyldcard5.png

Total Face Negated Diamonds Total % Face Negated % Diamonds %
0 Points 32,400 3,596,400 114,827,520 0.01% 1.03% 32.88%
1 Points 168,480 2,721,600 15,096,120 0.05% 0.78% 4.32%
2 Points 332,640 3,137,400 15,096,120 0.10% 0.90% 4.32%
3 Points 644,160 4,019,160 16,625,880 0.18% 1.15% 4.76%
4 Points 999,600 4,628,400 16,625,880 0.29% 1.33% 4.76%
5 Points 1,525,920 5,690,400 18,155,640 0.44% 1.63% 5.20%
6 Points 2,168,160 6,560,520 18,267,720 0.62% 1.88% 5.23%
7 Points 2,989,440 7,819,200 19,797,480 0.86% 2.24% 5.67%
8 Points 3,964,560 8,903,400 19,909,560 1.14% 2.55% 5.70%
9 Points 5,187,840 10,436,640 21,551,400 1.49% 2.99% 6.17%
10 Points 6,594,240 11,768,520 21,668,760 1.89% 3.37% 6.20%
11 Points 8,110,080 11,966,760 8,214,480 2.32% 3.43% 2.35%
12 Points 9,623,280 12,636,480 6,914,160 2.76% 3.62% 1.98%
13 Points 11,213,280 13,521,240 7,031,520 3.21% 3.87% 2.01%
14 Points 12,714,720 13,951,320 5,624,400 3.64% 4.00% 1.61%
15 Points 14,233,920 14,628,120 5,741,880 4.08% 4.19% 1.64%
16 Points 15,563,280 14,798,640 4,227,960 4.46% 4.24% 1.21%
17 Points 16,780,320 15,157,080 4,233,360 4.81% 4.34% 1.21%
18 Points 17,740,800 15,050,520 2,719,560 5.08% 4.31% 0.78%
19 Points 18,448,320 15,023,640 2,613,000 5.28% 4.30% 0.75%
20 Points 18,754,800 14,478,000 981,960 5.37% 4.15% 0.28%
21 Points 18,704,640 13,995,840 870,120 5.36% 4.01% 0.25%
22 Points 18,378,720 13,476,600 656,760 5.26% 3.86% 0.19%
23 Points 17,782,080 12,926,400 534,480 5.09% 3.70% 0.15%
24 Points 16,955,760 12,271,800 422,640 4.86% 3.51% 0.12%
25 Points 15,907,200 11,541,840 300,240 4.56% 3.31% 0.09%
26 Points 14,665,440 10,696,440 183,000 4.20% 3.06% 0.05%
27 Points 13,315,680 9,849,960 167,280 3.81% 2.82% 0.05%
28 Points 11,845,200 8,876,280 49,920 3.39% 2.54% 0.01%
29 Points 10,351,200 7,930,920 33,960 2.96% 2.27% 0.01%
30 Points 8,881,440 6,968,760 28,560 2.54% 2.00% 0.01%
31 Points 7,505,280 6,062,400 17,760 2.15% 1.74% 0.01%
32 Points 6,261,840 5,200,200 12,240 1.79% 1.49% 0.00%
33 Points 5,115,360 4,362,600 6,600 1.46% 1.25% 0.00%
34 Points 4,115,040 3,602,040 6,360 1.18% 1.03% 0.00%
35 Points 3,216,480 2,890,320 840 0.92% 0.83% 0.00%
36 Points 2,469,840 2,276,520 600 0.71% 0.65% 0.00%
37 Points 1,844,640 1,742,040 360 0.53% 0.50% 0.00%
38 Points 1,341,600 1,298,400 240 0.38% 0.37% 0.00%
39 Points 953,280 939,240 120 0.27% 0.27% 0.00%
40 Points 665,520 664,440 120 0.19% 0.19% 0.00%
41 Points 452,640 452,640 0 0.13% 0.13% 0%
42 Points 299,040 299,040 0 0.09% 0.09% 0%
43 Points 186,240 186,240 0 0.05% 0.05% 0%
44 Points 110,400 110,400 0 0.03% 0.03% 0%
45 Points 58,080 58,080 0 0.02% 0.02% 0%
46 Points 28,800 28,800 0 0.01% 0.01% 0%
47 Points 11,040 11,040 0 0.00% 0.00% 0%
48 Points 3,360 3,360 0 0.00% 0.00% 0%
49 Points 480 480 0 0.00% 0.00% 0%
50 Points 0 0 0 0% 0% 0%
Mode 20 17 0
Median 21 18 4
Mean 21.014598 18.30114 5.253649
Permutations 349,216,560

Maximum Points

Drawing some cards prohibits the use of others. This changes things as cards are dealt (so I'm not sure averages from above really mean anything). In any case, there is a maximum number of points you can get drawing x cards per round. Since each hand eats the cards of a given rank, the rate points per round as you draw a "maximum hand" each round decreases. For example, when drawing four cards, the first round the maximum is four 10s. The next round, there are no more 10s, so the max would be four 9s. Drawing all cards gives 220 points total.

Round
Cards Drawn Per Round 1 2 3 4 5 6 7 8 9 10 11 12 13 14
3 30 58 84 108 129 148 165 180 192 202 210 216 219 220
4 40 76 108 136 160 180 196 208 216 220
5 49 92 129 160 184 202 214 220
6 58 108 148 180 202 216 220
7 67 122 165 196 216 220
8 76 142 188 214 220
9 84 154 199 219 220
10 92 165 208 220

Maximum Diamonds

Round
Cards Drawn Per Round 1 2 3 4
3 27 45 54 55
4 34 52 55
5 40 55
6 45 55
7 49 55
8 52 55
9 54 55
10 55

Code

This is Python code I used to build the data above. It is pretty completely unoptimized and, thus, pretty slow:

class Card:
   def __init__(self,rank,suit,points):
      self.rank = rank
      self.suit = suit
      self.points = points
      
   def getPoints(self):
      return self.points
   
   def getRank(self):
      return self.rank
   
   def getSuit(self):
      return self.suit

   def __repr__(self):
      result = "%s of %s" % (self.rank, self.suit)
      return result
   
   def __cmp__(self,other):
      result = cmp(self.points,other.points)
      if result == 0:
         result = cmp(self.suit,other.suit) 
      return result
      
class Hand:
   def __init__(self):
      self.cards = []
      
   def getSize(self):
      return len(self.cards)
   
   def pushCard(self,card):
      contains = card in self.cards
      if (not contains):
         self.cards.append(card)
      return not contains
      
   def popCard(self):
      self.cards.pop()
      
   def calculatePoints(self):
      hash = {
         "Diamonds":[],
         "Hearts":[],
         "Clubs":[],
         "Spades":[],
         "Face":[]
      }
      total = 0
      for card in self.cards:
         points = card.getPoints()
         total += points
         suit = card.getSuit()
         rank = card.getRank()
         if (points):
            hash[suit].append(card)
         elif rank is not "Joker":
            hash["Face"].append(card)
      
      diamondpoints = 0
      for card in hash["Diamonds"]:
         points = card.getPoints();
         diamondpoints += points
     
      facetotal = total
      for card in hash["Face"]:
         suit = card.getSuit()
         if (suit != "Diamonds"):
            list = hash[suit]
            list.sort()
            try:
               negatedCard = list.pop()
               facetotal -= negatedCard.getPoints()
            except:
               pass
            
      return (total,facetotal,diamondpoints)

   def __repr__(self):
      result = repr(self.cards)
      return result

      
class Deck:
   def __init__(self):
      cards = []
      suits = ["Diamonds","Hearts","Clubs","Spades"]
      for suit in suits:
         cards.append(Card("Ace",suit,1))
         cards.append(Card("Two",suit,2))
         cards.append(Card("Three",suit,3))
         cards.append(Card("Four",suit,4))
         cards.append(Card("Five",suit,5))
         cards.append(Card("Six",suit,6))
         cards.append(Card("Seven",suit,7))
         cards.append(Card("Eight",suit,8))
         cards.append(Card("Nine",suit,9))
         cards.append(Card("Ten",suit,10))
         cards.append(Card("Jack",suit,0))
         cards.append(Card("Queen",suit,0))
         cards.append(Card("King",suit,0))
      cards.append(Card("Joker","First",0))
      cards.append(Card("Joker","Second",0))
      self.cards = cards
   
   def checkCards(self,results,hand,totalCards):
      size = hand.getSize()
      if size < totalCards:
          for card in self.cards:
             added = hand.pushCard(card)
             if added:
                   self.checkCards(results,hand,totalCards)
                   hand.popCard()

      else:
        self.analyzeHand(results,hand)
   
   def summarizePermutations(self,totalCards):
      results = {"permutations":0,
         "totals":{"median":0,"mode":0,"runningHands":0,"runningPoints":0,"runningMax":0},
         "facenegation":{"median":0,"mode":0,"runningHands":0,"runningPoints":0,"runningMax":0},
         "diamondtotal":{"median":0,"mode":0,"runningHands":0,"runningPoints":0,"runningMax":0}
      }
      pointRange = range(0,(10*totalCards)+1)
      for index in pointRange:
         results["totals"][index] = 0
         results["facenegation"][index] = 0
         results["diamondtotal"][index] = 0
         
      hand = Hand()
      self.checkCards(results,hand,totalCards)
      
      permutations = results["permutations"]
      middle = permutations / 2
      permfloat = 1.0 * permutations
      for index in pointRange:
         totals = self.compute[[PointSet]](results["totals"],index,middle)
         faceneg = self.compute[[PointSet]](results["facenegation"],index,middle)
         diamonds = self.compute[[PointSet]](results["diamondtotal"],index,middle)
         tpercent = (totals * 100.0) / permutations
         fpercent = (faceneg * 100.0) / permutations
         dpercent = (diamonds * 100.0) / permutations
         print "%d\t%d\t%d\t%d\t%f%%\t%f%%\t%f%%" % (index,totals,faceneg,diamonds,tpercent,fpercent,dpercent)
      print "%s\t%d\t%d\t%d" % ("Mode",results["totals"]["mode"],results["facenegation"]["mode"],results["diamondtotal"]["mode"])
      print "%s\t%d\t%d\t%d" % ("Median",results["totals"]["median"],results["facenegation"]["median"],results["diamondtotal"]["median"])
      print "%s\t%f\t%f\t%f" % ("Mean",results["totals"]["runningPoints"]/permfloat,results["facenegation"]["runningPoints"]/permfloat,results["diamondtotal"]["runningPoints"]/permfloat)
      print "Permutations\t%d" % (permutations)
      print
      
   def compute[[PointSet]](self,hash,index,middle):
      hands = hash[index]
      hash["runningHands"] += hands
      hash["runningPoints"] += hands * index
      if (hash["runningMax"] < hands):
         hash["runningMax"] = hands
         hash["mode"] = index
      if (hash["median"] == 0 and hash["runningHands"] > middle):
         hash["median"] = index
      return hands
      
   def analyzeHand(self,results,hand):
      (points, facepoints, diamondpoints) = hand.calculatePoints()
      results["totals"][points] += 1
      results["facenegation"][facepoints] += 1
      results["diamondtotal"][diamondpoints] += 1
      results["permutations"] += 1
   
deck = Deck()
deck.summarizePermutations(1)
deck.summarizePermutations(2)
deck.summarizePermutations(3)
deck.summarizePermutations(4)
deck.summarizePermutations(5)