g | x | w | all
Bytes Lang Time Link
597Python 3.8240205T092121ZSevC_10

Python 3.8, 597 bytes

from copy import deepcopy as p
def f(r):
 u,g,b,e={},0,[],' '
 for l in r:
  if g:b+=[list(l)];z=len(l);continue
  j=l[:1]
  if'T'<j:c=[e,l[20]][l[6]>'n'];u[c]=[]
  if'I'==j:
   n=[]
   for s in l[13:].split(' or '):
    n+=[int(s[0])]
    if s[3:]:v=[s[2],e][','<s[3:4]]
   u[c]+=[[v,n,[l[-2],e][l[-3]>e]]]
  if'O'==j:i=int(l.split()[4]);g=1
 for _ in e*i:
  h=p(b)
  for k in range(len(b)*z):
   r,c=k//z,k%z;v={k:0 for k in u}
   for j in range(9):x,y=j//3-1,j%3-1;v[b[(r+y)%len(b)][(c+x)%z]]+=1
   a=b[r][c];v[a]-=1
   for w in u[a]:
    if v[w[0]]in w[1]:h[r][c]=w[2];break
  b=p(h)
 return b

Try it online!

Online custom game of life simulator: Emoji Simulator!


Commented code

from copy import deepcopy as p

def f(r):
    """Takes as input a list of lines"""
    
    # dictiornary of rules of the grid
    u = {}
    # flag to extract lines of the grid
    g = 0
    # the grid, as a list of lists of characters
    b = []
    # space used to represent nothing
    e = ' '
    
    
    # PART 1
    # parse the rules
    
    # loop on the input lines
    for l in r:
        
        if g:
            # extract lines of the grid
            b += [list(l)]
            # extract the lenght of the row of the grid
            # used for the loop n the grid
            z = len(l)
            
            # skip other checks
            continue
        
        # extract the first character for each line
        # not [0] since it can be an empty line
        j = l[:1]
        
        if 'T' < j:
            
            # line "Using the character ..."
            
            # extract the character
            # checking if the character is nothing
            c = [e, l[20]][l[6] > 'n']
            
            # initialize an empty list for the rules associated to the character
            u[c] = []
        
        if 'I' == j:
            
            # line "If there are ..."
            
            # initialize list of repetitions
            n = []
            
            # the number of repetitions are split by or
            for s in l[13:].split(' or '):
                
                # extract the number
                # always the first element of the split
                n += [int(s[0])]
                
                # extract the character associated with the repetitions
                # the number is followed by the character
                # this means that the split string is longer
                if s[3:]:
                    
                    # character associated with the repetitons
                    # checking if the character is nothing
                    v = [s[2], e][',' < s[3:4]]
            
            # add the rule
            u[c] += [[
            # character associated with the repetitons
            v,
            # list of number of repetitions
            n,
            # extract the new character to substitute
            # checking if the character is nothing
            [l[-2], e][l[-3] > e]
            ]]
        
        if 'O' == j:
            
            # line "Output the result ..."
            
            # extract the number of steps
            i = int(l.split()[4])
            # set flag to extract the lines of the grid
            g = 1
    
    
    # PART 2
    # evaluate the steps on the grid
    
    # loop for i steps
    # e*i is an auxiliary string of length i to evaluate i steps
    for _ in e * i:
        
        # copy the previous grid state
        h = p(b)
        
        # loop on each cell of the grid
        # loop on height*width
        for k in range(len(b)*z):
            
            # extract the index of row, column from the "total" loop index
            r, c = k//z, k%z
            
            # initialize dictionary of count of neighbouring characters
            v = {k: 0 for k in u}
            
            # loop on the 3x3 square around the actual cell
            for j in range(9):
                
                # scale to range [-1, 0, 1]
                x, y = j//3 - 1, j%3 - 1
                
                # update the count of neighbour
                # extracting the corresponding character in the grid
                v[b[(r+y)%len(b)][(c+x)%z]] += 1
            
            # current character
            a = b[r][c]
            
            # remove the current cell from the count of neighbours
            v[a] -= 1
            
            # check rules
            for w in u[a]:
                
                # if count of neighbour is in list of number of repetitions
                if v[w[0]] in w[1]:
                    
                    # substituite actual character in the grid with the new one
                    h[r][c] = w[2]
                    
                    # rule found, skip others
                    break
        
        # update the actual grid
        b = p(h)
    
    # return the grid after the steps
    return b