[SCRIPT]Game of Life in /View
[1/7] from: coussement::c::itc::mil::be at: 4-May-2001 11:26
hi list:
Just for the fun of learning /View, I've just hack a *Game of Life* ...
Thanks again to Anton for helping me for the dynamic refresh of the panel.
Just Copy&Paste and enjoy it !
<script>
rebol [
title: "Game of Life"
date: 03-may-2001
file: %gol.r
author: "C. COUSSEMENT"
email: [coussement--c--itc--mil--be]
comment: {Game of Life is a cellular automaton on an infinite quadratic
grid.
Each grid cell is either alive/on or dead/off.
The new state of each cell is computed in discrete timesteps
and is
determinated by it's old state and the sum of the alive cells
among
its surrounding 8 nearest neighbours cells. All these changes
are
simultaneously over the whole, infinite grid! - which can be
only simulated !
The Game of Life rules let a cell in the next generation only
alive if
a living cell is either surrounded by either 2 or 3 alive
cells, the
*survive condition*, or a dead cell flips into the alive state
in the
next generation if it is surrounded by exactly 3 living cells,
the *borne
condition*. Otherwise it dies or stays dead.
Therefore a given initial pattern, a collection of alive cells
in a
universe of dead cells, develops according to these rules over
the
generations and produces various configurations.
These special rules were invented 1970 by the mathematician
J.H.
Conway to garanty that the cellular automaton is on the
boundary
between unbounded growth and decay into dullness. It was
proven that
it's chaotic behaviour is unpredictable and it could be used
to build
an universal turing-machine and even an universal constructor.
One
of the important open problems is whether a sufficient large
random
populated universe will develop selforganization structures.
}
usage: {
>> do %gol.r
*ESC*
>> unview
A dimension of 10x10 works fast enough on a P233 under WinNT4
}
]
init-map: func [
"set initial pattern"
max-x [integer!]
max-y [integer!]
/local x y map
][
map: make block! []
for x 1 max-x 1 [
;random/seed now
for y 1 max-y 1 [
append map to-integer rejoin [x y]
append/only map to-block pick reduce [true false] random 2
]
]
return map
]
kill: func [
"set given cell to dead"
map [block!]
x [integer!]
y [integer!]
][
clear select map to-integer rejoin [x y]
append select map to-integer rejoin [x y] false
return map
]
birth: func [
"set given cell to life"
map [block!]
x [integer!]
y [integer!]
][
clear select map to-integer rejoin [x y]
append select map to-integer rejoin [x y] true
return map
]
alive?: func [
"get cell status"
map [block!]
x [integer!]
y [integer!]
][
return first select map to-integer rejoin [x y]
]
neightboor: func [
"get amount of surronding alive cells"
map [block!]
x [integer!]
y [integer!]
/local lives
][
lives: make integer! 0
if all [(x > 1)(y < max-y)(alive? map (x - 1) (y + 1))][lives: lives +
1]
if all [(x)(y < max-y)(alive? map (x) (y + 1))][lives: lives + 1]
if all [(x < max-x)(y < max-y)(alive? map (x + 1) (y + 1))][lives: lives
+ 1]
if all [(x > 1)(y)(alive? map (x - 1) (y))][lives: lives + 1]
if all [(x < max-x)(y)(alive? map (x + 1) (y))][lives: lives + 1]
if all [(x > 1)(y > 1)(alive? map (x - 1) (y - 1))][lives: lives + 1]
if all [(x)(y > 1)(alive? map (x) (y - 1))][lives: lives + 1]
if all [(x < max-x)(y > 1)(alive? map (x + 1) (y - 1))][lives: lives +
1]
return lives
]
make-generation: func [
"compute status of each cell"
map [block!]
max-x [integer!]
max-y [integer!]
/local x y
][
for x 1 max-x 1 [
for y 1 max-y 1 [
;--- survive condition
if any [((neightboor map x y) < 2)((neightboor map x y) > 3)]
[map: kill map x y]
;--- borne condition
if all[(not alive? map x y)((neightboor map x y) = 3)] [map:
birth map x y]
]
]
return map
]
show-visual: func [
"visualize map"
max-x [integer!]
max-y [integer!]
/local x y main society map
][
;--- initialize map
map: init-map max-x max-y
;--- set layout
lay: [
style amibe box 20x20 black
space 1x1
]
for x 1 max-x 1 [
for y 1 max-y 1 [
append lay 'amibe
]
append lay 'return
]
lay: layout lay
view/new lay
;--- animate
forever [
count: 0
for x 1 max-x 1 [
for y 1 max-y 1 [
count: count + 1
either alive? map x y [
set in pick lay/pane count 'color red
][
set in pick lay/pane count 'color black
]
show pick lay/pane count
]
]
map: make-generation map max-x max-y
]
]
;--- get map dim from user
max-x: to-integer ask "x dimension = "
max-y: to-integer ask "y dimension = "
;--- begin show
show-visual max-x max-y
</script>
Regards,
chr==
[2/7] from: gchiu:compkarori at: 4-May-2001 22:35
On Fri, 4 May 2001 11:26:40 +0200
"CRS - Psy Sel/SPO, COUSSEMENT Christophe, CPN"
<[COUSSEMENT--C--ITC--mil--be]> wrote:
> Just for the fun of learning /View, I've just hack a
> *Game of Life* ...
I don't know if it matters, but 'alive? is already used in
View.
--
Graham Chiu
[3/7] from: arolls:bigpond:au at: 4-May-2001 22:20
It gives me an idea.
It should be possible to use built-in image processing
effects on a small image to do the life calculations
for you (at the same time getting more interesting
colours), then stretching the little image to fit
into your window and slapping a grid on it.
The tricky part is to balance the use of image
processing effects in such a way as to produce a
feedback, "life-like".
Such a system will be much faster too, I expect.
See anim-zoom3.r on my reb-site for a demonstration
of effects used in a feedback loop.
I'll probably give it a go myself.
Actually, you could still use a stretched image
to store your cell state, with different colours
representing different states.
Anton.
[4/7] from: arolls:bigpond:au at: 4-May-2001 22:38
Christophe can enclose his functions in a context so
that the global wordspace won't be cluttered, and
functions like 'alive? won't be redefined.
On a second note, the function
'neightboor
should be 'neighbour or 'neighbor, in English, yes?
Regards,
Anton.
[5/7] from: coussement:c:itc:mil:be at: 4-May-2001 15:03
Thanks for the tip: I did know that.
I don't know if it matters, but I changed the function *alive?* in
*is-alive?*
CU,
chr==
[6/7] from: coussement:c:itc:mil:be at: 4-May-2001 15:07
> Christophe can enclose his functions in a context so
> that the global wordspace won't be cluttered, and
> functions like 'alive? won't be redefined.
[Keep it simple: I just renamed it.]
> On a second note, the function
> 'neightboor
> should be 'neighbour or 'neighbor, in English, yes?
[Oowh, sourry four my pour English ! ;-)) ]
> Regards,
>
> Anton.
[
CU,
chr==
]
[7/7] from: arolls:bigpond:au at: 5-May-2001 1:19
> > Christophe can enclose his functions in a context so
> > that the global wordspace won't be cluttered, and
> > functions like 'alive? won't be redefined.
> [Keep it simple: I just renamed it.]
Fair enough.
> > On a second note, the function
> > 'neightboor
> > should be 'neighbour or 'neighbor, in English, yes?
> [Oowh, sourry four my pour English ! ;-)) ]
Forgiven :)
I wondered if it was close to a word in another
language?
We should make a rebol dialect called 'bad-english.
It should translate bad English into good English.
Then none of us have to worry about spelling
mistakes in our code.