Jason Tang 2002-09-25: Here is another implementation of the cellular automata game of Life.
Use the mouse and left drag to add life, right drag to remove. Hit the enter key to resume simulating. As cells "age" they change colors. Hope you like...If you want to try a Starkit version download it here [L1 ].
An optimized version of the program may be downloaded from http://jtang.org/tcl/life/
### Life by Jason Tang ### configurable parameters below package require Tk set CELL_SIZE 15 ;# size of each cell, in pixels set NUM_ROWS 20 ;# number of rows in the grid set NUM_COLS 20 ;# number of columns in the grid set REFRESH 10 ;# how often to calculate next iteration, in milliseconds set RESPAWN 120 ;# number of iterations before spawning new life set DENSITY 0.6 ;# how crowded to make world when generating life set NUM_ROWS 15 ;# number of rows in the grid set NUM_COLS 15 ;# number of columns in the grid ### end configuration proc life {start_col end_col start_row end_row} { global life for {set row $start_row} {$row <= $end_row} {incr row} { for {set col $start_col} {$col <= $end_col} {incr col} { set count($col,$row) 0 if {$life($col,$row) == 1} { set count($col,$row) -1 } for {set x [expr $col - 1]} {$x <= [expr $col + 1]} {incr x} { for {set y [expr $row - 1]} {$y <= [expr $row + 1]} {incr y} { if {$x < $start_col} { set x_col $end_col } elseif {$x > $end_col} { set x_col $start_col } else { set x_col $x } if {$y < $start_row} { set y_row $end_row } elseif {$y > $end_row} { set y_row $start_row } else { set y_row $y } incr count($col,$row) $life($x_col,$y_row) } } } } for {set row $start_row} {$row <= $end_row} {incr row} { for {set col $start_col} {$col <= $end_col} {incr col} { if {$life($col,$row) == 0 && $count($col,$row) == 3} { make_life $col $row } elseif {$life($col,$row) != 1 || \ [expr {$count($col,$row) != 2} && \ {$count($col,$row) != 3}]} { kill_life $col $row } else { incr life($col,$row:age) if {$life($col,$row:age) >= 10} { .c itemconfigure $life($col,$row:id) -fill red } elseif {$life($col,$row:age) >= 7} { .c itemconfigure $life($col,$row:id) -fill orange } elseif {$life($col,$row:age) >= 5} { .c itemconfigure $life($col,$row:id) -fill yellow } elseif {$life($col,$row:age) >= 4} { .c itemconfigure $life($col,$row:id) -fill greenyellow } elseif {$life($col,$row:age) >= 3} { .c itemconfigure $life($col,$row:id) -fill green } elseif {$life($col,$row:age) >= 2} { .c itemconfigure $life($col,$row:id) -fill turquoise } } } } } proc make_life {col row} { global life CELL_SIZE set life($col,$row:id) [.c create rectangle \ [expr $col * $CELL_SIZE + 1] \ [expr $row * $CELL_SIZE + 1] \ [expr [expr $col + 1] * $CELL_SIZE - 1] \ [expr [expr $row + 1] * $CELL_SIZE - 1] \ -fill blue -width 0] set life($col,$row:age) 1 set life($col,$row) 1 } proc kill_life {col row} { global life set life($col,$row) 0 if {[info exists life($col,$row:id)]} { .c delete $life($col,$row:id) unset life($col,$row:id) unset life($col,$row:age) } } proc generate_life {start_col end_col start_row end_row ratio} { global life for {set row $start_row} {$row <= $end_row} {incr row} { for {set col $start_col} {$col <= $end_col} {incr col} { if {[expr rand() < $ratio]} { make_life $col $row } } } } proc init_life {start_col end_col start_row end_row} { global life for {set row $start_row} {$row <= $end_row} {incr row} { for {set col $start_col} {$col <= $end_col} {incr col} { kill_life $col $row } } } proc button_down {x y new_life} { global CELL_SIZE set col [expr int($x / $CELL_SIZE)] set row [expr int($y / $CELL_SIZE)] kill_life $col $row if {$new_life} { make_life $col $row } } proc life_timer {} { global age NUM_ROWS NUM_COLS REFRESH RESPAWN DENSITY incr age -1 if {$age < 0} { set age $RESPAWN init_life 0 [expr $NUM_COLS - 1] 0 [expr $NUM_ROWS - 1] generate_life 0 [expr $NUM_COLS - 1] 0 [expr $NUM_ROWS - 1] $DENSITY } else { life 0 [expr $NUM_COLS - 1] 0 [expr $NUM_ROWS - 1] } update idletasks after $REFRESH life_timer } canvas .c -bg black -relief flat \ -scrollregion [list 0 0 [expr $NUM_COLS * $CELL_SIZE] \ [expr $NUM_ROWS * $CELL_SIZE]] \ -width [expr $NUM_COLS * $CELL_SIZE] \ -height [expr $NUM_ROWS * $CELL_SIZE] pack .c wm protocol . WM_DELETE_WINDOW { exit } wm title . "Life" bind . <ButtonPress-1> {after cancel life_timer; button_down %x %y 1} bind . <ButtonPress-3> {after cancel life_timer; button_down %x %y 0} bind . <B1-Motion> {button_down %x %y 1} bind . <B3-Motion> {button_down %x %y 0} bind . <Key-Return> {after cancel life_timer; set age $RESPAWN; life_timer} bind . <Key-space> {after cancel life_timer} update idletasks set age 0 life_timer