diff --git a/DARE.py b/DARE.py
index 90ad2d6075279791de4852795b7e1d2b7f175e76..1bc6e079d1aeeb6224e92202e1f7f0c75c6c1e71 100755
--- a/DARE.py
+++ b/DARE.py
@@ -5,70 +5,89 @@ File that implements DARE dice-system for my tabletop game
 import dice
 import codecs
 import copy
+import random
 
 #####################---INIT AND UTILS---#########################
 abc = "abcdefghijklmnopqrstuvwxyz"
 
+
 ##Inherit Dice, adds name support and latency (count)
 class SpecialDice(dice.Dice):
     def __init__(self, n, name):
         """init a special dice"""
         super().__init__(n)
-        self.name=str(name)
-        self.count=0 #number of time this dice was rerolled
+        self.name = str(name)
+        self.count = 0  # number of time this dice was rerolled
         return None
-    
+
     def __str__(self):
         if self.value != None:
-            return self.name+str(self.n)+"["+str(self.value)+"]"
+            return self.name + str(self.n) + "[" + str(self.value) + "]"
         else:
-            return self.name+str(self.n)
+            return self.name + str(self.n)
 
     def __repr__(self):
-        return "SDice object : "+str(self)
+        return "SDice object : " + str(self)
 
     def __lt__(self, otherdice):
         return self.n <= otherdice.n
 
+    def roll(self):
+        """roll the dice"""
+        self.value = random.randrange(self.n) + 1
+        self.count += 1
+        return self.value
+
     def softReset(self):
-        self.reset();
+        self.reset()
         return None
 
     # I guess this is what u get when u don't do proper code dev lol
     # But hey, overriding is the future, right Java ?
     def HardReset(self):
-        self.reset();
-        self.count = 0;
+        self.reset()
+        self.count = 0
         return None
 
-class LatencyQueue():
+
+class LatencyQueue:
     def __init__(self):
         """init the Latency Queue"""
         self.queue = []
-    
+
     def add(self, elt):
         """put elt in the indexQueue"""
         self.queue.append(elt)
-    
+
     def move(self):
-        ret = "TODO"
+        ret = []
+        to_rem = []
+        for e in self.queue:
+            if e.count == 0:
+                ret.append(e)
+                to_rem.append(e)
+            else:
+                e.count -= 1
+        for e in to_rem:
+            self.queue.remove(e)
         return ret
 
     def __str__(self):
         return "TODO"
 
     def __repr__(self):
-        return "Latency Queue Object :"+str(self)
+        return "Latency Queue Object :" + str(self)
+
 
-#Prints the main art
+# Prints the main art
 def art():
     f = codecs.open("art", "r", encoding="utf-8")
     art = f.read()
     f.close()
-    print("\033[2J\033[0;0H",end="")
+    print("\033[2J\033[0;0H", end="")
     print(art)
     print(
-"""
+        """
 \033[38;5;148m\033[11;10H ██████   █████  ██████  ███████ 
 \033[38;5;149m\033[12;10H ██   ██ ██   ██ ██   ██ ██      
 \033[38;5;150m\033[13;10H ██   ██ ███████ ██████  █████   
@@ -78,640 +97,742 @@ def art():
     )
     return None
 
-#Prints a line
+
+# Prints a line
 def line():
-    print("\033[38;5;240m"+50*"-"+"\033[0m")
+    print("\033[38;5;240m" + 50 * "-" + "\033[0m")
     return None
 
-ask_history=[]
 
-#Asks the player which actions does he wants to do
+ask_history = []
+
+
+# Asks the player which actions does he wants to do
 def ask(symbol):
-    out = input("\033[38;5;217m"+symbol+">\033[0m")
+    out = input("\033[38;5;217m" + symbol + ">\033[0m")
     return out
 
-if __name__=="__main__":
 
-    from types import SimpleNamespace
+from types import SimpleNamespace
+
+##INITVAR
+COMMAND_LIST = {}
+S = SimpleNamespace()
+S.PHIdicepool = []
+S.PSIdicepool = []
+S.PDiceTray = dice.DiceTray()  # PHI DiceTray
+S.pDiceTray = dice.DiceTray()  # pSI DiceTray
+S.Latency = LatencyQueue()
+S.thro = []
+S.name = ""
+S.inroll = False
+
+# Namespace where S object can be at any moments reverted to its old self
+Undoable = SimpleNamespace()
+Undoable.S = S
+Undoable.OldS = S
+Undoable.RedoS = S
+
+# DEPRECATED
+##S.PHIqueue = []#SpecialDice(2,"Ψ"),SpecialDice(6,"Ψ")]
+##S.PSIqueue = []#SpecialDice(2,"Ψ"),SpecialDice(6,"Ψ")]
+#
 
-    ##INITVAR
-    COMMAND_LIST={} 
-    S = SimpleNamespace()
-    S.PHIdicepool = []
-    S.PSIdicepool = []
-    S.PDiceTray = dice.DiceTray() #PHI DiceTray
-    S.pDiceTray = dice.DiceTray() #pSI DiceTray
-    S.Latency = LatencyQueue() 
-    S.thro = [] 
-    S.name = ""
-    S.inroll = False
+# S.PDiceTray.add(SpecialDice(2,"Ψ"))
 
-    #Namespace where S object can be at any moments reverted to its old self 
-    Undoable = SimpleNamespace()
-    Undoable.S = S
-    Undoable.OldS = S
-    Undoable.RedoS = S
+##INIT CLI
+art()
 
-#DEPRECATED
-    ##S.PHIqueue = []#SpecialDice(2,"Ψ"),SpecialDice(6,"Ψ")] 
-    ##S.PSIqueue = []#SpecialDice(2,"Ψ"),SpecialDice(6,"Ψ")] 
-#
 
-        #S.PDiceTray.add(SpecialDice(2,"Ψ"))
-
-    ##INIT CLI
-    art()
-
-#Badly prints mlist i think
-    def stupidPrint(mlist):
-        out = ""
-        for e in mlist:
-            out += str(e)+" "
-        return out
-
-#Print the actual dice tray. 
-    def printDiceTray():
-    #This function crash if more than 26 dice are thrown
-    #This won't ever happen, right ?
-        i = 0
-        sumP = 0
-        sumPMax = 0
-        sump = 0
-        sumpMax = 0
-        for e in S.PDiceTray:
-            print("\t\033[38;5;217m"+abc[i]+"\033[38;5;10m"+e.name+str(e.n)+"["+"\033[0m"+str(e.value)+"\033[38;5;10m]" ,end="")
-            i+=1
-            sumP += e.value
-            sumPMax += e.n
-        print("\n",end="")
-        for e in S.pDiceTray:
-            print("\t\033[38;5;217m"+abc[i]+"\033[38;5;159m"+e.name+str(e.n)+"["+"\033[0m"+str(e.value)+"\033[38;5;159m]" ,end="")
-            i+=1
-            sump += e.value
-            sumpMax += e.n
-        print("\033[0m")
-        print("Sum of\033[38;5;10m PHI\033[0m dice is :\033[38;5;217m "+str(sumP)+"\033[0m.")
-        print("Sum of\033[38;5;159m PSI\033[0m dice is :\033[38;5;217m "+str(sump)+"\033[0m.")
-        #Todo : number of same dice
-
-        print("\n")
-    def printallstat(S, ShowDiceTray=False):
-        print("\033[38;5;214m PHI \033[38;5;10m [ "+stupidPrint(S.PHIdicepool)+"]\033[0m "
-        ,end="")
-        print("\033[38;5;214m PSI \033[38;5;159m [ "+stupidPrint(S.PSIdicepool)+"]\033[0m "
-        ,end="")
-
-        if ShowDiceTray:
-            print("\n\033[38;5;214m ROLL ")
-            printDiceTray()
-
-        if ShowDiceTray and S.thro:
-            print("\033[38;5;242m DEL  [ "+stupidPrint(S.thro)+"]\033[0m")
+# Badly prints mlist i think
+def stupidPrint(mlist):
+    out = ""
+    for e in mlist:
+        out += str(e) + " "
+    return out
+
+
+# Print the actual dice tray.
+def printDiceTray():
+    # This function crash if more than 26 dice are thrown
+    # This won't ever happen, right ?
+    i = 0
+    sumP = 0
+    sumPMax = 0
+    sump = 0
+    sumpMax = 0
+    for e in S.PDiceTray:
+        print(
+            "\t\033[38;5;217m"
+            + abc[i]
+            + "\033[38;5;10m"
+            + e.name
+            + str(e.n)
+            + "["
+            + "\033[0m"
+            + str(e.value)
+            + "\033[38;5;10m]"
+            + str(e.count),
+            end="",
+        )
+        i += 1
+        sumP += e.value
+        sumPMax += e.n
+    print("\n", end="")
+    for e in S.pDiceTray:
+        print(
+            "\t\033[38;5;217m"
+            + abc[i]
+            + "\033[38;5;159m"
+            + e.name
+            + str(e.n)
+            + "["
+            + "\033[0m"
+            + str(e.value)
+            + "\033[38;5;159m]"
+            + str(e.count),
+            end="",
+        )
+        i += 1
+        sump += e.value
+        sumpMax += e.n
+    print("\033[0m")
+    print(
+        "Sum of\033[38;5;10m PHI\033[0m dice is :\033[38;5;217m "
+        + str(sumP)
+        + "\033[0m."
+    )
+    print(
+        "Sum of\033[38;5;159m PSI\033[0m dice is :\033[38;5;217m "
+        + str(sump)
+        + "\033[0m."
+    )
+    # Todo : number of same dice
+
+    print("\n")
+
+
+def printallstat(S, ShowDiceTray=False):
+    print(
+        "\033[38;5;214m PHI \033[38;5;10m [ "
+        + stupidPrint(S.PHIdicepool)
+        + "]\033[0m ",
+        end="",
+    )
+    print(
+        "\033[38;5;214m PSI \033[38;5;159m [ "
+        + stupidPrint(S.PSIdicepool)
+        + "]\033[0m ",
+        end="",
+    )
+
+    if ShowDiceTray:
+        print("\n\033[38;5;214m ROLL ")
+        printDiceTray()
+
+    if ShowDiceTray and S.thro:
+        print("\033[38;5;242m DEL  [ " + stupidPrint(S.thro) + "]\033[0m")
+    print("")
+
+    if S.Latency.queue:
+        print("\033[38;5;214m LAT \033[38;5;242m [ ", end="")
+        for dice in S.Latency.queue:
+            print(dice.name + str(dice.n) + "(" + str(dice.count) + ") ", end="")
+        print("]\033[0m")
 
 
 #
 ##HELP
-    def helpDARE(args,S):
-        """
-USAGE : help [command name]
-Show command list. If invoked with command name as 
-an argument, then show command's usage and 
-descritpion.
-        """
-        if len(args) == 0:
-            print("Available commands are :")
-            for e in COMMAND_LIST:
-                print(" - \033[1m"+e+"\033[0m")
-            print(
-"""
+def helpDARE(args, S):
+    """
+    USAGE : help [command name]
+    Show command list. If invoked with command name as
+    an argument, then show command's usage and
+    descritpion.
+    """
+    if len(args) == 0:
+        print("Available commands are :")
+        for e in COMMAND_LIST:
+            print(" - \033[1m" + e + "\033[0m")
+        print(
+            """
 Type \033[1m help <command> \033[0m to get help
 on a specific command"""
-                )
+        )
+    else:
+        if args[0] in COMMAND_LIST:
+            print(COMMAND_LIST[args[0]].__doc__[1:])
         else:
-            if args[0] in COMMAND_LIST:
-                print(COMMAND_LIST[args[0]].__doc__[1:])
-            else:
-                print(
-"""
-No command found '"""+str(args[0])+"""'"""
-                )
-        return None
+            print(
+                """
+No command found '"""
+                + str(args[0])
+                + """'"""
+            )
+    return None
+
 
 #
-##MOVE    
-    def move(args,S):
-        """
+##MOVE
+def move(args, S):
+    """
         USAGE : move
-GM-purposed command.
-move the LAT queue, update pools."""
-        availDice = S.Latency.move()
-        #Update pools
-        for e in availDice:
-            if e.name == "Ψ":
-                S.PSIdicepool.append(e)
-            else:
-                S.PHIdicepool.append(e)
-        S.PSIdicepool.sort()
-        S.PHIdicepool.sort()
-        return None
+    GM-purposed command.
+    move the LAT queue, update pools."""
+    availDice = S.Latency.move()
+    # Update pools
+    for e in availDice:
+        if e.name == "Ψ":
+            S.PSIdicepool.append(e)
+        else:
+            S.PHIdicepool.append(e)
+    S.PSIdicepool.sort()
+    S.PHIdicepool.sort()
+    return None
 
-    def Nothing(args,S):
-        return None
+
+def Nothing(args, S):
+    return None
 
 
 #
 ##REDO
-    def redo(args,S):
-        """
-USAGE : redo
-GM-purposed command.
-Restore (once) the current state before an undo !
-state."""
-        if Undoable.S == Undoable.RedoS:
-            print(
-"""
+def redo(args, S):
+    """
+    USAGE : redo
+    GM-purposed command.
+    Restore (once) the current state before an undo !
+    state."""
+    if Undoable.S == Undoable.RedoS:
+        print(
+            """
 Nothing to revert !"""
-            )
-            return None
-        else:
-            Undoable.OldS = deepcopy(Undoable.S)
-            Undoable.S = Undoable.RedoS
-            return None
+        )
+        return None
+    else:
+        Undoable.OldS = deepcopy(Undoable.S)
+        Undoable.S = Undoable.RedoS
+        return None
+
 
 #
 ##UNDO
-    def undo(args,S):
-        """
-USAGE : undo
-GM-purposed command.
-Restore (once) the current state to the previous
-state."""
-        if Undoable.S == Undoable.OldS:
-            print(
-"""
+def undo(args, S):
+    """
+    USAGE : undo
+    GM-purposed command.
+    Restore (once) the current state to the previous
+    state."""
+    if Undoable.S == Undoable.OldS:
+        print(
+            """
 Nothing to revert !"""
-            )
-            return None
-        else:
-            Undoable.RedoS = deepcopy(Undoable.S)
-            Undoable.S = Undoable.OldS
-            return None
+        )
+        return None
+    else:
+        Undoable.RedoS = deepcopy(Undoable.S)
+        Undoable.S = Undoable.OldS
+        return None
+
 
 #
 ##EXITDARE
-    def exitDARE(args,S):
-        """
-USAGE : exit
-Closes this programm while being polite :)"""
-        print("Goodbye !")
-        exit()
+def exitDARE(args, S):
+    """
+    USAGE : exit
+    Closes this programm while being polite :)"""
+    print("Goodbye !")
+    exit()
+
+
+def show(args, S):
+    """
+    USAGE : show
+    all info about the current state."""
+    print(S.name + ": ")
+    printallstat(S, S.inroll)
+    return None
+
 
-    def show(args,S):
-        """
-USAGE : show
-all info about the current state."""
-        print(S.name+": ")
-        printallstat(S, S.inroll)
-        return None
 #
 ##ADD
-    def select(args,S,fromQueue=False):
-        """
-        Selects dice, and removes them from dicepools, return selected dice.
-        Apply this to S.Queue if fromQueue is true
-        """
-        #check for valid input first
-        if len(args) == 0:
-                print("At least one dice is expected.")
-                return None
- 
-        for d in args:
-            if d[0] != "p" and d[0] != "P":
-                print("Unknown dice '"+str(d)+"' !")
+def select(args, S, fromQueue=False):
+    """
+    Selects dice, and removes them from dicepools, return selected dice.
+    Apply this to S.Queue if fromQueue is true
+    """
+    # check for valid input first
+    if len(args) == 0:
+        print("At least one dice is expected.")
+        return None
+
+    for d in args:
+        if d[0] != "p" and d[0] != "P":
+            print("Unknown dice '" + str(d) + "' !")
+            return None
+        try:
+            int(d[1:])
+        except ValueError:
+            print("Unknown dice '" + str(d) + "' !")
+            return None
+
+    # our input are valid !!!
+    PselectedDice = []
+    pselectedDice = []
+
+    if not fromQueue:
+        first = S.PSIdicepool
+        second = S.PHIdicepool
+    else:
+        first = S.Latency.queue
+        second = S.Latency.queue
+    for d in args:  # rem from pools
+        if d[0] == "p":
+            found = False
+            for e in S.PSIdicepool:
+                if e.n == int(d[1:]):
+                    S.pDiceTray.add(e)
+                    pselectedDice.append(e)
+                    first.remove(e)
+                    found = True
+                    break
+
+            if not found:  # valid dices, but not in pool
+                print("Not enough Ψ" + str(d[1:]) + " !")
+                first = first + pselectedDice
+                second = second + PselectedDice
                 return None
-            try:
-                int(d[1:])
-            except ValueError:
-                print("Unknown dice '"+str(d)+"' !")
+
+        elif d[0] == "P":
+            found = False
+            for e in S.PHIdicepool:
+                if e.n == int(d[1:]):
+                    S.PDiceTray.add(e)
+                    PselectedDice.append(e)
+                    second.remove(e)
+                    found = True
+                    break
+
+            if not found:
+                print("Not enough Φ" + str(d[1:]) + " !")
+                second = second + PselectedDice
+                first = first + pselectedDice
                 return None
-        
-        # our input are valid !!!
-        PselectedDice=[] 
-        pselectedDice = [] 
-
-        if not fromQueue:
-            first = S.PSIdicepool
-            second = S.PHIdicepool
-        else:
-            first = S.Latency.queue
-            second = S.Latency.queue
-        for d in args: #rem from pools 
-            if d[0] == "p":
-                found=False
-                for e in S.PSIdicepool:
-                    if e.n == int(d[1:]):
-                       S.pDiceTray.add(e)
-                       pselectedDice.append(e)
-                       first.remove(e)
-                       found = True
-                       break
-            
-                if not found: #valid dices, but not in pool
-                    print("Not enough Ψ"+str(d[1:])+" !")
-                    first = first + pselectedDice
-                    second = second + PselectedDice
-                    return None
-       
-            elif d[0] == "P":
-                found=False
-                for e in S.PHIdicepool:
-                    if e.n == int(d[1:]):
-                        S.PDiceTray.add(e)
-                        PselectedDice.append(e)
-                        second.remove(e)
-                        found = True
-                        break
-
-                if not found:
-                    print("Not enough Φ"+str(d[1:])+" !")
-                    second = second + PselectedDice
-                    first = first + pselectedDice
-                    return None
-       
-        return pselectedDice+PselectedDice
+
+    return pselectedDice + PselectedDice
+
 
 #
 ##ADD
-    def add(args,S):
-        """add dice into tray"""
-        #check for valid input first
-        if len(args) == 0:
-                print("At least one dice is expected.")
-                return None
- 
-        for d in args:
-            if d[0] != "p" and d[0] != "P":
-                print("Unknown dice '"+str(d)+"' !")
+def add(args, S):
+    """add dice into tray"""
+    # check for valid input first
+    if len(args) == 0:
+        print("At least one dice is expected.")
+        return None
+
+    for d in args:
+        if d[0] != "p" and d[0] != "P":
+            print("Unknown dice '" + str(d) + "' !")
+            return None
+        try:
+            int(d[1:])
+        except ValueError:
+            print("Unknown dice '" + str(d) + "' !")
+            return None
+
+    # our input are valid !!!
+    p = []
+    P = []
+    paddedDice = []
+    PaddedDice = []
+    for d in args:
+        if d[0] == "p":
+            found = False
+            for e in S.PSIdicepool:
+                if e.n == int(d[1:]):
+                    # S.pDiceTray.add(e)
+                    paddedDice.append(e)
+                    S.PSIdicepool.remove(e)
+                    found = True
+                    break
+
+            if not found:  # valid dices, but not in pool
+                print("Not enough Ψ" + str(d[1:]) + " !")
+                S.PSIdicepool = S.PSIdicepool + paddedDice
+                S.PHIdicepool = S.PHIdicepool + PaddedDice
                 return None
-            try:
-                int(d[1:])
-            except ValueError:
-                print("Unknown dice '"+str(d)+"' !")
+
+        elif d[0] == "P":
+            found = False
+            for e in S.PHIdicepool:
+                if e.n == int(d[1:]):
+                    # S.PDiceTray.add(e)
+                    PaddedDice.append(e)
+                    S.PHIdicepool.remove(e)
+                    found = True
+                    break
+
+            if not found:
+                print("Not enough Φ" + str(d[1:]) + " !")
+                S.PSIdicepool = S.PSIdicepool + paddedDice
+                S.PHIdicepool = S.PHIdicepool + PaddedDice
                 return None
-        
-        # our input are valid !!!
-        p = []
-        P = [] 
-        addedDice = [] 
-        for d in args:
-            if d[0] == "p":
-                found=False
-                for e in S.PSIdicepool:
-                    if e.n == int(d[1:]):
-                        S.pDiceTray.add(e)
-                        addedDice.append(e)
-                        S.PSIdicepool.remove(e)
-                        found = True
-                        break
-                
-                if not found: #valid dices, but not in pool
-                    print("Not enough Ψ"+str(d[1:])+" !")
-                    S.PSIdicepool = S.PSIdicepool + S.pDiceTray.tray
-                    S.PHIdicepool = S.PHIdicepool + S.PDiceTray.tray
-                    S.pDiceTray.tray = []
-                    S.PDiceTray.tray = [] 
-                    return None
-           
-            elif d[0] == "P":
-                found=False
-                for e in S.PHIdicepool:
-                    if e.n == int(d[1:]):
-                        S.PDiceTray.add(e)
-                        addedDice.append(e)
-                        S.PHIdicepool.remove(e)
-                        found = True
-                        break
-
-                if not found:
-                    print("Not enough Φ"+str(d[1:])+" !")
-                    S.PSIdicepool = S.PSIdicepool + S.pDiceTray.tray
-                    S.PHIdicepool = S.PHIdicepool + S.PDiceTray.tray
-                    S.pDiceTray.tray = []
-                    S.PDiceTray.tray = [] 
-                    return None
-        return addedDice
+
+    for dice in PaddedDice:
+        S.PDiceTray.add(dice)
+    for dice in paddedDice:
+        S.pDiceTray.add(dice)
+
+    return paddedDice + PaddedDice
+
 
 #
 ##DEEPCOPY
-    def deepcopy(S):
-        SCopy = copy.deepcopy(S)
-        SCopy.PHIdicepool = copy.deepcopy(S.PHIdicepool)
-        SCopy.PSIdicepool = copy.deepcopy(S.PSIdicepool) 
-        SCopy.PDiceTray = copy.deepcopy(S.PDiceTray) 
-        SCopy.pDiceTray = copy.deepcopy(S.pDiceTray)
-        SCopy.Latency = copy.deepcopy(S.Latency)
-        SCopy.thro = copy.deepcopy(S.thro)
-        SCopy.inroll = S.inroll
-        return SCopy
+def deepcopy(S):
+    SCopy = copy.deepcopy(S)
+    SCopy.PHIdicepool = copy.deepcopy(S.PHIdicepool)
+    SCopy.PSIdicepool = copy.deepcopy(S.PSIdicepool)
+    SCopy.PDiceTray = copy.deepcopy(S.PDiceTray)
+    SCopy.pDiceTray = copy.deepcopy(S.pDiceTray)
+    SCopy.Latency = copy.deepcopy(S.Latency)
+    SCopy.thro = copy.deepcopy(S.thro)
+    SCopy.inroll = S.inroll
+    return SCopy
+
 
 #
 ##ROLL
-    def roll(args,S):
-        """
-USAGE : roll [dices]   
+def roll(args, S):
+    """
+    USAGE : roll [dices]
 
-Does a roll within the possibilities 
-of your dice pool, and show the roll 
-result (with PSI and PHI total sum)
+    Does a roll within the possibilities
+    of your dice pool, and show the roll
+    result (with PSI and PHI total sum)
 
-To select a PSI dice, use "p" as a prefix.
-To select a PHI dice, use "P" as a prefix.
-For instance :
+    To select a PSI dice, use "p" as a prefix.
+    To select a PHI dice, use "P" as a prefix.
+    For instance :
     roll p4 p4 P6
-will roll Ψ4, Ψ4 and Φ6
-
-Once in a roll, you can either \033[1m reroll \033[0m 
-up to half of the throw.
-dice, \033[1m reroll ... add \033[0m to add any 
-dice in your roll, \033[1m reroll ... throw \033[0m to 
-remove any dice of your roll, or\033[1m cont \033[0m to finish 
-your roll. Please type \033[1m help reroll \033[0m
-To better know how rerolls works in DARE.
-
-LAT, PSI and PHI queues and pool are proprely 
-updated."""
-        ##UNDO MGMT
-        Undoable.OldS = deepcopy(Undoable.S)
-        
-        add(args,S)
-        S.pDiceTray.tray.sort()
-        S.PDiceTray.tray.sort()
-        S.pDiceTray.rollall()
-        S.PDiceTray.rollall()
-        #State : in roll
-        
-        S.inroll = True
-        
-        print(str(S.name)+" does a roll !")
-        printallstat(S, S.inroll)
+    will roll Ψ4, Ψ4 and Φ6
+
+    Once in a roll, you can either \033[1m reroll \033[0m
+    up to half of the throw.
+    dice, \033[1m reroll ... add \033[0m to add any
+    dice in your roll, \033[1m reroll ... throw \033[0m to
+    remove any dice of your roll, or\033[1m cont \033[0m to finish
+    your roll. Please type \033[1m help reroll \033[0m
+    To better know how rerolls works in DARE.
+
+    LAT, PSI and PHI queues and pool are proprely
+    updated."""
+
+    ##ERR CHECKING
+    if S.inroll:
+        print(
+            "Already in a roll ! Please use\033[1m reroll\033[0m command or\033[1m cont\033[0m command."
+        )
         return None
+    ##UNDO MGMT
+    Undoable.OldS = deepcopy(Undoable.S)
+
+    res = add(args, S)
+    if not res:
+        return None
+    S.pDiceTray.tray.sort()
+    S.PDiceTray.tray.sort()
+    S.pDiceTray.rollall()
+    S.PDiceTray.rollall()
+    # State : in roll
+
+    S.inroll = True
+
+    print(str(S.name) + " does a roll !")
+    printallstat(S, S.inroll)
+    return None
+
 
 #
 ##REROLL
-    def reroll(args, S):
-        """
-USAGE : reroll [dice] [throw [dice]] [add [dice]]
-
-reroll dice.
-Additionnally, you can add any dice of your pool 
-with the add keyword, or throw any dice of your 
-current tray with the throw keyword.
-For instance, consider this roll :
-
-Ninten:
- PHI  [ Φ4 Φ4 Φ6 Φ6 ]
- PSI  [ Ψ4 Ψ4 Ψ8 ]
- ROLL
+def reroll(args, S):
+    """
+    USAGE : reroll [dice] [throw [dice]] [add [dice]]
+
+    reroll dice.
+    Additionnally, you can add any dice of your pool
+    with the add keyword, or throw any dice of your
+    current tray with the throw keyword.
+    For instance, consider this roll :
+
+    Ninten:
+    PHI  [ Φ4 Φ4 Φ6 Φ6 ]
+    PSI  [ Ψ4 Ψ4 Ψ8 ]
+    ROLL
         aΦ4[3]  bΦ6[1]
         cΨ4[3]  dΨ6[4]
-Sum of PHI dice is : 4 <= 5.
-Sum of PSI dice is : 7 > 5.
+    Sum of PHI dice is : 4 <= 5.
+    Sum of PSI dice is : 7 > 5.
+
+    One could then type :
+    reroll ac remove b add p4
+
+    This would :
+    reroll a and c dice,
+    remove the b dice
+    add a psi4 dice into the final roll
+
+    if you only want to add or throw dice,
+    you can type
+
+    reroll ... add ...
+    reroll ... remove ...
+    reroll ... remove ... add ...
+
+    The ordering of the keywords doesn't matter."""
+    # UNDO MGMT
+    Undoable.OldS = deepcopy(Undoable.S)
+    if not (S.inroll):
+        print(
+            """
+Must start a roll first ! see \033[1m help roll\033[0m for
+more info"""
+        )
+        return None
 
-One could then type :
-reroll ac remove b add p4
+    if len(args) == 0:
+        print("For usage see \033[1m help reroll\033[0m .")
+        return None
 
-This would :
-reroll a and c dice,
-remove the b dice
-add a psi4 dice into the final roll
+    doAdd = False
+    doThrow = False
 
-if you only want to add or throw dice, 
-you can type
+    # which index are dice to be added in our args list
+    addIndex = -1
+    # which index are dice to be trashed in our arglist
+    throwIndex = -1
 
-reroll ... add ...
-reroll ... remove ...
-reroll ... remove ... add ...
+    # List of dice to add
+    addList = []
+    # List of dice to trash
+    throwList = []
 
-The ordering of the keywords doesn't matter."""
-        #UNDO MGMT
-        Undoable.OldS = deepcopy(Undoable.S)
-        if not(S.inroll):
-            print("""
-Must start a roll first ! see \033[1m help roll\033[0m for
-more info"""
-            )
-            return None
-        
-        if len(args) == 0:
-            print("For usage see \033[1m help reroll\033[0m .")
+    # Remaining dice to reroll
+    rerollList = args
+
+    # error checking
+    if args.count("add") > 1:
+        print(
+            "Too much 'add' keyword. see \033[1m help reroll\033[0m to see\n correct formatting"
+        )
+        return None
+    if args.count("remove") > 1:
+        print(
+            "Too much 'remove' keyword. see \033[1m help reroll\033[0m to see\n correct formatting"
+        )
+        return None
+
+    # Populate addList accordingly and update rerollList
+    if "add" in args:
+        doAdd = True
+        addIndex = args.index("add")
+        addList = args[addIndex + 1 :]
+        rerollList = rerollList[:addIndex]
+
+    # Populate throwList accordingly and update rerollList
+    if "remove" in args:
+        doThrow = True
+        throwIndex = args.index("remove")
+        throwList = args[throwIndex + 1 :]
+        rerollList = rerollList[:throwIndex]
+
+    ##After these two if, rerollList is OK,
+    ##But it is certain that either "throw" or "add" appears in each other.
+    ##This is a hacky way to patch a stupid bug and idc doing it better : )
+    if "add" in throwList:
+        throwList = throwList[: throwList.index("add")]
+    if "remove" in addList:
+        addList = addList[: addList.index("remove")]
+
+    # Indexing dice with abc
+    index = 0
+    diceDict = {}
+    for e in S.PDiceTray.tray:
+        diceDict[abc[index]] = e
+        index += 1
+    for a in S.pDiceTray.tray:
+        diceDict[abc[index]] = a
+        index += 1
+
+    if doAdd and addList:
+        addedDice = add(addList, S)
+        if (
+            not addedDice
+        ):  # This happens when add is invoked but no dice that could be added were
             return None
 
-        doAdd = False
-        doThrow = False
-
-        #which index are dice to be added in our args list
-        addIndex = -1
-        #which index are dice to be trashed in our arglist
-        throwIndex = -1
-
-        #List of dice to add
-        addList = []
-        #List of dice to trash
-        throwList = []
-
-        #Remaining dice to reroll
-        rerollList = args
-        
-        #error checking
-        if args.count("add") > 1:
-            print("Too much 'add' keyword. see \033[1m help reroll\033[0m to see\n correct formatting")
+    # Dice to remove
+    allstrThrow = ""
+    if len(throwList) > 1:
+        for letters in throwList:
+            allstrThrow = allstrThrow + letters
+    elif throwList:
+        allstrThrow = throwList[0]
+
+    allstr = ""
+    if len(rerollList) > 1:
+        for letters in rerollList:
+            allstr = allstr + letters
+    elif rerollList:
+        allstr = rerollList[0]
+
+    for c in allstr + allstrThrow:
+        if not (c in diceDict):
+            print("no dice of index'" + c + "' !")
             return None
-        if args.count("remove") > 1:
-            print("Too much 'remove' keyword. see \033[1m help reroll\033[0m to see\n correct formatting")
+
+    # Verify that dices are not rerolled too much
+    for l in allstr:
+        if diceDict[l].count >= 3:
+            print("Cannot reroll dice " + l + "\ntoo much latency !")
             return None
-        
-        #Populate addList accordingly and update rerollList
-        if "add" in args:
-            doAdd = True
-            addIndex=args.index("add")
-            addList=args[addIndex+1:]
-            rerollList=rerollList[:addIndex]
-
-        #Populate throwList accordingly and update rerollList
-        if "remove" in args:
-            doThrow = True
-            throwIndex=args.index("throw")
-            throwList=args[throwIndex+1:]
-            rerollList=rerollList[:throwIndex]  
-        
-        ##After these two if, rerollList is OK,
-        ##But it is certain that either "throw" or "add" appears in each other.
-        ##This is a hacky way to patch a stupid bug and idc doing it better : )
-        if "add" in throwList:
-            throwList=throwList[:throwList.index("add")]
-        if "throw" in addList:
-            addList=addList[:addList.index("throw")]
-        
-        #Indexing dice with abc
-        index = 0
-        diceDict = {}
-        for e in S.PDiceTray.tray:
-            diceDict[abc[index]]=e
-            index+=1
-        for a in S.pDiceTray.tray:
-            diceDict[abc[index]]=a
-            index+=1
-        
-        if doAdd and addList:
-            addedDice = add(addList,S)
-            if not addedDice:#This shouldn't happen I think...
-                print("Argshs something awfully wrong happened qwq")
-                return None
-        
-        #Dice to remove
-        allstrThrow = ""
-        if len(throwList) > 1:
-            for letters in throwList:
-                allstrThrow = allstrThrow+letters
-        elif throwList:
-            allstrThrow = throwList[0]
-        
-        allstr=""
-        if len(rerollList) > 1:
-            for letters in rerollList:
-                allstr = allstr+letters
-        elif rerollList:
-            allstr = rerollList[0]
-
-        for c in allstr+allstrThrow:
-            if not(c in diceDict):
-                print("no dice of index'"+c+"' !")
-                return None
-       ##Now, everything should be okay !
-        if doThrow:
-            for l in allstrThrow:
-                S.thro.append(diceDict[l])
-                if diceDict[l] in S.pDiceTray:
-                    S.pDiceTray.tray.remove(diceDict[l])
-                else:
-                    S.PDiceTray.tray.remove(diceDict[l])
-        
-        if doAdd:
-            for dice in addedDice:
-                dice.roll()
-
-        for l in allstr:
-            diceDict[l].roll()
-        
-        print(S.name+" rerolls !")
-        printallstat(S, True)
-       
-        return None
+
+    ##Now, everything should be okay !
+    if doThrow:
+        for l in allstrThrow:
+            S.thro.append(diceDict[l])
+            if diceDict[l] in S.pDiceTray:
+                S.pDiceTray.tray.remove(diceDict[l])
+            else:
+                S.PDiceTray.tray.remove(diceDict[l])
+
+    if doAdd:
+        for dice in addedDice:
+            dice.roll()
+            dice.count += 1
+
+    for l in allstr:
+        diceDict[l].roll()
+
+    print(S.name + " rerolls !")
+    printallstat(S, True)
+
+    return None
+
 
 #
 ##CONT
-    def cont(args,S):
-        """
-USAGE : cont
-Skips a turn. If done during a roll,
-said roll is finished."""
-        if not args or not (args[0]  in ["žInvokedFromRR","žInvokedFromTrash"]):#UNDO MGMT
-            Undoable.OldS = deepcopy(Undoable.S)
-            
-        S.inroll = False
-        if not args or args[0] != "žInvokedFromTrash":
-            move("",S)
-        all = S.pDiceTray.tray + S.PDiceTray.tray + S.thro
-        all.sort()
-        for e in all:
-            e.Softreset()
-            S.Latency.add(e)
-
-        S.pDiceTray.tray = []
-        S.PDiceTray.tray = []
-        S.thro = []
-        if args and args[0] == "žInvokedFromRR":
-            return None
-        printallstat(S)
+def cont(args, S):
+    """
+    USAGE : cont
+    Skips a turn. If done during a roll,
+    said roll is finished."""
+    if not args or not (
+        args[0] in ["žInvokedFromRR", "žInvokedFromTrash"]
+    ):  # UNDO MGMT
+        Undoable.OldS = deepcopy(Undoable.S)
+
+    S.inroll = False
+    if not args or args[0] != "žInvokedFromTrash":
+        move("", S)
+
+    all = S.pDiceTray.tray + S.PDiceTray.tray + S.thro
+    all.sort()
+    for e in all:
+        e.softReset()
+        S.Latency.add(e)
+
+    S.pDiceTray.tray = []
+    S.PDiceTray.tray = []
+    S.thro = []
+    if args and args[0] == "žInvokedFromRR":
         return None
+    printallstat(S)
+    return None
+
 
 #
 ##TRASH
-    def trash(args,S):
-        """
-USAGE : trash [dice]
-GM-purposed command.
-Trash dice as if they were rolled"""
-        Undoable.OldS = deepcopy(Undoable.S)
-        selected = select(args,S)
-        if select == None:
-            print("No dice found !")
-            return None
-        for dice in selected:
-        ##print(SCopy)
-            S.Latency.add(dice)
+def trash(args, S):
+    """
+    USAGE : trash [dice]
+    GM-purposed command.
+    Trash dice as if they were rolled"""
+    Undoable.OldS = deepcopy(Undoable.S)
+    selected = select(args, S)
+    if select == None:
+        print("No dice found !")
         return None
-    
+    for dice in selected:
+        ##print(SCopy)
+        S.Latency.add(dice)
+    return None
 
-##COMMAND LIST##
-    COMMAND_LIST = {
-            "exit" : exitDARE,
-            "quit" : exitDARE,
-            "help" : helpDARE,
-            "show" : show,
-            "undo" : undo,
-            "redo" : redo,
-            "roll" : roll,
-            "cont" : cont,
-            "reroll" : reroll,
-            "trash": trash,
-    }
 
+##COMMAND LIST##
+COMMAND_LIST = {
+    "exit": exitDARE,
+    "q": exitDARE,
+    "quit": exitDARE,
+    "help": helpDARE,
+    "show": show,
+    "undo": undo,
+    "redo": redo,
+    "roll": roll,
+    "cont": cont,
+    "reroll": reroll,
+    "trash": trash,
+}
+if __name__ == "__main__":
     ## get init param :
     print(
-"""
-Please give your (sur)name"""
+        """
+    Please give your (sur)name"""
     )
-    S.name=ask("name?")
-    if S.name == "": S.name = "Ninten"
+    S.name = ask("name?")
+    if S.name == "":
+        S.name = "Ninten"
     print(
-"""
-Please give your PHI dice pool
-formatting is expected to be such as :
-d4,d4,d6,d4,d8 (no spaces at the start !)"""
+        """
+    Please give your PHI dice pool
+    formatting is expected to be such as :
+    \033[1m d4 d4 d6 d4 d8 
+    \033[0m(no spaces at the start !)"""
     )
     uinput = ask("Φ?")
-    if uinput=="":uinput="d4,d4,d4,d6,d6,d6"
-    argsdice = uinput.split(",")
-    S.PHIdicepool = [] 
+    if uinput == "":
+        uinput = "d4 d4 d4 d6 d6 d6"
+    argsdice = uinput.split(" ")
+    S.PHIdicepool = []
     for e in argsdice:
         dval = int(e[1:])
-        S.PHIdicepool.append(SpecialDice(dval,"Φ"))
+        S.PHIdicepool.append(SpecialDice(dval, "Φ"))
     S.PHIdicepool.sort()
 
     print(
-"""
-Please give your PSI dice pool
-(same format)"""
+        """
+    Please give your PSI dice pool
+    (same format)"""
     )
-    uinput=ask("Ψ?")
-    if uinput=="":uinput="d4,d4,d4,d6,d8"
-    argsdice = uinput.split(",")
-    S.PSIdicepool = [] 
+    uinput = ask("Ψ?")
+    if uinput == "":
+        uinput = "d4 d4 d4 d6 d8"
+    argsdice = uinput.split(" ")
+    S.PSIdicepool = []
     for e in argsdice:
         dval = int(e[1:])
-        S.PSIdicepool.append(SpecialDice(dval,"Ψ"))
+        S.PSIdicepool.append(SpecialDice(dval, "Ψ"))
     S.PSIdicepool.sort()
 
-    line() 
+    line()
     printallstat(S)
-    print("\nWelcome "+S.name+" !")
+    print("\nWelcome " + S.name + " !")
     print(
-"""
-Please type your command. Type \033[1m help \033[0m
-To see available command or \033[1m help <command> \033[0m
-To get an explanation of a command"""
-        )
+        """
+    Please type your command. Type \033[1m help \033[0m
+    To see available command or \033[1m help <command> \033[0m
+    To get an explanation of a command"""
+    )
     line()
     ##Main While Command
     while True:
@@ -719,12 +840,14 @@ To get an explanation of a command"""
         ##print(Undoable.S)
         uinput = ask("command?")
         args = uinput.split(" ")
-        if args[0] in COMMAND_LIST: COMMAND_LIST[args[0]](args[1:],Undoable.S)
+        if args[0] in COMMAND_LIST:
+            COMMAND_LIST[args[0]](args[1:], Undoable.S)
         elif args[0] != "":
             print(
-"""
-No command found '"""+str(args[0])+"""'
-try \033[1mhelp\033[0m to see command list."""
+                """
+    No command found '"""
+                + str(args[0])
+                + """'
+    try \033[1mhelp\033[0m to see command list."""
             )
         line()
-
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000000000000000000000000000000000000..815f1319114d5cbf5a149fd60ae08257c44c29b2
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,3 @@
+- Trash command
+- restore command
+- edit command (to chaneg dice specifically)
diff --git a/__pycache__/dice.cpython-311.pyc b/__pycache__/dice.cpython-311.pyc
index bd66aa5f770f06cb98d4abd2db56f06329a1f4dd..18dffa00804861ca6e3f3a975d31ed10a94f242a 100644
Binary files a/__pycache__/dice.cpython-311.pyc and b/__pycache__/dice.cpython-311.pyc differ
diff --git a/ascii.txt b/ascii.txt
deleted file mode 100644
index 10b16e54c026a153b83cdbf8697b81e0923b9a80..0000000000000000000000000000000000000000
--- a/ascii.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-                                                                                  
-                                                                                  
-                                 ...',,,,,,''...                                  
-                           .';oOOOxolooddddxkOxdddo:,..                           
-                       .;dxxkOxdxxkxdooodddddddoddddddxdc,.                       
-                    ,lxOKKK0kdxxxxdddoc:cloxkxxdddooloocllll;.                    
-                 .cddddxxkdddododdooooooo:cdxxdlc::;,;;;;;;:ccc;.                 
-               ,oxxdddddddddooooolllc::coodoc::::,,,,:::c;,,;clcc:.               
-             ,odxxxxdddoolcc::::::oocoooodooolol;,;;;;;,;,,,;:oddlc;.             
-           .oxxdddoollcc::::::c::;cldddodxooooc,,,,,;;;;:;;,;;:okdc::,            
-          ;ddoollclllcooxolocoooodxxdxxlddx:;,';,,,;::;;;;lOl;;;cll:c:;.          
-         collllcdoxodOxolkOOOl,:lKNdodxxdkx:;cclOl:oxxOkOkdONNdc:c::;:::.         
-        llcclollllokkkollOddOkclxOM0xK0OOcl;ldKk:ldlOlc',,;d0Odcdo::lc::;.        
-       clokdc:clocOX00XOkxxk00xkxkXkkO000Oo;;ckkdldc'',','',;:;,:dkl::;c:;.       
-      ;oxdcc:;;:,lc;clokxoldddxOOkddkOOkoOOdkklcl:,''.,,,;:;,;:,,;ooool:::,       
-     .oxlccldc,;,oc::;,dOxkdddxkNXKOK0oooo:;lclx0oc;',;,''',,;:;;l;;coxl::;.      
-     oollkddo;;cccok;::kKdooxodkNNWN0oll:;'''lccxc;dx:'.'',,',;::;';:xxol;;,      
-    .xlldlckOxdodco;,;:llolddddkkOkdl;c;;c:,':::,.,:;;;,l''''',',;;:;:lccc:;.     
-    .l::ldoXOxl;,',';::loooooodkdlc::l::;;,''::;.......,;,;''';'',';:,;,;;c:'     
-    ,lcc:cokl:oOOoccxOK0Odolooooolcc::::;,,''',..''..',,,,:',';,,'',,,:;,;;;,     
-    ;lc:,,;;:,c:,,',:;c:;:kxkddd00k::;;ll;,'','......'..''ck:,;l;''',:c,;;;;,     
-    ,l:;,;col:c:;;;;,'''',cdkkOkkxxlc::;;;,''''....'......,;:dl,:l,,','',;;;,     
-    .oc:;:ccc:clO0Kkxdol;:cooO0KWN0kdoclll;;:,:'...''''','.',,:dc''',;',;;::'     
-     lxdk0dl;,::;oOKOxol;,',;oxOk0WMMWNWWWNW0oo::'',;:lc;:l'''''xl',';,',;:;.     
-     ;klo0Kk;;coOkcodol,,',:cccclclOXWMWMMMMMMWOx:;,,;lolldd,';;,kd;'',,:c:'      
-      dkxNNO:cclccllloo,..,cooddkol:;oXNMMMMMWOooc,;looxoxdx;,,o,lKc;,,,;;,.      
-      .xdKM0::ckddkO0Kkd:.,:;;lOXWK0kXMMMMMXKOkd;,,:cxloO0Olclodcodoc:,;;,'       
-       'lcXWKo:olloolo0NKOoclx0N0KMWMWWN0kololdo:;:cloccOWNK00O0xxddol:,;'        
-        ,oOWNdkKookxolllNNKlO0KOXNWXKK0OOkdodoloc;:c,:clxoxc:;dOOkxlccl;'.        
-         .d000kNclXOoooOWMWdKOkoo0K0Okkkkkkkdoollcodo:cc::;'',;looc;;;:.          
-          .lddoXkcdKN0dd0MWOOkKxoxO00XO0lodkddcoOOdcox::',,:cllc::;,;;.           
-            ,ol:ddd0K0kccokO0K0OO0NN0ddk0XK0OkK0xdxdllclloddodolc:::;.            
-              :doollx0kxoox00KNWWMWNK0NNMWMWW0OOKxolkkdddoooooolll:'              
-               .;oddd0NNXXWWWNNXKNXNMMWWWNWNWWWMMNKOkxOOxddolllc:'                
-                  'cdkkKNNWWWWNN0WWNWMWWMMMMMMMWWNNKkxddddlclc:.                  
-                     'clodkOKXN00WMMMMMMWWWNNNNKOOkxddddoll:'.                    
-                        .,coxxkkxx0KXKKKK00kxxxddddooolc,.                        
-                            ..,:cloddddddddooooolc:,..                            
-                                     .........                                    
-                                                                                  
-