1 " Macros to play Conway's Game of Life in vi
2 " Version 1.0m: edges wrap
3 " by Eli-the-Bearded (eli@netusa.net), Sept 1996
4 " This file may be free distributed so long as these credits remain unchanged.
6 " Modified by Bram Moolenaar (Bram@vim.org), 1996 Sept 10
7 " - Made it quite a bit faster, but now needs search patterns in the text
8 " - Changed the order of mappings to top-down.
9 " - Made "g" run the whole thing, "C" run one generation.
10 " - Added support for any uppercase character instead of 'X'
13 " If a germ has 0 or 1 live neighbors it dies of loneliness
14 " If a germ has 2 or 3 live neighbors it survives
15 " If a germ has 4 to 8 live neighbors it dies of starvation
16 " If an empty box has 3 live neighbors a new germ is born
18 " A new born germ is an "A". Every generation it gets older: B, C, etc.
19 " A germ dies of old age when it reaches "Z".
21 " Notice the rules do not mention edges. This version has the edges wrap
22 " around. I have an earlier version that offers the option of live edges or
23 " dead edges. Email me if you are interested. -Eli-
25 " Note: This is slow! One generation may take up to ten minutes (depends on
26 " your computer and the vi version).
28 " Quite a lot of the messy stuff is to work around the vi error "Can't yank
29 " inside global/macro". Still doesn't work for all versions of vi.
31 " To use these macros:
35 " :so life.mac Source this file
37 " g 'g'o! runs everything until interrupted: "IR".
39 " I Initialize everything. A board will be drawn at the end
40 " of the current buffer. All line references in these macros
41 " are relative to the end of the file and playing the game
42 " can be done safely with any file as the current buffer.
44 " Change the left field with spaces and uppercase letters to suit
47 " C 'C'ompute one generation.
48 " + idem, time running one generation.
49 " R 'R'un 'C'ompute until interrupted.
50 " i<nr><Esc>z Make a number the only thing on the current line and use
51 " 'z' to time that many generations.
53 " Time to run 30 generations on my 233 AMD K6 (FreeBSD 3.0):
54 " vim 5.4 xterm 51 sec
55 " gvim 5.4 Athena 42 sec
56 " gvim 5.4 Motif 42 sec
58 " nvi 1.79 xterm 58 sec
59 " vi 3.7 xterm 2 min 30 sec
60 " Elvis 2.1 xterm 7 min 50 sec
61 " Elvis 2.1 X11 6 min 31 sec
64 " And now the macros, more or less in top-down order.
66 " ----- macros that can be used by the human -----
68 " 'g'o: 'I'nitialize and then 'R'un 'C'ompute recursively (used by the human)
72 " 'R'un 'C'ompute recursively (used by the human and 'g'o)
74 " work around "tail recursion" problem in vi, "V" == "R".
78 " 'I'nitialize the board (used by the human and 'g'o)
79 map I G)0)0)0)0)1)0)0)2)0)0)0)0,ok,-11k,-,R,IIN
82 " 'C'ompute next generation (used by the human and others)
86 " Time running one generation (used by the human)
90 " Time running N generations, where N is the number on the current line.
94 " ----- END of macros that can be used by the human -----
96 " ----- Initialisation -----
99 map ,o oPut 'X's in the left box, then hit 'C' or 'R'
\e
102 " Write a new line (used by 'I'nitialize board)
103 map )0 o- --....................--....................-
\e
104 map )1 o- VIM --....................--....................-
\e
105 map )2 o- LIVES --....................--....................-
\e
108 " Initialisation of the pattern/command to execute for working out a square.
109 " Pattern is: "#<germ><count>"
110 " where <germ> is " " if the current germ is dead, "X" when living.
111 " <count> is the number of living neighbours (including current germ)
114 map ,Il8 O#XXXXXXXXXX .`a22lr
\e
115 map ,Id8 o# XXXXXXXX .`a22lr
\e
116 map ,Il7 o#XXXXXXXXX .`a22lr
\e
117 map ,Id7 o# XXXXXXX .`a22lr
\e
118 map ,Il6 o#XXXXXXXX .`a22lr
\e
119 map ,Id6 o# XXXXXX .`a22lr
\e
120 map ,Il5 o#XXXXXXX .`a22lr
\e
121 map ,Id5 o# XXXXX .`a22lr
\e
122 map ,Il4 o#XXXXXX .`a22lr
\e
123 map ,Id4 o# XXXX .`a22lr
\e
124 map ,Il3 o#XXXXX .,a
\e
125 map ,Id3 o# XXX .`a22lrA
\e
126 map ,Il2 o#XXXX .,a
\e
127 map ,Id2 o# XX .`a22lr
\e
128 map ,Il1 o#XXX .`a22lr
\e
129 map ,Id1 o# X .`a22lr
\e
130 map ,Il0 o#XX .`a22lr
\e
131 map ,Id0 o# .`a22lr
\e
133 " Patterns used to replace a germ with it's next generation
134 map ,Iaa o=AB =BC =CD =DE =EF =FG =GH =HI =IJ =JK =KL =LM =MN =NO =OP =PQ =QR
\e
135 map ,Iab o=RS =ST =TU =UV =VW =WX =XY =YZ =Z
\e
137 " Insert the searched patterns above the board
138 map ,IIN G?^top
\r,Il8,Id8,Il7,Id7,Il6,Id6,Il5,Id5,Il4,Id4,Il3,Id3,Il2,Id2,Il1,Id1,Il0,Id0,Iaa,Iab
140 " ----- END of Initialisation -----
142 " ----- Work out one line -----
144 " Work out 'T'op line (used by show next)
145 map T G,c2k,!9k,@,#j>2k,$j
147 " Work out 'B'ottom line (used by show next)
150 " Work out a line (used by show next, work out top and bottom lines)
151 map > 0 LWWWWWWWWWWWWWWWWWW,rj
153 " Refresh board (used by show next)
154 map & :%s/^\(-[ A-Z]*-\)\(-[ A-Z]*-\)\(-[.]*-\)$/\2\3\3/
\r
157 " Work around vi multiple yank/put in a single macro limitation
158 " (used by work out top and/or bottom line)
166 " ----- END of Work out one line -----
168 " ----- Work out one square -----
170 " The next three work out a square: put all nine chars around the current
171 " character on the bottom line (the bottom line must be empty when starting).
173 " 'W'ork out a center square (used by work out line)
174 map W makh,3`ah,3`ajh,3(
177 " Work out a 'L'eft square (used by work out line)
178 map L makf-h,1`ak,2`af-h,1`a,2`ajf-h,1`aj,2(
181 " Work out a 'R'ight square (used by work out line)
182 map ,r makh,2`akF-l,1`ah,2`aF-l,1`ajh,2`ajF-l,1(
184 " 'M'ove a character to the end of the file (used by all work out square
192 " ----- END of Work out one square -----
194 " ----- Work out one germ -----
196 " Generate an edit command that depends on the number of living in the last
197 " line, and then run the edit command. (used by work out square).
198 " Leaves the cursor on the next character to be processed.
200 map ( ,s,i,X0i?^#
\eA
\x16\x16\r\e0,df.l,Y21h
202 " Delete 's'paces (deads);
203 " The number of remaining characters is the number of living neighbours.
204 map ,s :.g/ /s///g
\x16\r
206 " Insert current character in the last line
209 " Replace any uppercase letter with 'X';
210 map ,X :.g/[A-Z]/s//X/g
\x16\r
212 " Delete and execute the rest of the line
215 " Yank and execute the rest of the line
218 " Yank the character under the cursor
221 " Put the current cut buffer after the cursor
224 " Delete the character under the cursor
227 " Replace a character by it's next, A --> B, B --> C, etc.
228 map ,a `a,jGi?=
\e,ma
\x16\x16\r\e0,dll,j`a21l,ml,nh
230 " ----- END of Work out one germ -----
232 " ----- timing macros -----
234 " Get current date (used by time a generation)
240 " Turn number on current line into edit command (used by time N generations)
241 map ,^ AiC
\x16\x16\x16\e\e
244 " Delete current line and save current line (used by time N generations)
248 " Run saved line (used by time N generations)
251 " ----- END of timing macros -----