PYTHON   9

# LifeDisplay.py

Guest on 6th June 2021 05:06:19 PM

1. # LifeDisplay.py
2.
3. from graphics import GraphWin, Rectangle, Point, Circle, Line
4. from LifeWidgets import Button, InfoBox
5.
6. class Organism:
7.     #   An organism is a square representing one element
8.     #   on the board of a Game of Life.
9.     #
10.     #   An organism knows its own location on the board, and
11.     #   it can draw() itself and undraw() itself.
12.     #
13.     #   On the display, an organism is a solid rectangle
14.     #   one unit in size in the x- and y-directions and
15.     #   is located at integer boundaries in the coordinate
16.     #   system of the board. (Specifically, if an organism
17.     #   is located at position x, y on the board, the upper
18.     #   xMin corner of its rectangle is at point x, y, and
19.     #   the lower xMax corner is at point x+1, y+1.)
20.
21.     def __init__(self, xPos, yPos):
22.         #   Create a new organism
23.         self.__x  = xPos
24.         self.__y  = yPos
25.         upperxMin  = Point(self.__x, self.__y)
26.         lowerxMax = Point(self.__x+1, self.__y+1)
27.         rect = Rectangle(upperxMin, lowerxMax)
28.         rect.setFill("black")
29.         self.__rect = rect
30.         return
31.
32.     def draw(self, win):
33.         #   draw a square representing this organism
34.         if win.clip(self.__x, self.__y):
35.             self.__rect.draw(win)
36.         return
37.
38.     def undraw(self):
39.         #   undraw (i.e., delete on screen) the organism
40.         self.__rect.undraw()
41.         return
42.
43.
44. class LifeDisplay(GraphWin):
45.     #   This is a subclass of the graphics windows from
46.     #   graphics.py. It provices scaling so that each organism
47.     #   is on integer boundaries and occupied an integer
48.     #   number of pixels in each dimension. It also remembers
49.     #   its clipping boundaries so that the draw method
50.     #   of Organism does not draw outside the array.
51.     #
52.     #   Future expansion includes provision for buttons
53.     #   at text input in the window without impacting the
54.     #   game board itself
55.
56.     def __init__(self, width, height, orgSize=8, extra=4):
57.         #   The parameters width and height are measured in
58.         #   numbers of organisms. The parameter orgSize is
59.         #   the number of pixels on each edge of an organism.
60.         #   The parameter extra is the number of additional
61.         #   additional organism-sized rows reserved at the
62.         #   yMin of the display for buttons and other graphic
63.         #   fields.
64.
65.         #   The actual graphics window size
66.         winWidth  = abs(width * orgSize)
67.         winHeight = abs(height * orgSize + extra * orgSize)
68.         title = "Game of Life"
69.
70.         GraphWin.__init__(self, title,
71.                                       winWidth, winHeight)
72.
73.
74.         #   Clipping boundaries for the game board so that
75.         #   the origin is in the center.
76.         #
77.         #   Organisms with x, y positions are shown if and
78.         #   only if xMin <= x < xMax and yMin <= y < height
79.         xMin   = - width // 2
80.         xMax  = xMin + width
81.         yMin    = - height // 2
82.         yMax = yMin + height
83.         self.__xMin, self.__xMax = xMin, xMax
84.         self.__yMin, self.__yMax = yMin, yMax
85.         self.__extra = extra
86.
87.         self.setCoords(xMin, yMax + extra, xMax, yMin)
88.         self.drawAxes(xMin, xMax, yMin, yMax)
89.
90.         self.__stopButton = self.setupStopButton(self)
91.         self.__generationInfo = self.setupGenInfo(self)
92.         self.__generationsToPlay = \
93.                     self.setupGensToPlay(self, 150)
94.
95.         return
96.
97.     def drawAxes(self, xMin, xMax, yMin, yMax):
98.
99.         verticalAxis = self.line(0, yMin, 0, yMax, 'cyan')
100.         verticalAxis.draw(self)
101.
102.         horizontalAxis = self.line(xMin, 0, xMax, 0, 'cyan')
103.         horizontalAxis.draw(self)
104.
105.         yMaxBorder = self.line(xMin, yMax, xMax, yMax, 'black')
106.         yMaxBorder.draw(self)
107.
108.         return
109.
110.
111.     def clip(self, x, y):
112.         return (self.__xMin <= x < self.__xMax and \
113.            self.__yMin  <= y < self.__yMax)
114.
115.     def line(self, x0, y0, x1, y1, color='black'):
116.         start = Point(x0, y0)
117.         end   = Point(x1, y1)
118.         line  = Line(start, end)
119.         line.setWidth(1)
120.         line.setOutline(color)
121.         return line
122.
123.     def setupStopButton(self, win):
124.         cpx, cpy = self.__xMin + 5, \
125.                    self.__yMax + self.__extra/2
126.         center = Point(cpx, cpy)
127.         width  = 8
128.         height = self.__extra - 1
129.         activeText = 'Stop'
130.         inactiveText = 'Stopped'
131.
132.         return Button(win, center, width, height,
133.                       activeText, inactiveText)
134.
135.     def stopButton(self):
136.         return self.__stopButton
137.
138. ##    def pause(self, win, mouse):
139. ##        if self.__stopButton.clicked(mouse):
140. ##            self.__stopButton.deactivate()
141. ##        secondClick = win.getMouse()
142. ##        while not self.__stopButton.clicked(secondClick):
143. ##            secondClick = win.getMouse()
144. ##        self.__stopButton.activate()
145. ##        return
146.
147.
148.     def setupGenInfo(self, win):
149.         cpx, cpy = self.__xMin + 20, \
150.                    self.__yMax + self.__extra/2
151.         center = Point(cpx, cpy)
152.         labelWidth, infoWidth = 10, 6
153.         height = self.__extra - 1
154.         label  = 'Current Generation:-:'
155.
156.         return InfoBox(win, center, labelWidth, infoWidth,
157.                        height, label)
158.
159.     def updateGeneration(self, generation):
160.         self.__generationInfo.updateInfo(generation)
161.         return
162.
163.     def setupGensToPlay(self, win, defaultNumber):
164.         cpx, cpy = self.__xMin + 40, \
165.                    self.__yMax + self.__extra/2
166.         center = Point(cpx, cpy)
167.         labelWidth, infoWidth = 10, 6
168.         height = self.__extra - 1
169.         label  = 'Generations To Play:'
170.
171.         return InfoBox(win, center, labelWidth, infoWidth,
172.                        height, label, boxType='input',
173.                        infoValue = defaultNumber)
174.
175.     def GetNumberOfGenerations(self):
176.         return eval(self.__generationsToPlay.getInput())