Skip to content

Instantly share code, notes, and snippets.

@YujiSODE
Created March 25, 2019 09:23
Show Gist options
  • Save YujiSODE/49ee3fbee5806d8e0b44a97a6f2b44b5 to your computer and use it in GitHub Desktop.
Save YujiSODE/49ee3fbee5806d8e0b44a97a6f2b44b5 to your computer and use it in GitHub Desktop.
Conway's Game of Life on Tcl.
#tclCell
#tclCell.tcl
##===================================================================
# Copyright (c) 2019 Yuji SODE <yuji.sode@gmail.com>
#
# This software is released under the MIT License.
##===================================================================
#Conway's Game of Life on Tcl.
#=== Synopsis ===
# [shell]
# - `tclsh tclCell.tcl`
#
# [tclsh]
# - `tclCell ?w? ?h? ?N? ?char0? ?char1?;`
# === parameters ===
# - $w and $h: width and height of map that are 10 or more
# - $N: model simulated for N time steps
# - $char0 and $char1: characters to replace 0 and 1
#
#=== Description ===
#It runs Conway's Game of Life and generates namespace.
#Simulation log is available at `::TCLCELL::log`.
##===================================================================
#it runs Conway's Game of Life and generates namespace called `::TCLCELL`
proc tclCell {{w 10} {h 10} {N 10} {char0 __} {char1 \u2588\u2588}} {
# - $w and $h: width and height of map that are 10 or more
# - $N: model simulated for N time steps
# - $char0 and $char1: characters to replace 0 and 1
set i 0;set j 0;set v {};
set w [expr {$w>9?int($w):10}];
set h [expr {$h>9?int($h):10}];
set N [expr {$N>0?$N:10}];
#===<< namespace ::TCLCELL >>===
namespace eval ::TCLCELL {
#map is map data
variable map {};
#W and H are width and height of map
variable W 0;variable H 0;
#log is simulation log
variable log {};
#number of steps
variable nSteps 0;
};
#=== procedures in namespace ::TCLCELL ===
#it calculates next step
proc ::TCLCELL::step {} {
#map data and its log and size
variable ::TCLCELL::map;variable ::TCLCELL::log;
variable ::TCLCELL::W;variable ::TCLCELL::H;
#number of steps
variable ::TCLCELL::nSteps;
set y 0;set x 0;set v {};set _map {};
set c0 0;
set c 0;
#rule of "Conway's Game of Life"
#[surrounding sum: 012345678]
#[_current cell=0: 000100000]
#[_current cell=1: 001100000]
set rule {{0 0 0 1 0 0 0 0 0} {0 0 1 1 0 0 0 0 0}};
while {$y<$H} {
set x 0;set v {};
while {$x<$W} {
#Moore neighborhood: c0 and c1 to c8
# [c1|c2|c3]
# [c4|c0|c5]
# [c6|c7|c8]
set c0 0;set c 0;
#c0
set c0 [string index [lindex $map $y] $x];
#c1
set c [expr {$y>0&&$x>0?$c+[string index [lindex $map $y-1] $x-1]:$c}];
#c2
set c [expr {$y>0?$c+[string index [lindex $map $y-1] $x]:$c}];
#c3
set c [expr {$y>0&&$x<$W-1?$c+[string index [lindex $map $y-1] $x+1]:$c}];
#c4
set c [expr {$x>0?$c+[string index [lindex $map $y] $x-1]:$c}];
#c5
set c [expr {$x<$W-1?$c+[string index [lindex $map $y] $x+1]:$c}];
#c6
set c [expr {$y<$H-1&&$x!=0?$c+[string index [lindex $map $y+1] $x-1]:$c}];
#c7
set c [expr {$y<$H-1?$c+[string index [lindex $map $y+1] $x]:$c}];
#c8
set c [expr {$y<$H-1&&$x<$W-1?$c+[string index [lindex $map $y+1] $x+1]:$c}];
append v [lindex $rule "$c0 $c"];
incr x 1;
};
lappend _map $v;
incr y 1;
};
set map $_map;
lappend log [join $map \n];
set nSteps [expr {$nSteps+1}];
};
#it runs simulation
proc ::TCLCELL::run {char0 char1 n} {
# - $char0 and $char1: characters to replace 0 and 1
# - $n: model simulated for n time steps
#map size, its log and steps
variable ::TCLCELL::W;variable ::TCLCELL::H;variable ::TCLCELL::log;variable ::TCLCELL::nSteps;
set i 0;
while {$i<$n} {
::TCLCELL::step;
puts -nonewline stderr "\x1b\[1;1H[string map "0 $char0 1 $char1" [lindex $log $nSteps]]";
after 250;
incr i 1;
};
puts stdout "\n\#===================================================================\n$W X $H\nsteps: $nSteps";
#puts stdout "$W X $H\nsteps: $nSteps";
};
#=== main script ===
#width and height of map
variable ::TCLCELL::W;variable ::TCLCELL::H;
set W $w;set H $h;
#map, log and steps
variable ::TCLCELL::map;variable ::TCLCELL::log;variable ::TCLCELL::nSteps;
#initial value for map data
while {$i<$h} {
set j 0;set v {};
while {$j<$w} {
#random number 1 or 0
append v [expr {2*rand()<1?0:1}];
incr j 1;
};
lappend map $v;
incr i 1;
};
#--- 0th Step ---
lappend log [join $map \n];
#Clearing display
puts stdout "\x1b\[2J";
puts -nonewline stderr "\x1b\[1;1H[string map "0 $char0 1 $char1" [lindex $log $nSteps]]";
after 250;
::TCLCELL::run $char0 $char1 $N;
};
#shell
if {$tcl_interactive<1} {tclCell;};
#*** License ***
#MIT License
#
#Copyright (c) 2019 Yuji Sode
#
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment