]>
Softwares of Agnibho - life.git/blob - Board.py
1 # Agnibho's Game of Life - Python implementation of Conway's Game of Life
2 # Copyright (C) 2014 Agnibho Mondal
4 # This file is part of Agnibho's Game of Life
6 # Agnibho's Game of Life is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # Agnibho's Game of Life is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Agnibho's Game of Life. If not, see <http://www.gnu.org/licenses/>.
19 from Tkinter
import BooleanVar
, StringVar
25 class Board(tk
.Frame
):
39 def __init__(self
, master
=None):
40 tk
.Frame
.__init
__(self
, master
)
42 self
.stepnum
=StringVar()
43 self
.steppop
=StringVar()
45 def render(self
, width
, depth
):
48 self
.start_dim
=[width
, depth
]
49 self
.statusbar
=tk
.Frame(self
)
50 self
.steplbl
=tk
.Label(self
.statusbar
, textvariable
=self
.stepnum
, padx
=10)
51 self
.poplbl
=tk
.Label(self
.statusbar
, textvariable
=self
.steppop
, padx
=10)
52 self
.contain
=tk
.Canvas(self
, width
=self
.WIDTH
*self
.SIZE
, height
=self
.DEPTH
*self
.SIZE
)
53 self
.toolbar
=tk
.Frame(self
)
54 self
.startbtn
=tk
.Button(self
.toolbar
, text
="Start", command
=self
.auto
)
55 self
.pausebtn
=tk
.Button(self
.toolbar
, text
="Pause", state
="disabled", command
=self
.pause
)
56 self
.stepbtn
=tk
.Button(self
.toolbar
, text
="Next Step", command
=self
.step
)
57 self
.resetbtn
=tk
.Button(self
.toolbar
, text
="Reset", command
=self
.reset
)
58 self
.revertbtn
=tk
.Button(self
.toolbar
, text
="Revert", state
="disabled", command
=self
.revert
)
59 self
.openbtn
=tk
.Button(self
.toolbar
, text
="Open", command
=self
.openfile
)
60 self
.savebtn
=tk
.Button(self
.toolbar
, text
="Save", command
=self
.savefile
)
61 self
.aboutbtn
=tk
.Button(self
.toolbar
, text
="About", command
=self
.about
)
62 self
.slider
=tk
.Scale(self
.toolbar
, orient
="horizontal", command
=self
.speed
, from_
=0, to
=900, resolution
=100, showvalue
=0, length
=150)
63 self
.spdlbl1
=tk
.Label(self
.toolbar
, text
="Slow")
64 self
.spdlbl2
=tk
.Label(self
.toolbar
, text
="Fast")
65 self
.statusbar
.grid(row
=0)
66 self
.steplbl
.grid(row
=0, column
=0)
67 self
.poplbl
.grid(row
=0, column
=1)
68 self
.contain
.grid(row
=1)
69 self
.toolbar
.grid(row
=2)
70 self
.startbtn
.grid(row
=0, column
=0)
71 self
.pausebtn
.grid(row
=0, column
=1)
72 self
.stepbtn
.grid(row
=0, column
=2)
73 self
.resetbtn
.grid(row
=0, column
=3)
74 self
.openbtn
.grid(row
=1, column
=0)
75 self
.savebtn
.grid(row
=1, column
=1)
76 self
.revertbtn
.grid(row
=1, column
=2)
77 self
.aboutbtn
.grid(row
=1, column
=3)
78 self
.spdlbl1
.grid(row
=2, column
=0)
79 self
.slider
.grid(row
=2, column
=1, columnspan
=2)
80 self
.spdlbl2
.grid(row
=2, column
=3)
82 for i
in range(0, self
.WIDTH
):
84 for j
in range (0, self
.DEPTH
):
85 self
.cells
[i
].append(Cell
.Cell(self
.contain
.create_rectangle(i
*self
.SIZE
, j
*self
.SIZE
, i
*self
.SIZE
+self
.SIZE
, j
*self
.SIZE
+self
.SIZE
, fill
="white", outline
="gray"), self
.contain
))
87 def recreate(self
, width
, depth
):
88 self
.contain
.destroy()
92 if(self
.SIZE
*self
.WIDTH
>self
.winfo_screenwidth() or self
.SIZE
*self
.DEPTH
>self
.winfo_screenheight()-150):
94 self
.WIDTH
=self
.winfo_screenwidth()/self
.SIZE
95 self
.DEPTH
=(self
.winfo_screenheight()-150)/self
.SIZE
98 self
.contain
=tk
.Canvas(self
, width
=self
.WIDTH
*self
.SIZE
, height
=self
.DEPTH
*self
.SIZE
)
99 self
.contain
.grid(row
=1)
101 for i
in range(0, self
.WIDTH
):
102 self
.cells
.append([])
103 for j
in range (0, self
.DEPTH
):
104 self
.cells
[i
].append(Cell
.Cell(self
.contain
.create_rectangle(i
*self
.SIZE
, j
*self
.SIZE
, i
*self
.SIZE
+self
.SIZE
, j
*self
.SIZE
+self
.SIZE
, fill
="white", outline
="gray"), self
.contain
))
107 for i
in range(0, self
.WIDTH
):
108 for j
in range (0, self
.DEPTH
):
109 self
.cells
[i
][j
].freeze()
110 self
.original
=self
.cells
112 self
.revertbtn
["state"]="normal"
116 tkMessageBox
.showwarning("Game over", "All life forms have been terminated")
118 if(self
.mode
=="edit"):
120 for i
in range(0, self
.WIDTH
):
121 for j
in range (0, self
.DEPTH
):
123 if(self
.cells
[i
][j
].getState()=="live"):
125 self
.cells
[i
][j
].makeDead()
126 elif(self
.cells
[i
][j
].getState()=="dead"):
128 self
.cells
[i
][j
].makeLive()
130 for i
in range(0, self
.WIDTH
):
131 for j
in range (0, self
.DEPTH
):
132 self
.cells
[i
][j
].commit()
133 if(self
.cells
[i
][j
].getState()=="live"):
135 if(self
.Pop
>self
.Max
):
140 tkMessageBox
.showwarning("Game over", "All life forms have been terminated\nMaximun polpulation reached: "+str(self
.Max
))
142 self
.startbtn
["state"]="disabled"
143 self
.stepbtn
["state"]="disabled"
145 self
.stepnum
.set("Generation: "+str(self
.Num
))
146 self
.steppop
.set("Population: "+str(self
.Pop
))
148 self
.stepnum
.set(str("Gen:"+str(self
.Num
)))
149 self
.steppop
.set("Pop:"+str(self
.Pop
))
150 if(self
.mode
=="auto"):
151 self
.timer
=self
.after(self
.TIME
, self
.step
)
154 self
.startbtn
["state"]="disabled"
155 self
.stepbtn
["state"]="disabled"
156 self
.pausebtn
["state"]="normal"
157 if(self
.mode
=="edit"):
160 self
.timer
=self
.after(self
.TIME
, self
.step
)
163 self
.startbtn
["state"]="normal"
164 self
.stepbtn
["state"]="normal"
165 self
.pausebtn
["state"]="disabled"
167 self
.after_cancel(self
.timer
)
170 filename
=tkFileDialog
.askopenfilename(filetypes
=[("Life 1.06", "*.life"), ("Life 1.6", "*.lif"), ("All", "*")])
171 self
.parsefile(filename
)
174 filename
=tkFileDialog
.asksaveasfilename(filetypes
=[("Life 1.06", "*.life"), ("Life 1.6", "*.lif")], defaultextension
=".life")
175 self
.writefile(filename
)
177 def parsefile(self
, filename
):
184 with
open(filename
) as f
:
186 data
=line
.strip().lower()
188 if(data
.startswith("#life")):
189 if(data
!="#life 1.06" and data
!="#life 1.6"):
190 tkMessageBox
.showerror("Format Error", "The file must be in Life 1.06 format.")
192 elif(data
.startswith("#")):
198 arr
[0][-1]=int(data
.split()[0])
199 arr
[1][-1]=int(data
.split()[1])
201 tkMessageBox
.showerror("Format Error", "Failed to open. The file has formatting error.")
202 print "Failed to open file\nFormat error near: "+line
205 tkMessageBox
.showerror("File not found", "Failed to open the specified file. Make sure the file exists and is readable.")
208 tkMessageBox
.showerror("Error", "Failed to open the specified file.")
213 if((max(arr
[0])-min(arr
[0]))>self
.WIDTH
/2 or (max(arr
[1])-min(arr
[1]))>self
.DEPTH
/2):
214 if((max(arr
[0])-min(arr
[0]))>self
.WIDTH
/2):
215 width
=(max(arr
[0])-min(arr
[0]))*2
217 if((max(arr
[1])-min(arr
[1]))>self
.DEPTH
/2):
218 depth
=(max(arr
[1])-min(arr
[1]))*2
220 self
.recreate(width
, depth
)
224 for i
in range(0, len(arr
[0])):
225 arr
[0][i
]+=self
.WIDTH
/2
227 for i
in range(0, len(arr
[1])):
228 arr
[1][i
]+=self
.DEPTH
/2
229 for i
in range(0, len(arr
[0])):
231 arr
[0][i
]+=self
.WIDTH
232 while(arr
[0][i
]>self
.WIDTH
):
233 arr
[0][i
]-=self
.WIDTH
234 for i
in range(0, len(arr
[0])):
236 arr
[1][i
]+=self
.DEPTH
237 while(arr
[1][i
]>self
.DEPTH
):
238 arr
[1][i
]-=self
.DEPTH
239 for i
in range(0, len(arr
[0])):
240 self
.cells
[arr
[0][i
]][arr
[1][i
]].toggle()
242 tkMessageBox
.showerror("Error", "Something went wrong. Failed to open the file properly.")
244 self
.reset(True, True)
246 def writefile(self
, filename
):
248 f
=open(filename
, "w")
249 f
.write("#Life 1.06\r\n")
250 for i
in range(0, self
.WIDTH
):
251 for j
in range (0, self
.DEPTH
):
252 if(self
.cells
[i
][j
].getState()=="live"):
253 f
.write(str(i
)+" "+str(j
)+"\r\n")
256 def reset(self
, full
=True, force
=False):
258 for i
in range(0, self
.WIDTH
):
259 for j
in range (0, self
.DEPTH
):
260 if(self
.cells
[i
][j
].getState()=="live"):
265 flag
=tkMessageBox
.askokcancel("Confirm Reset", "This action will erase all the cells from current board. Are you sure to continue?")
277 if(self
.WIDTH
==self
.start_dim
[0] and self
.DEPTH
==self
.start_dim
[1]):
278 for i
in range(0, self
.WIDTH
):
279 for j
in range (0, self
.DEPTH
):
280 self
.cells
[i
][j
].clear()
282 self
.recreate(self
.start_dim
[0], self
.start_dim
[1])
283 self
.revertbtn
["state"]="disabled"
287 for i
in range(0, self
.WIDTH
):
288 for j
in range (0, self
.DEPTH
):
289 self
.cells
[i
][j
].revert()
292 tkMessageBox
.showinfo("About Life", "Life 1.04 by Agnibho Mondal\nBased on Conway's Game of Life\nhttp://code.agnibho.com/life")
294 def count(self
, i
, j
):
296 for cl
in [self
.getCell(i
-1, j
-1), self
.getCell(i
-1, j
), self
.getCell(i
, j
-1), self
.getCell(i
+1, j
+1), self
.getCell(i
+1, j
), self
.getCell(i
, j
+1), self
.getCell(i
-1, j
+1), self
.getCell(i
+1, j
-1)]:
297 if(cl
.getState()=="live"):
301 def getCell(self
, x
, y
):
310 return self
.cells
[x
][y
]
312 def speed(self
, val
):
313 self
.TIME
=1000-int(val
)