From: Agnibho Mondal Date: Thu, 4 Dec 2014 13:22:10 +0000 (+0530) Subject: Added Life 1.06 file support X-Git-Url: https://code.agnibho.com/repo?a=commitdiff_plain;h=3e6a8423928a796a247d07b8c38306409a06d982;p=life.git Added Life 1.06 file support --- diff --git a/Board.py b/Board.py index 242c9bb..a407a54 100644 --- a/Board.py +++ b/Board.py @@ -1,11 +1,15 @@ -from Tkinter import BooleanVar +from Tkinter import BooleanVar, StringVar import Tkinter as tk +import tkFileDialog +import tkMessageBox import Cell class Board(tk.Frame): cells=[] - WIDTH=20 - DEPTH=20 + SIZE=10 + WIDTH=50 + DEPTH=50 + start_dim=[] Num=0 auto={} timer={} @@ -14,59 +18,164 @@ class Board(tk.Frame): tk.Frame.__init__(self, master) self.grid() self.auto=BooleanVar() + self.stepnum=StringVar() - def render(self, width, depth,): + def render(self, width, depth): self.WIDTH=width self.DEPTH=depth - self.contain=tk.Canvas(self, width=self.WIDTH*10, height=self.DEPTH*10) + self.start_dim=[width, depth] + self.contain=tk.Canvas(self, width=self.WIDTH*self.SIZE, height=self.DEPTH*self.SIZE) self.contain.grid() for i in range(0, self.WIDTH): self.cells.append([]) for j in range (0, self.DEPTH): - self.cells[i].append(Cell.Cell(self.contain.create_rectangle(i*10, j*10, i*10+10, j*10+10, fill="white", outline="gray"), self.contain)) + 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)) self.startbtn=tk.Button(self, text="Start", command=self.start) self.autobtn=tk.Checkbutton(self, text="Automatic", command=self.run, variable=self.auto) self.stepbtn=tk.Button(self, text="Next Step", command=self.step) self.resetbtn=tk.Button(self, text="Reset", command=self.reset) - self.startbtn.grid() + self.openbtn=tk.Button(self, text="Open", command=self.openfile) + self.savebtn=tk.Button(self, text="Save", command=self.savefile) + self.steplbl=tk.Label(self, textvariable=self.stepnum) + self.steplbl.grid(row=1) + self.startbtn.grid(row=1, sticky="W") + self.openbtn.grid(row=1, sticky="E") - def setdim(w, h): - self.WIDTH=w - self.DEPTH=h + def recreate(self, width, depth): + self.contain.destroy() + self.cells=[] + self.WIDTH=width + self.DEPTH=depth + if(self.SIZE*self.WIDTH>self.winfo_screenwidth()-100 or self.SIZE*self.DEPTH>self.winfo_screenheight()-150): + self.SIZE=5 + self.WIDTH=(self.winfo_screenwidth()-100)/self.SIZE + self.DEPTH=(self.winfo_screenheight()-150)/self.SIZE + else: + self.SIZE=10 + self.contain=tk.Canvas(self, width=self.WIDTH*self.SIZE, height=self.DEPTH*self.SIZE) + self.contain.grid(row=0) + + for i in range(0, self.WIDTH): + self.cells.append([]) + for j in range (0, self.DEPTH): + 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)) def start(self): for i in range(0, self.WIDTH): for j in range (0, self.DEPTH): self.cells[i][j].freeze() self.startbtn.grid_remove() - if(self.WIDTH>30): - self.stepbtn.grid(row=1) - self.resetbtn.grid(row=1, sticky="E") - self.autobtn.grid(row=1, sticky="W") - elif(self.WIDTH>10): - self.stepbtn.grid(row=1, sticky="W") - self.resetbtn.grid(row=1, sticky="E") - self.autobtn.grid(row=2) + self.openbtn.grid_remove() + self.stepbtn.grid(row=1, sticky="W") + self.resetbtn.grid(row=1, sticky="E") + self.autobtn.grid(row=2, sticky="W") + self.savebtn.grid(row=2, sticky="E") + + def openfile(self): + filename=tkFileDialog.askopenfilename(filetypes=[("Life 1.06", "*.life"), ("Life 1.6", "*.lif"), ("All", "*")]) + self.parsefile(filename) + + def savefile(self): + filename=tkFileDialog.asksaveasfilename(filetypes=[("Life 1.06", "*.life"), ("Life 1.6", "*.lif")], defaultextension=".life") + self.writefile(filename) + + def parsefile(self, filename): + self.reset() + arr=[] + arr.append([]) + arr.append([]) + if(len(filename)>0): + try: + with open(filename) as f: + for line in f: + data=line.strip().lower() + if(len(data)>0): + if(data.startswith("#life")): + if(data!="#life 1.06" and data!="#life 1.6"): + tkMessageBox.showerror("Format Error", "The file must be in Life 1.06 format.") + return + elif(data.startswith("#")): + continue + else: + arr[0].append([]) + arr[1].append([]) + try: + arr[0][-1]=int(data.split()[0]) + arr[1][-1]=int(data.split()[1]) + except ValueError: + tkMessageBox.showerror("Format Error", "Failed to open. The file has formatting error.") + print "Failed to open file\nFormat error near: "+line + return + except IOError: + tkMessageBox.showerror("File not found", "Failed to open the specified file. Make sure the file exists and is readable.") + return + except Exception, e: + tkMessageBox.showerror("Error", "Failed to open the specified file.") + print e + return else: - self.stepbtn.grid() - self.resetbtn.grid() - self.autobtn.grid() + return + if((max(arr[0])-min(arr[0]))>self.WIDTH/2 or (max(arr[1])-min(arr[1]))>self.DEPTH/2): + width=(max(arr[0])-min(arr[0]))*2 + depth=(max(arr[1])-min(arr[1]))*2 + self.recreate(width, depth) + + if(min(arr[0])<=0): + for i in range(0, len(arr[0])): + arr[0][i]+=self.WIDTH/2 + if(min(arr[1])<=0): + for i in range(0, len(arr[1])): + arr[1][i]+=self.DEPTH/2 + for i in range(0, len(arr[0])): + while(arr[0][i]<0): + arr[0][i]+=self.WIDTH + while(arr[0][i]>self.WIDTH): + arr[0][i]-=self.WIDTH + for i in range(0, len(arr[0])): + while(arr[1][i]<0): + arr[1][i]+=self.DEPTH + while(arr[1][i]>self.DEPTH): + arr[1][i]-=self.DEPTH + for i in range(0, len(arr[0])): + self.cells[arr[0][i]][arr[1][i]].makeLive() + self.cells[arr[0][i]][arr[1][i]].commit() + + def writefile(self, filename): + if(len(filename)>0): + f=open(filename, "w") + f.write("#Life 1.06\r\n") + for i in range(0, self.WIDTH): + for j in range (0, self.DEPTH): + if(self.cells[i][j].getState()=="live"): + f.write(str(i)+" "+str(j)+"\r\n") + f.close() def reset(self): - for i in range(0, self.WIDTH): - for j in range (0, self.DEPTH): - self.cells[i][j].makeDead() - self.cells[i][j].commit() - self.cells[i][j].unfreeze() + self.Num=0 + self.stepnum.set("") + if(self.WIDTH==self.start_dim[0] and self.DEPTH==self.start_dim[1]): + for i in range(0, self.WIDTH): + for j in range (0, self.DEPTH): + self.cells[i][j].makeDead() + self.cells[i][j].commit() + self.cells[i][j].unfreeze() + else: + self.recreate(self.start_dim[0], self.start_dim[1]) self.stepbtn.grid_remove() self.resetbtn.grid_remove() self.autobtn.grid_remove() + self.savebtn.grid_remove() self.startbtn.grid() + self.openbtn.grid() if(self.auto.get()): self.autobtn.invoke() def step(self): self.Num+=1 + if(self.WIDTH>30): + self.stepnum.set("Generation: "+str(self.Num)) + else: + self.stepnum.set(str(self.Num)) for i in range(0, self.WIDTH): for j in range (0, self.DEPTH): z=self.count(i, j) diff --git a/README.TXT b/README.TXT index ca5240a..3208e8c 100644 --- a/README.TXT +++ b/README.TXT @@ -8,9 +8,14 @@ General Usage Notes -You can specify dimensions by providing width and height as arguments. Eg: python __main__.py 20 20 -Seed the board by clicking on cells -Click to begin emulation +-Open Life 1.06 files by clicking and selecting the file from your computer -Click for emulating the next step -Select the checkbox for automatically running the game -Click to reset all the cells +-Save the current pattern to your computer by clicking and choosing the target file to save. +-You can specify the cell dimensions by supplying the number of cells in rows and columns respectively as arguments. Example: python life.zip 20 20 +-To directly open a file from the command line supply the filename as argument. Example: python life.zip +-The program supports Life 1.06 file format only. To use other file formats you need to convert them to Life 1.06 first. Program Notes ------------- diff --git a/__main__.py b/__main__.py index 8dddb3c..59dab97 100644 --- a/__main__.py +++ b/__main__.py @@ -2,10 +2,11 @@ import sys import Board -width=20 -depth=20 +width=50 +depth=50 +filename="" app=Board.Board() -app.master.title("The Game of Life") +app.master.title("Conway's Game of Life - Agnibho.com") if(len(sys.argv)>1): if(len(sys.argv)==3): @@ -15,19 +16,23 @@ if(len(sys.argv)>1): except Exception: print "Dimensions must be integer" sys.exit() + elif(len(sys.argv)==2): + filename=sys.argv[1] else: print "Argument not recognized" sys.exit() -if(width<5 or depth<5): - width=20 - depth=20 - print "Dimensions must be more than 5x5" +if(width<10 or depth<10): + width=50 + depth=50 + print "Dimensions must be more than 10x10" sys.exit() elif(width>app.winfo_screenwidth()/10 or depth>app.winfo_screenheight()/10-10): - width=20 - depth=20 + width=50 + depth=50 print "Dimensions are too large to fit in the screen. Maximum allowed dimension "+str(app.winfo_screenwidth()/10)+"x"+str(app.winfo_screenheight()/10-10) sys.exit() app.render(width, depth) +if(len(filename)>0): + app.parsefile(filename) app.mainloop() \ No newline at end of file