ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> perl-AI
perl-AI
Game of Life
by Ala Qumsieh other posts by this author
Aug 27 2001 3:40PM messages near this date
RE: Game of Life | Perl creates life! (was Re: Game of Life)
Hey all,

I hacked a very quick Perl/Tk version of Conway's Game of Life and thought
some of you might enjoy it.

--Ala

#!/usr/bin/perl -w

use strict;
use Tk;

use vars qw/$repeat/;

my $size = 20;

#############################
# START OF USER CUSTOMIZABLE VARIABLES
#############################

# Size of the grid.
my $rows = 30;
my $cols = 30;

# The rules. An anonymous array of 2 arrays.
# The rules are like this:
# [
#   [ creation list  ]
#   [ survival list  ]
# ]
#
# The creation list is a list of numbers from 0 to 8 inclusive.
# If the sum of living neighbours of any cell is in this list
# then this cell springs up to life in the next generation.
#
# The survival list is a list of numbers from 0 to 8 inclusive.
# If the sum of living neighbours of any cell is in this list
# and the cell is alive, then it will survive to the next generation.
#
# All other cells die in the next generation.

my $rules = [
	     [3],
	     [2, 3],
	    ];

# Anonymous list or (row, column) coordinates of the starting
# pattern.

# Some boring test shape.
#  my $start = [
#  	     [4,3],
#  	     [4,4],
#  	     [4,5],
#  	     [4,6],
#  	    ];

# The infamous Glider!!
my $start = [
	     [1,2],
	     [2,3],
	     [3,1],
	     [3,2],
	     [3,3],
	    ];
#############################
# START OF USER CUSTOMIZABLE VARIABLES
#############################

drawGUI($rows, $cols, $size, $rules, $start);

MainLoop;

sub drawGUI {
    my ($rows,
	$cols,
	$size,
	$rules,
	$start,
       ) = @_;

    my $mw = new MainWindow;
    my $c  = $mw-> Canvas(-bg     => 'black',
			 -width  =>  $cols * $size,
			 -height =>  $rows * $size,
			)-> pack(qw/-side top/);

    $mw-> bind('<Any-Enter>', sub { $c->Tk::focus });

    my $array = [];
    for my $i (0 .. $rows - 1) {
	$array-> [$i] = [(0) x $cols];
    }

    # Draw the grid.
    for my $i (0 .. $rows) {
	$c-> createLine(0, $i * $size,
		       $cols * $size, $i * $size,
		       -fill =>  'white',
		      );
    }

    for my $i (0 .. $cols) {
	$c-> createLine($i * $size, 0,
		       $i * $size, $rows * $size,
		       -fill =>  'white',
		      );
    }

    my $frame = $mw-> Frame->pack(qw/-side top -expand 1
				 -fill both -padx 10 -pady 10/);

    $frame-> Button(
		   -text    =>  'Run',
		   -height  =>  3,
		   -command =>  [\&run, $array, $rules, $rows,
				$cols, $size, $c],
		  )-> pack(qw/side left -fill both -expand 1/);

    $frame-> Button(
		   -text    =>  'Exit',
		   -command =>  sub { exit },
		  )-> pack(qw/side left -fill both -expand 1/);

    # Fill in the starting pattern.
    for my $x (@$start) {
	fill($c, $size, @$x, $array);
    }
}

sub run {
    my ($array, $rules, $rows, $cols, $size, $c) = @_;

    $repeat = $c-> repeat(200, [\&step, $array, $rules,
			       $rows, $cols, $size, $c]);
}

sub step {
    my ($array, $rules, $rows, $cols, $size, $c) = @_;

    my ($fill, $unfill) = calc(
			       $array,
			       $rules,
			       $rows,
			       $cols,
			      );

    if (!@$unfill and !@$fill) {
	print "Done!\n";
	$c-> afterCancel($repeat);
    }

    fill  ($c, $size, @$_, $array) for @$fill;
    unfill($c, @$_, $array) for @$unfill;
    $c-> update;
}

sub fill {
    my ($c,
	$size,
	$row,
	$col,
	$array,
       ) = @_;

    $array-> [$row][$col] = 1;
    $c-> createOval(
		   $col * $size, $row * $size,
		   ($col + 1) * $size, ($row + 1) * $size,
		   -fill =>  'red',
		   -tags =>  "$row-$col",
		  );
}

sub unfill {
    my ($c, $row, $col, $array) = @_;

    $c-> delete("$row-$col");
    $array-> [$row][$col] = 0;
}

sub calc {
    my ($array, $rules, $rows, $cols) = @_;

    my (@fill, @unfill);

    for my $r (0 .. $rows - 1) {
	for my $c (0 .. $cols - 1) {
	    # Look at the neighbours.
	    my $sum = 0;

	    for my $n (
		       [$r - 1, $c - 1],
		       [$r - 1, $c    ],
		       [$r - 1, $c + 1],
		       [$r    , $c - 1],
		       [$r    , $c + 1],
		       [$r + 1, $c - 1],
		       [$r + 1, $c    ],
		       [$r + 1, $c + 1],
		      ) {

		$sum += $array-> [$n->[0]][$n->[1]] if
		    $n    -> [0] >= 0 && $n->[0] < $rows &&
			$n-> [1] >= 0 && $n->[1] < $cols;
	    }

	    if ($array-> [$r][$c]) {
		# will it survive?
		unless (grep {$_ == $sum} @{$rules-> [1]}) {
		    push @unfill =>  [$r, $c];
		}
	    } else {
		# will it get born?
		if (grep {$_ == $sum} @{$rules-> [0]}) {
		    push @fill =>  [$r, $c];
		}
	    }
	}
    }

    return (\@fill, \@unfill);
}
Thread:
Ala Qumsieh

Simon Cozens

Gidon Wise

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved