File: __init__.py

package info (click to toggle)
golly 3.2-2
  • links: PTS
  • area: main
  • in suites: buster
  • size: 19,516 kB
  • sloc: cpp: 69,819; ansic: 25,894; python: 7,921; sh: 4,267; objc: 3,721; java: 2,781; xml: 1,362; makefile: 530; perl: 69
file content (267 lines) | stat: -rw-r--r-- 8,493 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# Initialization script executed by using "import glife".
# Based on python/life/__init__.py in Eugene Langvagen's PLife.

import golly
import sys
import time

__doc__ = """High-level scripting aids for Golly.""";

# --------------------------------------------------------------------

class rect(list):
    """A simple class to make it easier to manipulate rectangles."""

    def visible(self):
        """Return true if rect is completely visible in viewport."""
        return golly.visrect( [self.x, self.y, self.wd, self.ht] )

    def __init__(self, R = []):
        if len(R) == 0:
            self.empty = True
        elif len(R) == 4:
            self.empty = False
            self.x  = self.left   = R[0]
            self.y  = self.top    = R[1]
            self.wd = self.width  = R[2]
            self.ht = self.height = R[3]
            if self.wd <= 0: raise ValueError("rect width must be > 0")
            if self.ht <= 0: raise ValueError("rect height must be > 0")
            self.right  = self.left + self.wd - 1
            self.bottom = self.top  + self.ht - 1
        else:
            raise TypeError("rect arg must be [] or [x,y,wd,ht]")
        list.__init__(self, R)

# --------------------------------------------------------------------

# Define some useful synonyms:

# for golly.clear and golly.advance
inside = 0
outside = 1

# for golly.flip
left_right = 0
top_bottom = 1
up_down = 1

# for golly.rotate
clockwise = 0
anticlockwise = 1

# for golly.setcursor (must match strings in Cursor Mode submenu)
draw =    "Draw"
pick =    "Pick"
select =  "Select"
move =    "Move"
zoomin =  "Zoom In"
zoomout = "Zoom Out"

# --------------------------------------------------------------------

# Define some transformation matrices:

identity = ( 1,  0,  0,  1)

flip     = (-1,  0,  0, -1)
flip_x   = (-1,  0,  0,  1)
flip_y   = ( 1,  0,  0, -1)

swap_xy      = ( 0,  1,  1,  0)
swap_xy_flip = ( 0, -1, -1,  0)

# Rotation:

rcw  = ( 0, -1,  1,  0)
rccw = ( 0,  1, -1,  0)

# --------------------------------------------------------------------

def rule(s = "B3/S23"):
    """\
 Set the rule for the Game of Life.
 Although it affects subsequent calls to pattern.evolve(),
 only the last call to this function matters for the viewer."""
    golly.setrule(s)

# --------------------------------------------------------------------

def description(s):
    """Supply a textual description to the whole pattern."""
    for line in s.split("\n"):
        print "#D", line

# --------------------------------------------------------------------

def compose(S, T):
    """\
 Return the composition of two transformations S and T.
 A transformation is a tuple of the form (x, y, A), which denotes
 multiplying by matrix A and then translating by vector (x, y).
 These tuples can be passed to pattern.__call__()."""
    x = S[0]; y = S[1]; A = S[2]
    s = T[0]; t = T[1]; B = T[2]
    return (x * B[0] + y * B[1] + s, x * B[2] + y * B[3] + t,
       (A[0] * B[0] + A[2] * B[1], A[1] * B[0] + A[3] * B[1],
        A[0] * B[2] + A[2] * B[3], A[1] * B[2] + A[3] * B[3]))

# --------------------------------------------------------------------

class pattern(list):
    """This class represents a cell list."""

    def __add__(self, q):
        """Join patterns."""
        return pattern(golly.join(self, q))

    def __getitem__(self, N):
        """\
  The __getitem__() function is an alias to evolve().
  It allows to access the pattern's phases as elements of an array."""
        return self.evolve(N)

    def __call__(self, x, y, A = identity):
        """The same as 'apply(A).translate(x, y)'."""
        return pattern(golly.transform(self, x, y, *A))

    def translate(self, x, y):
        """Translate the pattern."""
        return self(x, y)

    def apply(self, A):
        """\
  Apply a matrix transformation to the pattern.
  Predefined matrices are:
  identity, flip, flip_x, flip_y, swap_xy, swap_xy_flip,
  rcw (rotate clockwise) and rccw (rotate counter-clockwise)."""
        return self(0, 0, A)

    def put(self, x = 0, y = 0, A = identity):
        """Paste pattern into current universe."""
        golly.putcells(self, x, y, *A)

    def display(self, title = "untitled", x = 0, y = 0, A = identity):
        """Paste pattern into new universe and display it all."""
        golly.new(title)
        golly.putcells(self, x, y, *A)
        golly.fit()
        golly.setcursor(zoomin)

    def save(self, fn, desc = None):
        """\
  Save the pattern to file 'fn' in RLE format.
  An optional description 'desc' may be given."""
        golly.store(self, fn, desc)

    def evolve(self, N):
        """\
  Return N-th generation of the pattern.
  Once computed, the N-th generation is remembered and quickly accessible.
  It is also the base for computing generations subsequent to N-th."""
        if N < 0:
            raise ValueError("backward evolving requested")
        if self.__phases.has_key(N):
            return self.__phases[N]
        M = 0
        for k in self.__phases.keys():
            if M < k < N: M = k
        p = self.__phases[N] = pattern(golly.evolve(self.__phases[M], N - M))
        return p

    def __init__(self, P = [], x0 = 0, y0 = 0, A = identity):
        """\
  Initialize a pattern from argument P.
  P may be another pattern, a cell list, or a multi-line string.
  A cell list should look like [x1, y1, x2, y2, ...];
  a string may be in one of the two autodetected formats:
  'visual' or 'RLE'.
  o  'visual' format means that the pattern is represented
     in a visual way using symbols '*' (on cell), '.' (off cell)
     and '\\n' (newline), just like in Life 1.05 format.
     (Note that an empty line should contain at least one dot).
  o  'RLE' format means that a string is Run-Length Encoded.
     The format uses 'o' for on-cells, 'b' for off-cells and
     '$' for newlines.
     Moreover, any of these symbols may be prefixed by a number,
     to denote that symbol repeated that number of times.

  When P is a string, an optional transformation
  (x0, y0, A) may be specified.
  """
        self.__phases = dict()

        if type(P) == list:
            list.__init__(self, P)
        elif type(P) == pattern:
            list.__init__(self, list(P))
        elif type(P) == str:
            list.__init__(self, golly.parse(P, x0, y0, *A))
        else:
            raise TypeError("list or string is required here")
        self.__phases[0] = self

# --------------------------------------------------------------------

def load(fn):
    # note that top left cell of bounding box will be at 0,0
    return pattern(golly.load(fn))

# --------------------------------------------------------------------

def getminbox(patt):
    # return a rect which is the minimal bounding box of given pattern;
    # note that if the pattern is a multi-state list then any dead cells
    # are included in the bounding box
    minx =  sys.maxint
    maxx = -sys.maxint
    miny =  sys.maxint
    maxy = -sys.maxint
    clist = list(patt)
    clen = len(clist)
    inc = 2
    if clen & 1 == 1:
        # multi-state list (3 ints per cell)
        inc = 3
        # ignore padding int if it is present
        if clen % 3 == 1: clen -= 1

    for x in xrange(0, clen, inc):
        if clist[x] < minx: minx = clist[x]
        if clist[x] > maxx: maxx = clist[x]

    for y in xrange(1, clen, inc):
        if clist[y] < miny: miny = clist[y]
        if clist[y] > maxy: maxy = clist[y]

    return rect( [ minx, miny, maxx - minx + 1, maxy - miny + 1 ] )

# --------------------------------------------------------------------

def validint(s):
    # return True if given string represents a valid integer
    if len(s) == 0: return False
    s = s.replace(",","")
    if s[0] == '+' or s[0] == '-': s = s[1:]
    return s.isdigit()

# --------------------------------------------------------------------

def getposint():
    # return current viewport position as integer coords
    x, y = golly.getpos()
    return int(x), int(y)

# --------------------------------------------------------------------

def setposint(x,y):
    # convert integer coords to strings and set viewport position
    golly.setpos(str(x), str(y))

# --------------------------------------------------------------------

def getstring(prompt):
    # this routine is deprecated
    golly.warn("Change the script to use the getstring() command\n"+
               "from golly rather than from glife.")
    golly.exit("")