[Jason Tang] (September 25, 2002) - Here is another implementation of the cellular automata game of ''Life''. [http://mywebpages.comcast.net/jakeforce/Life.jpg] Use the mouse and right click on the canvas to add cells. Hope you like... ---- ### Life by Jason Tang ### configurable parameters below 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 . {console show} bind . {after cancel life_timer} bind . {after cancel life_timer} bind . {button_down %x %y 1} bind . {button_down %x %y 0} bind . {life_timer} bind . {life_timer} update idletasks set age 0 life_timer