EDIT : [WORK IN PROGRESS]
So, I first posted this thread in the Other Metagames forum because I thought it could help some Anything Goes players, but it wasn't the right place to post it (as Eevee General told me). This thread can also provide figures when discussing about Moody in general. I'll try to make (and add to this thread) a small python code to calculate the probabilities quickly so that this thread could find its place here.
i ∈ ⟦-6 ; +6⟧
n ∈ ℕ
Moody: At the end of each turn, Moody raises one of the stats of the Pokemon with this Ability by two stages (at random), then decreases another stat by one stage (at random). It can select Accuracy and Evasion. Moody will not attempt to lower a stat that is already at -6 or attempt to increase a stat that is already at +6. Moody will not select the same stat to lower as it raised.
(Taken from Bulbapedia)
So we have a total of 7 stats to deal with (Attack, Defense, Sp. Atk., Sp. Def., Speed, Accuracy and Evasion) and it’s totally random.
========================================================================================================
I believe this has already be done before, but I cannot find the old thread.
This approach doesn't give the exact theoretical probabilities but something very close to them. It's reliable enough so that people can discuss about it. I'll probably add a table later.
Maybe the code can be improved a little bit. Anyway, here are the results for turn 1 to turn 100 with 10,000 iterations for each turn.
At the end all stats are at +6 except one stat at +5. The system converge toward a limit. This can easily be proven analytically. (Correct me if I'm wrong because I do not know the English mathematical vocabulary).
========================================================================================================
/
So, I first posted this thread in the Other Metagames forum because I thought it could help some Anything Goes players, but it wasn't the right place to post it (as Eevee General told me). This thread can also provide figures when discussing about Moody in general. I'll try to make (and add to this thread) a small python code to calculate the probabilities quickly so that this thread could find its place here.
Calculating the probability of a specific stat of a Pokemon with the Ability Moody to be at stage "i" at "turn n" assuming that we are at "turn 0" (that is to say : the beginning of "turn 1").
Supposing that the Pokemon never gets Knocked Out nor have its stat raised or lowered by anything else than his Ability (Moody).
i ∈ ⟦-6 ; +6⟧
n ∈ ℕ
Moody: At the end of each turn, Moody raises one of the stats of the Pokemon with this Ability by two stages (at random), then decreases another stat by one stage (at random). It can select Accuracy and Evasion. Moody will not attempt to lower a stat that is already at -6 or attempt to increase a stat that is already at +6. Moody will not select the same stat to lower as it raised.
(Taken from Bulbapedia)
So we have a total of 7 stats to deal with (Attack, Defense, Sp. Atk., Sp. Def., Speed, Accuracy and Evasion) and it’s totally random.
========================================================================================================
Statistical approach :
========================================================================================================I believe this has already be done before, but I cannot find the old thread.
This approach doesn't give the exact theoretical probabilities but something very close to them. It's reliable enough so that people can discuss about it. I'll probably add a table later.
from random import random
from matplotlib.pyplot import plot, grid, show
def Moody(Stats_Boosts): # Stats_Boosts=[Attack,Defense,SpAtk,SpDef,Speed,Accuracy,Evasion]
---StatPlus=[]
---for i in range(0,len(Stats_Boosts)) :
------if Stats_Boosts < 6 :
---------StatPlus.append(i)
---if StatPlus != [] :
------r = int(len(StatPlus)*random())
------if Stats_Boosts[StatPlus[r]] == 5 :
---------Stats_Boosts[StatPlus[r]] = 6
------else :
---------Stats_Boosts[StatPlus[r]] += 2
---StatMinus=[]
---for i in range(0,len(Stats_Boosts)) :
------if Stats_Boosts > -6 and i != StatPlus[r] :
---------StatMinus.append(i)
---if StatMinus != [] :
------q = int(len(StatMinus)*random())
------Stats_Boosts[StatMinus[q]] -= 1
---return Stats_Boosts
def Stats_Boosts_After_n_Turns_of_Moody(n):
---Stats_Boosts = [0,0,0,0,0,0,0]
---for i in range (1,n+1):
------Stats_Boosts = Moody(Stats_Boosts)
---return Stats_Boosts
def Statistics(n,i): # turn n, i itérations
---freq_minus_6 = 0 ; freq_minus_5 = 0 ; freq_minus_4 = 0 ; freq_minus_3 = 0 ; freq_minus_2 = 0 ; freq_minus_1 = 0 ; freq_0 = 0 ; freq_plus_1 = 0 ; freq_plus_2 = 0 ; freq_plus_3 = 0 ; freq_plus_4 = 0 ; freq_plus_5 = 0 ; freq_plus_6 = 0
---for _ in range (1,i+1):
------L = Stats_Boosts_After_n_Turns_of_Moody(n)
------if L[0] == -6 :
---------freq_minus_6 += 1
------if L[0] == -5 :
---------freq_minus_5 += 1
------if L[0] == -4 :
---------freq_minus_4 += 1
------if L[0] == -3 :
---------freq_minus_3 += 1
------if L[0] == -2 :
---------freq_minus_2 += 1
------if L[0] == -1 :
---------freq_minus_1 += 1
------if L[0] == 0 :
---------freq_0 += 1
------if L[0] == 1 :
---------freq_plus_1 += 1
------if L[0] == 2 :
---------freq_plus_2 += 1
------if L[0] == 3 :
---------freq_plus_3 += 1
------if L[0] == 4 :
---------freq_plus_4 += 1
------if L[0] == 5 :
---------freq_plus_5 += 1
------if L[0] == 6 :
---------freq_plus_6 += 1
---return [freq_minus_6/i, freq_minus_5/i, freq_minus_4/i, freq_minus_3/i, freq_minus_2/i, freq_minus_1/i, freq_0/i, freq_plus_1/i, freq_plus_2/i, freq_plus_3/i, freq_plus_4/i, freq_plus_5/i, freq_plus_6/i]
def Representer_Courbe(n,i): # n turns, i itérations
---Y_minus_6=[] ; Y_minus_5=[] ; Y_minus_4=[] ; Y_minus_3=[] ; Y_minus_2=[] ; Y_minus_1=[] ; Y_0=[] ; Y_plus_1=[] ; Y_plus_2=[] ; Y_plus_3=[] ; Y_plus_4=[] ; Y_plus_5=[] ; Y_plus_6=[] ; X=[]
---for j in range (1,n+1):
------X.append(j)
------L = Statistics(j,i)
------Y_minus_6.append(L[0])
------Y_minus_5.append(L[1])
------Y_minus_4.append(L[2])
------Y_minus_3.append(L[3])
------Y_minus_2.append(L[4])
------Y_minus_1.append(L[5])
------Y_0.append(L[6])
------Y_plus_1.append(L[7])
------Y_plus_2.append(L[8])
------Y_plus_3.append(L[9])
------Y_plus_4.append(L[10])
------Y_plus_5.append(L[11])
------Y_plus_6.append(L[12])
---plot(X,Y_minus_6,color=[0,0,1])
---plot(X,Y_minus_5,color=[1/12,1/12,5/6])
---plot(X,Y_minus_4,color=[2/12,2/12,4/6])
---plot(X,Y_minus_3,color=[3/12,3/12,3/6])
---plot(X,Y_minus_2,color=[4/12,4/12,2/6])
---plot(X,Y_minus_1,color=[5/12,5/12,1/6])
---plot(X,Y_0,color=[1,1,0])
---plot(X,Y_plus_1,color=[1,5/6,0])
---plot(X,Y_plus_2,color=[1,4/6,0])
---plot(X,Y_plus_3,color=[1,3/6,0])
---plot(X,Y_plus_4,color=[1,2/6,0])
---plot(X,Y_plus_5,color=[1,1/6,0])
---plot(X,Y_plus_6,color=[1,0,0])
---grid(True) ; show()
from matplotlib.pyplot import plot, grid, show
def Moody(Stats_Boosts): # Stats_Boosts=[Attack,Defense,SpAtk,SpDef,Speed,Accuracy,Evasion]
---StatPlus=[]
---for i in range(0,len(Stats_Boosts)) :
------if Stats_Boosts < 6 :
---------StatPlus.append(i)
---if StatPlus != [] :
------r = int(len(StatPlus)*random())
------if Stats_Boosts[StatPlus[r]] == 5 :
---------Stats_Boosts[StatPlus[r]] = 6
------else :
---------Stats_Boosts[StatPlus[r]] += 2
---StatMinus=[]
---for i in range(0,len(Stats_Boosts)) :
------if Stats_Boosts > -6 and i != StatPlus[r] :
---------StatMinus.append(i)
---if StatMinus != [] :
------q = int(len(StatMinus)*random())
------Stats_Boosts[StatMinus[q]] -= 1
---return Stats_Boosts
def Stats_Boosts_After_n_Turns_of_Moody(n):
---Stats_Boosts = [0,0,0,0,0,0,0]
---for i in range (1,n+1):
------Stats_Boosts = Moody(Stats_Boosts)
---return Stats_Boosts
def Statistics(n,i): # turn n, i itérations
---freq_minus_6 = 0 ; freq_minus_5 = 0 ; freq_minus_4 = 0 ; freq_minus_3 = 0 ; freq_minus_2 = 0 ; freq_minus_1 = 0 ; freq_0 = 0 ; freq_plus_1 = 0 ; freq_plus_2 = 0 ; freq_plus_3 = 0 ; freq_plus_4 = 0 ; freq_plus_5 = 0 ; freq_plus_6 = 0
---for _ in range (1,i+1):
------L = Stats_Boosts_After_n_Turns_of_Moody(n)
------if L[0] == -6 :
---------freq_minus_6 += 1
------if L[0] == -5 :
---------freq_minus_5 += 1
------if L[0] == -4 :
---------freq_minus_4 += 1
------if L[0] == -3 :
---------freq_minus_3 += 1
------if L[0] == -2 :
---------freq_minus_2 += 1
------if L[0] == -1 :
---------freq_minus_1 += 1
------if L[0] == 0 :
---------freq_0 += 1
------if L[0] == 1 :
---------freq_plus_1 += 1
------if L[0] == 2 :
---------freq_plus_2 += 1
------if L[0] == 3 :
---------freq_plus_3 += 1
------if L[0] == 4 :
---------freq_plus_4 += 1
------if L[0] == 5 :
---------freq_plus_5 += 1
------if L[0] == 6 :
---------freq_plus_6 += 1
---return [freq_minus_6/i, freq_minus_5/i, freq_minus_4/i, freq_minus_3/i, freq_minus_2/i, freq_minus_1/i, freq_0/i, freq_plus_1/i, freq_plus_2/i, freq_plus_3/i, freq_plus_4/i, freq_plus_5/i, freq_plus_6/i]
def Representer_Courbe(n,i): # n turns, i itérations
---Y_minus_6=[] ; Y_minus_5=[] ; Y_minus_4=[] ; Y_minus_3=[] ; Y_minus_2=[] ; Y_minus_1=[] ; Y_0=[] ; Y_plus_1=[] ; Y_plus_2=[] ; Y_plus_3=[] ; Y_plus_4=[] ; Y_plus_5=[] ; Y_plus_6=[] ; X=[]
---for j in range (1,n+1):
------X.append(j)
------L = Statistics(j,i)
------Y_minus_6.append(L[0])
------Y_minus_5.append(L[1])
------Y_minus_4.append(L[2])
------Y_minus_3.append(L[3])
------Y_minus_2.append(L[4])
------Y_minus_1.append(L[5])
------Y_0.append(L[6])
------Y_plus_1.append(L[7])
------Y_plus_2.append(L[8])
------Y_plus_3.append(L[9])
------Y_plus_4.append(L[10])
------Y_plus_5.append(L[11])
------Y_plus_6.append(L[12])
---plot(X,Y_minus_6,color=[0,0,1])
---plot(X,Y_minus_5,color=[1/12,1/12,5/6])
---plot(X,Y_minus_4,color=[2/12,2/12,4/6])
---plot(X,Y_minus_3,color=[3/12,3/12,3/6])
---plot(X,Y_minus_2,color=[4/12,4/12,2/6])
---plot(X,Y_minus_1,color=[5/12,5/12,1/6])
---plot(X,Y_0,color=[1,1,0])
---plot(X,Y_plus_1,color=[1,5/6,0])
---plot(X,Y_plus_2,color=[1,4/6,0])
---plot(X,Y_plus_3,color=[1,3/6,0])
---plot(X,Y_plus_4,color=[1,2/6,0])
---plot(X,Y_plus_5,color=[1,1/6,0])
---plot(X,Y_plus_6,color=[1,0,0])
---grid(True) ; show()
At the end all stats are at +6 except one stat at +5. The system converge toward a limit. This can easily be proven analytically. (Correct me if I'm wrong because I do not know the English mathematical vocabulary).
Graph :

========================================================================================================
Analytical approach :
========================================================================================================/
Last edited: