NB. Viewing the evolution of the Game of Life NB. Colored by number of neighbors NB. vlife3.ijs NB. Cliff Reiter NB. January 2005 NB. updated for J6.02, October 2011 coinsert 'vclife' NB. locale for vlife.ijs script definitions coinsert 'jgl2' coclass 'vclife' require 'gl2 files' NB. defaults LA_wh=:256 256 LA_mag=:0 NB. auto LA_bor_sz=:100 NB. default border padding size pat_path=: jpath '~temp' NB. path for *.lif patterns im_path=: jpath '~temp' NB. path for reading/writing images LA_save_fseq=: 0 NB. default is not to save a file sequence bor_wh=:30 175 NB. default edge used by windowing system NB. update life pattern lifee=:([:,/1&|.^:(i:1)@|:"2^:2) NB. life expand lifes=:lifee@:(4&{((3:=])+.[*.4:=]) +/) NB. life step (expanded to expended) NB. get color indices associated with a pattern lcolor=: 4&{ * +/ NB. Palettes used for showing the colors LA_pal=:255*1,0,(=i.3), 1 1 3#-.=i.3 LA_pakpal=:256 256 256#. LA_pal NB. General utilities pad=: (+:@[-@+$@]){.([+$@]){. ] NB. pad around an array getpath=: ([: +./\. =&PATHSEP_j_) # ] NB. borrowed from ...extras\util\jadecon.ijs NB. Form menus and buttons LIFE0=: 0 : 0 pc life;pn vlife; menupop "File"; menu new "&New" "" "" ""; menu load "&Load *.lif Pattern" "" "" ""; menusep; menu import "&Import Pattern from Image" "" "" ""; menu export "&Export Pattern to Image" "" "" ""; menu exportsnap "&Export Snapshot" "" "" ""; menu exportfseq "&Export Snapshot Sequence On" "" "" "1"; menu exportfseqoff "&Export Snapshot Sequence Off" "" "" "1"; menusep; menu rand "&Random" "" "" ""; menu ggun "Load &Glider Gun" "" "" ""; menu bhept "Load &B-Heptomino" "" "" ""; menusep; menu exit "&Exit" "" "" ""; menupopz; menupop "Size"; menu size6 "Array &Size 64 64" "" "" ""; menu size7 "Array &Size 128 128" "" "" ""; menu size8 "Array &Size 256 256" "" "" ""; menu size9 "Array &Size 512 512" "" "" ""; menu size10 "Array &Size 1024 1024" "" "" ""; menupopz; menupop "Magnification"; menu mag0 "Auto Magnification" "" "" ""; menu mag1 "Magnification 1" "" "" ""; menu mag2 "Magnification 2" "" "" ""; menu mag3 "Magnification 3" "" "" ""; menu mag4 "Magnification 4" "" "" ""; menu mag5 "Magnification 5" "" "" ""; menu mag6 "Magnification 6" "" "" ""; menu mag7 "Magnification 7" "" "" ""; menu mag8 "Magnification 8" "" "" ""; menu mag9 "Magnification 9" "" "" ""; menupopz; menupop "Expand"; menu expandall "Expand All Borders" "" "" ""; menu expandr "Expand Right" "" "" ""; menu expandl "Expand Left" "" "" ""; menu expandt "Expand Top" "" "" ""; menu expandb "Expand Bottom" "" "" ""; menupopz; menupop "Help"; menu help "&Help" "" "" ""; menu about "&About" "" "" ""; menupopz; cc start button;cn "Start"; setxywhx start 10 10 80 25; cc step button;cn "Step"; setxywhx step 110 10 80 25; cc pause button;cn "Pause"; setxywhx pause 210 10 80 25; cc iter static;cn "Iteration: "; setxywhx iter 310 10 100 25; cc rasterwin isigraph; ) NB. end of menu form LIFE1=: 0 : 0 pas 2 2; pshow; ) NB. run the main life form function life_run=: 3 : 0 LA_blank '' LA_paint_all '' ) NB. paint the current life configuration LA_paint=: 3 : 0 color=.lcolor LAe wd 'psel life' NB. glsel 'rasterwin' NB. glclear '' NB. glmap MM_RAW NB. glwindowext LA_plp_wh wd 'setxywhx rasterwin 0 50 ',":LA_plp_wh t=.0 0 ,LA_plp_wh,,(LA_plp { color){LA_pakpal glpixels t glpaint'' NB. glshow '' ) NB. repaint entire form LA_paint_all=:3 : 0 form_xywh=:wd :: ((12$'20 ')"_) 'psel life;qformx;' wd :: 0: 'pclose;' wd LIFE0 wd 'setxywhx rasterwin 10 45 ',(":LA_plp_wh),';' wd LIFE1 LA_paint '' try. wd 'pmovex ',form_xywh,';pas 2 2;pshow;' catch. wd 'pas 2 2;pshow;' end. ) NB. used to initialize a new nonblank pattern LA_init=:3 : 0 if. LA_mag=0 do. winm=.".wd 'qm;' whav=.(0 1{winm)-bor_wh else. whav=.LA_mag*LA_wh end. szi=.|.LA_wh szo=.<.szi*<./(|.whav)%szi LA_plp=:<(<"0 szi%szo) <.@*&.> <@i."0 szo LA_plp_wh=:|.szo ) NB. initialize a blank pattern LA_blank=: 3 : 0 LAe=: lifee (|.LA_wh) $ 0 LA_init '' LA_iter=:0 setiter '' ) NB. New button creates a blank image life_new_button=: 3 : 0 LA_blank '' LA_paint_all '' ) NB. save current pattern as an image life_export_button=:3 : 0 require '~addons/image3/image3.ijs' fn=.wd 'mbsave "Save Pattern As Image" "',im_path,'" "" "Bmp(*.bmp);Png(*.png)|*.bmp;*.png|All Files(*.*)|*.*"' if. fn-: '' do. return. end. im_path=: getpath fn (LA_pal;lcolor LAe) write_image fn ) NB. read pattern from image life_import_button=:3 : 0 require '~addons/image3/image3.ijs' fn=.wd 'mbopen "Read Image" "',im_path,'" "" "Bmp(*.bmp);Jpeg(*.jpg);Png(*.png)|*.bmp;*.jpg;*.png|All Files(*.*)|*.*"' if. fn-: '' do. return. end. im_path=: getpath fn b=.read_image fn LA_wh=:1 0{$b LAe=: lifee 85 > <./"1 b LA_init '' LA_paint_all '' LA_iter=:0 setiter '' ) NB. save snapshot life_exportsnap_button=:3 : 0 require '~addons/image3/image3.ijs' fn=.wd 'mbsave "Save Current Image As" "',im_path,'" "" "Bmp(*.bmp);Png(*.png)|*.bmp;*.png|All Files(*.*)|*.*"' if. fn-: '' do. return. end. im_path=: getpath fn color=.lcolor LAe (LA_pal;LA_plp { color)write_image fn ) NB. save snapshot sequence life_exportfseq_button=:3 : 0 require '~addons/image3/image3.ijs' LA_fseq_fn=:wd 'mbsave "Save Generations with First File as" "',im_path,'" "" "Bmp(*.bmp);Png(*.png)|*.bmp;*.png|All Files(*.*)|*.*"' if. LA_fseq_fn-: '' do. return. end. if. ''-:fn_num_suffix LA_fseq_fn do. LA_fseq_fn=:(}: '' ch_ext LA_fseq_fn),'0000.',fn_ext LA_fseq_fn end. LA_save_fseq=:1 im_path=: getpath LA_fseq_fn color=.lcolor LAe (LA_pal;LA_plp { color)write_image LA_fseq_fn ) NB. save snapshot sequence life_exportfseqoff_button=:3 : 0 LA_save_fseq=:0 ) NB. utilities for the load_lif utilities get_blocks=:3 : 0 ('#P' E. y)<;._1 y ) read_lif=:3 : 0 bposul=._1&".@}.@}:@>@{. bpat=.'*'&=@}:&>@}. pat=.fread y if. -. 1 e. '#N' E. pat do. wd 'mb error "Error: not a normal Life 1.05 file";' return. end. pb=.|:(bposul;bpat)@:(<;._2)&> get_blocks pat pos=.>{.pb pos=.|."1 pos-"1 <./pos blk=.{:pb max=.>./pos+"1 sblk=.$&>blk LA=.max$0 for_k. i.#pos do. LA=.(>k{blk)(<(k{pos)+&.> <@i."0 k{sblk)}LA end. LA=.LA_bor_sz pad LA LAe=:lifee LA LA_wh=:|.$LA LA_wh ) life_load_button=:3 : 0 require '~addons\image3\image3.ijs' fn=.wd 'mbopen "Load *.lif Pattern" "',pat_path,'" "" "Hensel Life(*.lif)|*.lif|All Files(*.*)|*.*"' pat_path=:getpath fn read_lif fn LA_init '' LA_paint_all '' LA_iter=:0 setiter '' ) NB. load glider gun configuration life_ggun_button=:3 : 0 LAe=:lifee(1 _1*|.LA_wh){.A2 LA_init '' LA_paint_all '' LA_iter=:0 setiter '' ) NB. load B-heptomino configuration life_bhept_button=:3 : 0 LAe=:lifee(|.LA_wh) {. (<.-:($A3)-|.LA_wh){.A3 LA_init '' LA_paint_all '' LA_iter=:0 setiter '' ) NB. create a random configuration life_rand_button=: 3 : 0 LAe=:lifee LAe=:? (|.LA_wh)$2 LA_init '' LA_paint_all '' LA_iter=:0 setiter '' ) NB. Pause life_pause_button=:3 : 0 wd 'timer 0' ) NB. run one step of life life_step_button=:3 : 0 LAe=:lifes LAe LA_iter=:LA_iter+1 if. LA_save_fseq do. color=.lcolor LAe (LA_pal;LA_plp { color)write_image LA_fseq_fn LA_fseq_fn=:nx_fn LA_fseq_fn end. setiter '' LA_paint '' ) NB. run life life_start_button=:3 : 0 life_step_button '' wd 'timer 100' ) NB. draw iteration count on form setiter=: 3 : 0 try. wd 'psel life;set iter "Iteration: ',(": LA_iter),'";' catch. 0 end. ) NB. event used to iterate life sys_timer=: 3 : 0 try. life_step_button '' catch. wd 'timer 0' end. ) NB. close/cancel/ext functions life_close=: 3 : 0 wd 'pclose' ) life_cancel_button=: life_close life_exit_button=: life_close NB. Sample initial configurations NB. A2 is the famous Glider Gun A2=: 10 pad ".;._2] 0 : 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 ) NB. A3 is the b_heptomino A3=:5 pad ".;._2] 0 : 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 ) NB. Change the current LA (life array) Size life_size=:4 : 0 LAe=:(|.x){."2 (<.-:-x+LA_wh){."2 LAe LA_wh=:x LA_init '' LA_paint_all '' ) life_size6_button=: 64 64 & life_size life_size7_button=: 128 128 & life_size life_size8_button=: 256 256 & life_size life_size9_button=: 512 512 & life_size life_size10_button=: 1024 1024 & life_size NB. specific magnification used to create super pixels life_mag=:4 : 0 LA_mag=:x LA_init '' LA_paint_all '' ) life_mag0_button=: 0&life_mag life_mag1_button=: 1&life_mag life_mag2_button=: 2&life_mag life_mag3_button=: 3&life_mag life_mag4_button=: 4&life_mag life_mag5_button=: 5&life_mag life_mag6_button=: 6&life_mag life_mag7_button=: 7&life_mag life_mag8_button=: 8&life_mag life_mag9_button=: 9&life_mag NB. Expand buttons life_expandall_button=:3 : 0 LAe=:LA_bor_sz pad"2 LAe LA_wh=:2 1{$LAe LA_init '' LA_paint_all '' ) life_expandr_button=:3 : 0 LAe=:(LA_bor_sz+{.LA_wh){."1 LAe LA_wh=:2 1{$LAe LA_init '' LA_paint_all '' ) life_expandl_button=:3 : 0 LAe=:(-LA_bor_sz+{.LA_wh){."1 LAe LA_wh=:2 1{$LAe LA_init '' LA_paint_all '' ) life_expandt_button=:3 : 0 LAe=:(-LA_bor_sz+{:LA_wh){."2 LAe LA_wh=:2 1{$LAe LA_init '' LA_paint_all '' ) life_expandb_button=:3 : 0 LAe=:(LA_bor_sz+{:LA_wh){."2 LAe LA_wh=:2 1{$LAe LA_init '' LA_paint_all '' ) NB. Help and about menus help_info=:0 : 0 This is vlife2, a J script providing a colored version of the game of life. Loading/Saving patterns as image files requires the image3 addon for J. Life patterns may be loaded using *.lif (v 1.05) patterns or image files. Obtaining lifep.zip by Al Hensel is highly recomended. ) life_help_button=:3 : 0 wd 'mb "vlife Help " "',help_info,'";' ) about_info=:0 : 0 vlife was written by Cliff Reiter January 2005 ) life_about_button=:3 : 0 wd 'mb "About vlife" "',about_info,'";' ) NB. simple name for main function vlife=:life_run NB. run the function coclass 'base' vlife ''