]> Softwares of Agnibho - life.git/commitdiff
Added Life 1.06 file support
authorAgnibho Mondal <mail@agnibho.com>
Thu, 4 Dec 2014 13:22:10 +0000 (18:52 +0530)
committerAgnibho Mondal <mail@agnibho.com>
Thu, 4 Dec 2014 13:22:10 +0000 (18:52 +0530)
Board.py
README.TXT
__main__.py

index 242c9bba57d30ed99d4502fe164433c713d0e34c..a407a54bb12768155a7a2ea82bd488e5495a1410 100644 (file)
--- 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)
index ca5240aa97e8d1e28a9fa049e2cfa742ade4943f..3208e8cc16ed4fd3048bc9bca82e9749fa0df8d8 100644 (file)
@@ -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 <Start> to begin emulation
+-Open Life 1.06 files by clicking <Open> and selecting the file from your computer
 -Click <Next Step> for emulating the next step
 -Select the <Automatic> checkbox for automatically running the game
 -Click <Reset> to reset all the cells
+-Save the current pattern to your computer by clicking <Save> 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 <filename>
+-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
 -------------
index 8dddb3cdd096118ce92d18c0163b094814c27ed9..59dab973cd7df4f57b763e31615d94e68262ad08 100644 (file)
@@ -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