xref: /vim-8.2.3635/runtime/macros/life/life.vim (revision 2c7f8c57)
1" Macros to play Conway's Game of Life in vi
2" Version 1.0m: edges wrap
3" by Eli-the-Bearded Benjamin Elijah Griffin <[email protected]>
4" Sept 1996
5" This file may be free distributed so long as these credits remain unchanged.
6"
7" Modified by Bram Moolenaar ([email protected]), 1996 Sept 10
8" - Made it quite a bit faster, but now needs search patterns in the text
9" - Changed the order of mappings to top-down.
10" - Made "g" run the whole thing, "C" run one generation.
11" - Added support for any uppercase character instead of 'X'
12"
13" Rules:
14"   If a germ has 0 or 1 live neighbors it dies of loneliness
15"   If a germ has 2 or 3 live neighbors it survives
16"   If a germ has 4 to 8 live neighbors it dies of starvation
17"   If an empty box has 3 live neighbors a new germ is born
18"
19"   A new born germ is an "A".	Every generation it gets older: B, C, etc.
20"   A germ dies of old age when it reaches "Z".
21"
22" Notice the rules do not mention edges. This version has the edges wrap
23" around. I have an earlier version that offers the option of live edges or
24" dead edges. Email me if you are interested. -Eli-
25"
26" Note: This is slow!  One generation may take up to ten minutes (depends on
27" your computer and the vi version).
28"
29" Quite a lot of the messy stuff is to work around the vi error "Can't yank
30" inside global/macro".  Still doesn't work for all versions of vi.
31"
32" To use these macros:
33"
34" vi		start vi/vim
35"
36" :so life.mac	Source this file
37"
38" g		'g'o!  runs everything until interrupted: "IR".
39"
40" I		Initialize everything. A board will be drawn at the end
41"		of the current buffer. All line references in these macros
42"		are relative to the end of the file and playing the game
43"		can be done safely with any file as the current buffer.
44"
45"	Change the left field with spaces and uppercase letters to suit
46"	your taste.
47"
48" C		'C'ompute one generation.
49" +		idem, time running one generation.
50" R		'R'un 'C'ompute until interrupted.
51" i<nr><Esc>z	Make a number the only thing on the current line and use
52"		'z' to time that many generations.
53"
54" Time to run 30 generations on my 233 AMD K6 (FreeBSD 3.0):
55"   vim   5.4 xterm	51 sec
56"   gvim  5.4 Athena	42 sec
57"   gvim  5.4 Motif	42 sec
58"   gvim  5.4 GTK	50 sec
59"   nvi   1.79 xterm	58 sec
60"   vi	  3.7 xterm	2 min 30 sec
61"   Elvis 2.1 xterm	7 min 50 sec
62"   Elvis 2.1 X11	6 min 31 sec
63"
64" Time to run 30 generations on my 850 AMD Duron (FreeBSD 4.2):
65"   vim   5.8   xterm    21 sec
66"   vim   6.0   xterm    24 sec
67"   vim   6.0   Motif    32 sec
68"   nvi   1.79  xterm	 29 sec
69"   vi    3.7   xterm    32 sec
70"   elvis 2.1.4 xterm    34 sec
71"
72" And now the macros, more or less in top-down order.
73"
74"  ----- macros that can be used by the human -----
75"
76" 'g'o: 'I'nitialize and then 'R'un 'C'ompute recursively (used by the human)
77map g IR
78"
79"
80" 'R'un 'C'ompute recursively (used by the human and 'g'o)
81map R CV
82" work around "tail recursion" problem in vi, "V" == "R".
83map V R
84"
85"
86" 'I'nitialize the board (used by the human and 'g'o)
87map I G)0)0)0)0)1)0)0)2)0)0)0)0,ok,-11k,-,R,IIN
88"
89"
90" 'C'ompute next generation (used by the human and others)
91map C T>>>>>>>>B&
92"
93"
94" Time running one generation (used by the human)
95map + <1C<2
96"
97"
98" Time running N generations, where N is the number on the current line.
99" (used by the human)
100map z ,^,&,*,&<1,*<2
101"
102"  ----- END of macros that can be used by the human -----
103"
104"  ----- Initialisation -----
105"
106map ,- :s/./-/g
107map ,o oPut 'X's in the left box, then hit 'C' or 'R'
108map ,R 03stop
109"
110" Write a new line (used by 'I'nitialize board)
111" In remembrance of John Conway, 26 December 1937 – 11 April 2020.
112map )0 o-                    --....................--....................-
113map )1 o-    JOHN CONWAY     --....................--....................-
114map )2 o-       LIVES        --....................--....................-
115"
116"
117" Initialisation of the pattern/command to execute for working out a square.
118" Pattern is: "#<germ><count>"
119" where <germ>   is " " if the current germ is dead, "X" when living.
120"       <count>  is the number of living neighbours (including current germ)
121"                expressed in X's
122"
123map ,Il8 O#XXXXXXXXXX .`a22lr 
124map ,Id8 o# XXXXXXXX .`a22lr 
125map ,Il7 o#XXXXXXXXX .`a22lr 
126map ,Id7 o# XXXXXXX .`a22lr 
127map ,Il6 o#XXXXXXXX .`a22lr 
128map ,Id6 o# XXXXXX .`a22lr 
129map ,Il5 o#XXXXXXX .`a22lr 
130map ,Id5 o# XXXXX .`a22lr 
131map ,Il4 o#XXXXXX .`a22lr 
132map ,Id4 o# XXXX .`a22lr 
133map ,Il3 o#XXXXX .,a
134map ,Id3 o# XXX .`a22lrA
135map ,Il2 o#XXXX .,a
136map ,Id2 o# XX .`a22lr 
137map ,Il1 o#XXX .`a22lr 
138map ,Id1 o# X .`a22lr 
139map ,Il0 o#XX .`a22lr 
140map ,Id0 o#  .`a22lr 
141"
142" Patterns used to replace a germ with its next generation
143map ,Iaa o=AB =BC =CD =DE =EF =FG =GH =HI =IJ =JK =KL =LM =MN =NO =OP =PQ =QR
144map ,Iab o=RS =ST =TU =UV =VW =WX =XY =YZ =Z 
145"
146" Insert the searched patterns above the board
147map ,IIN G?^top
148,Il8,Id8,Il7,Id7,Il6,Id6,Il5,Id5,Il4,Id4,Il3,Id3,Il2,Id2,Il1,Id1,Il0,Id0,Iaa,Iab
149"
150"  ----- END of Initialisation -----
151"
152"  ----- Work out one line -----
153"
154" Work out 'T'op line (used by show next)
155map T G,c2k,!9k,@,#j>2k,$j
156"
157" Work out 'B'ottom line (used by show next)
158map B ,%k>,$
159"
160" Work out a line (used by show next, work out top and bottom lines)
161map > 0 LWWWWWWWWWWWWWWWWWW,rj
162"
163" Refresh board (used by show next)
164map & :%s/^\(-[ A-Z]*-\)\(-[ A-Z]*-\)\(-[.]*-\)$/\2\3\3/
165"
166"
167" Work around vi multiple yank/put in a single macro limitation
168" (used by work out top and/or bottom line)
169map ,$ dd
170map ,% "cp
171map ,! "byy
172map ,@ "cyy
173map ,# "bP
174map ,c c$
175"
176"  ----- END of Work out one line -----
177"
178"  ----- Work out one square -----
179"
180" The next three work out a square: put all nine chars around the current
181" character on the bottom line (the bottom line must be empty when starting).
182"
183" 'W'ork out a center square (used by work out line)
184map W makh,3`ah,3`ajh,3(
185"
186"
187" Work out a 'L'eft square (used by work out line)
188map L makf-h,1`ak,2`af-h,1`a,2`ajf-h,1`aj,2(
189"
190"
191" Work out a 'R'ight square (used by work out line)
192map ,r makh,2`akF-l,1`ah,2`aF-l,1`ajh,2`ajF-l,1(
193"
194" 'M'ove a character to the end of the file (used by all work out square
195" macros)
196"
197map ,1 y G$p
198map ,2 2y G$p
199map ,3 3y G$p
200"
201"
202"  ----- END of Work out one square -----
203"
204"  ----- Work out one germ -----
205"
206" Generate an edit command that depends on the number of living in the last
207" line, and then run the edit command. (used by work out square).
208" Leaves the cursor on the next character to be processed.
209"
210map ( ,s,i,X0i?^#A 
2110,df.l,Y21h
212"
213" Delete 's'paces (deads);
214" The number of remaining characters is the number of living neighbours.
215map ,s :.g/ /s///g
216"
217" Insert current character in the last line
218map ,i `ay GP
219"
220" Replace any uppercase letter with 'X';
221map ,X :.g/[A-Z]/s//X/g
222"
223" Delete and execute the rest of the line
224map ,d "qd$@q
225"
226" Yank and execute the rest of the line
227map ,Y "qy$@q
228"
229" Yank the character under the cursor
230map ,j y
231"
232" Put the current cut buffer after the cursor
233map ,m p
234"
235" Delete the character under the cursor
236map ,n x
237"
238" Replace a character by its next, A --> B,  B --> C, etc.
239map ,a `a,jGi?=,ma
2400,dll,j`a21l,ml,nh
241"
242"  ----- END of Work out one germ -----
243"
244"  ----- timing macros  -----
245"
246" Get current date (used by time a generation)
247map << :r!date
248map <1 G?^top
249O<<
250map <2 G?^top
251k<<
252"
253"
254" Turn number on current line into edit command (used by time N generations)
255map ,^ AiC
256"
257"
258" Delete current line and save current line (used by time N generations)
259map ,& 0"gd$
260"
261"
262" Run saved line (used by time N generations)
263map ,* @g
264"
265"  ----- END of timing macros  -----
266"
267" End of the macros.
268