# isorule.py

Feb 14th, 2019 (edited)
406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. # isorule.py
2. # A modification of partialrule.py which returns the isotropic rulespace for a pattern in a format suitable for infoboxes on the wiki.
3. # This simply checks the number of generations you input to see if the pattern's evolution is the same, so it can be used for non-periodic patterns as well.
4. # Shamelessly stolen from Rhombic (Feb 2018) by Ian07 (Jan 2019).
5. # Now fixed for Python 3.x! (Oct 2020)
6.
7. import golly as g
8. from glife import validint
9.
10. Hensel = [
11.     ['0'],
12.     ['1c', '1e'],
13.     ['2a', '2c', '2e', '2i', '2k', '2n'],
14.     ['3a', '3c', '3e', '3i', '3j', '3k', '3n', '3q', '3r', '3y'],
15.     ['4a', '4c', '4e', '4i', '4j', '4k', '4n', '4q', '4r', '4t', '4w', '4y', '4z'],
16.     ['5a', '5c', '5e', '5i', '5j', '5k', '5n', '5q', '5r', '5y'],
17.     ['6a', '6c', '6e', '6i', '6k', '6n'],
18.     ['7c', '7e'],
19.     ['8']
20. ]
21.
22. # Python versions < 2.4 don't have "sorted" built-in
23. try:
24.     sorted
25. except NameError:
26.     def sorted(inlist):
27.         outlist = list(inlist)
28.         outlist.sort()
29.         return outlist
30.
31. # --------------------------------------------------------------------
32.
33. def chunks(l, n):
34.     for i in range(0, len(l), n):
35.         yield l[i:i+n]
36.
37. # --------------------------------------------------------------------
38.
39. def rulestringopt(a):
40.     result = ''
41.     context = ''
42.     lastnum = ''
43.     lastcontext = ''
44.     for i in a:
45.         if i in 'BS':
46.             context = i
47.             result += i
48.         elif i in '012345678':
49.             if (i == lastnum) and (lastcontext == context):
50.                 pass
51.             else:
52.                 lastcontext = context
53.                 lastnum = i
54.                 result += i
55.         else:
56.             result += i
57.     result = str.replace(result, '4aceijknqrtwyz', '4')
58.     result = str.replace(result, '3aceijknqry', '3')
59.     result = str.replace(result, '5aceijknqry', '5')
60.     result = str.replace(result, '2aceikn', '2')
61.     result = str.replace(result, '6aceikn', '6')
62.     result = str.replace(result, '1ce', '1')
63.     result = str.replace(result, '7ce', '7')
64.     return result
65.
66. clist = []
67. rule = g.getrule().split(':')[0]
68.
69. fuzzer = rule + '9'
70. oldrule = rule
71. rule = ''
72. context = ''
73. deletefrom = []
74. for i in fuzzer:
75.     if i == '-':
76.         deletefrom = [x[1] for x in Hensel[int(context)]]
77.     elif i in '0123456789/S':
78.         if deletefrom:
79.             rule += ''.join(deletefrom)
80.             deletefrom = []
81.         context = i
82.     if len(deletefrom) == 0:
83.         rule += i
84.     elif i in deletefrom:
85.         deletefrom.remove(i)
86. rule = rule.strip('9')
87.
88. if not (rule[0] == 'B' and '/S' in rule):
89.     g.exit('Please set Golly to a Life-like rule.')
90.
91. if g.empty():
92.     g.exit('The pattern is empty.')
93.
94. s = g.getstring('Enter the period:', '', 'Rules calculator')
95. if not validint(s):
96.     g.exit('Bad number: %s' % s)
97.
98. numsteps = int(s)
99. if numsteps < 1:
100.     g.exit('Period must be at least 1.')
101.
102. g.select(g.getrect())
103. g.copy()
104. s = int(s)
105.
106. for i in range(0,s):
107.     g.run(1)
108.     clist.append(list(chunks(g.getcells(g.getrect()), 2)))
109.     mcc = min(clist[i])
110.     clist[i] = [[x[0] - mcc[0], x[1] - mcc[1]] for x in clist[i]]
111.
112. g.show('Processing...')
113.
114. ruleArr = rule.split('/')
115. ruleArr[0] = ruleArr[0].lstrip('B')
116. ruleArr[1] = ruleArr[1].lstrip('S')
117.
118. b_need = []
119. b_OK = []
120. s_need = []
121. s_OK = []
122.
123. context = ''
124. fuzzed = ruleArr[0] + '9'
125. for i in fuzzed:
126.     if i in '0123456789':
127.         if len(context) == 1:
128.             b_need += Hensel[int(context)]
129.             b_OK += Hensel[int(context)]
130.         context = i
131.     elif context != '':
132.         b_need.append(context[0] + i)
133.         b_OK.append(context[0] + i)
134.         context += context[0]
135. context = ''
136. fuzzed = ruleArr[1] + '9'
137. for i in fuzzed:
138.     if i in '0123456789':
139.         if len(context) == 1:
140.             s_need += Hensel[int(context)]
141.             s_OK += Hensel[int(context)]
142.         context = i
143.     elif context != '':
144.         s_need.append(context[0] + i)
145.         s_OK.append(context[0] + i)
146.         context += context[0]
147.
148. for i in [iter2 for iter1 in Hensel for iter2 in iter1]:
149.     if not i in b_OK:
150.         b_OK.append(i)
151.         execfor = 1
152.         # B0 and nontotalistic rulestrings are mutually exclusive
153.         try:
154.             g.setrule(rulestringopt('B' + ''.join(b_OK) + '/S' + ruleArr[1]))
155.         except:
156.             b_OK.remove(i)
157.             execfor = 0
158.         for j in range(0, s * execfor):
159.             g.run(1)
160.             try:
161.                 dlist = list(chunks(g.getcells(g.getrect()), 2))
162.                 mcc = min(dlist)
163.                 dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
164.                 if not(clist[j] == dlist):
165.                     b_OK.remove(i)
166.                     break
167.             except:
168.                 b_OK.remove(i)
169.                 break
170.         g.new('')
171.         g.paste(0, 0, 'or')
172.         g.select(g.getrect())
173.         b_OK.sort()
174.
175.     if not i in s_OK:
176.         s_OK.append(i)
177.         execfor = 1
178.         # B0 and nontotalistic rulestrings are mutually exclusive
179.         try:
180.             g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_OK)))
181.         except:
182.             s_OK.remove(i)
183.             execfor = 0
184.         for j in range(0, s * execfor):
185.             g.run(1)
186.             try:
187.                 dlist = list(chunks(g.getcells(g.getrect()), 2))
188.                 mcc = min(dlist)
189.                 dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
190.                 if not(clist[j] == dlist):
191.                     s_OK.remove(i)
192.                     break
193.             except:
194.                 s_OK.remove(i)
195.                 break
196.         g.new('')
197.         g.paste(0, 0, 'or')
198.         g.select(g.getrect())
199.         s_OK.sort()
200.
201.     if i in b_need:
202.         b_need.remove(i)
203.         g.setrule(rulestringopt('B' + ''.join(b_need) + '/S' + ruleArr[1]))
204.         for j in range(0, s):
205.             g.run(1)
206.             try:
207.                 dlist = list(chunks(g.getcells(g.getrect()), 2))
208.                 mcc = min(dlist)
209.                 dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
210.                 if not(clist[j] == dlist):
211.                     b_need.append(i)
212.                     break
213.             except:
214.                 b_need.append(i)
215.                 break
216.         g.new('')
217.         g.paste(0, 0, 'or')
218.         g.select(g.getrect())
219.         b_need.sort()
220.
221.     if i in s_need:
222.         s_need.remove(i)
223.         g.setrule(rulestringopt('B' + ruleArr[0] + '/S' + ''.join(s_need)))
224.         for j in range(0, s):
225.             g.run(1)
226.             try:
227.                 dlist = list(chunks(g.getcells(g.getrect()), 2))
228.                 mcc = min(dlist)
229.                 dlist = [[x[0] - mcc[0], x[1] - mcc[1]] for x in dlist]
230.                 if not(clist[j] == dlist):
231.                     s_need.append(i)
232.                     break
233.             except:
234.                 s_need.append(i)
235.                 break
236.         g.new('')
237.         g.paste(0, 0, 'or')
238.         g.select(g.getrect())
239.         s_need.sort()
240.
241. g.setrule('B' + ''.join(sorted(b_need)) + '/S' + ''.join(sorted(s_need)))
242. rulemin = g.getrule()
243.
244. g.setrule('B' + ''.join(sorted(b_OK)) + '/S' + ''.join(sorted(s_OK)))
245. rulemax = g.getrule()
246.
247. ruleres = '|isorulemin       = ' + rulemin + '|isorulemax       = ' + rulemax
248. g.show(ruleres)
249. g.setclipstr(ruleres)
250. g.setrule(oldrule)