1 <!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns=
"http://www.w3.org/1999/xhtml">
4 <title>tendrils
</title>
5 <style type=
"text/css">
18 display: inline-block
;
27 <script type=
"text/javascript">
30 switch (arguments
.length
) {
35 if(a
instanceof Array
)
36 return a
[Math
.floor(Math
.random()*a
.length
)];
38 return Math
.random() * a
;
41 return a
+ Math
.random() * (b
- a
);
47 switch (arguments
.length
) {
49 return Math
.floor(Math
.random() * a
);
52 return Math
.floor(a
+ Math
.random() * (b
- a
));
57 if(!('contains' in Array
.prototype))
58 Array
.prototype.contains = function(needle
){
60 while(i
-->0)if(this[i
] == needle
)return true;
64 var maxchannel
= 0xff;
65 function Color(r
, g
, b
) {
69 else if (a
> maxchannel
) return maxchannel
;
74 a
= Math
.floor(a
).toString(16);
75 return a
.length
== 1 ? '0' + a
: a
;
82 // make color darker - k between 0 and 1
83 this.dim = function (k
) {
84 return new Color(r
* k
, g
* k
, b
* k
);
87 // randomly change color - k between 0 and 1
88 this.deviate = function (k
) {
89 return new Color(rnd(r
* (1 - k
), r
* (1 + k
)), rnd(g
* (1 - k
), g
* (1 + k
)), rnd(b
* (1 - k
), b
* (1 + k
)));
92 this.toString = function () {
93 return '#' + octet(r
) + octet(g
) + octet(b
);
97 Color
.random = function () {
102 var int = rnd(.5, .7);
109 case 0: r
= (int - wg
* g
- wb
* b
) / wr
;
111 case 1: g
= (int - wr
* r
- wb
* b
) / wg
;
113 case 2: b
= (int - wg
* g
- wr
* r
) / wb
;
117 return new Color(r
* maxchannel
, g
* maxchannel
, b
* maxchannel
);
120 function mkArray(n
, newvalfn
) {
125 map
.push(newvalfn(i
));
131 function mkMatrix(n
, m
, newvalfn
) {
138 while (++j
< m
) row
.push(newvalfn(i
, j
));
146 function arci(co
, r
, a
) {
147 return [Math
.round(co
[0] + r
* Math
.sin(2 * Math
.PI
* a
)), Math
.round(co
[1] + r
* Math
.cos(2 * Math
.PI
* a
))];
150 var dirs2n
= [[-1, -1], [-1, 0], [0, 1], [1, 0], [1, -1], [0, -1]];
151 var dirs2n1
= [[-1, 0], [-1, 1], [0, 1], [1, 1], [1, 0], [0, -1]];
153 var numdirs
= dirs2n
.length
;
155 function getDir(id
, i
, j
) {
156 if (id
< 0 || id
> dirs2n
.length
) id
= rndi(dirs2n
.length
);
158 var dir
= (i
% 2) ? dirs2n1
[id
] : dirs2n
[id
];
163 // getDir = function (id, i, j) {
164 // if (id < 0 || id > numdirs) id = rndi(numdirs);
166 // return [[-1, 0], [0, 1], [1, 0], [0, -1]][id];
169 var allColor
= Color
.random();
170 console
.log(allColor
.toString());
172 var Walker = function (coord
, dir
, power
) {
177 this.fill
= allColor
.deviate(.2);
180 function constant(val
){return function(){return val
}}
181 function args(){return [].join
.call(arguments
, 'x')}
183 var t
= document
.getElementById('target');
187 var h
= Math
.floor(w
/ aspect
);
189 var empty
= new Color(0,0,0);
191 function renderMap() {
192 var map
= mkMatrix(h
, w
, constant(empty
));
194 var getValidNext = function (coord
, dirId
) {
195 var dir
= getDir(dirId
, coord
[0], coord
[1]);
197 var i
= coord
[0] + dir
[0];
198 var j
= coord
[1] + dir
[1];
200 return (i
>= 0 && j
>= 0 && i
< h
&& j
< w
&& map
[i
][j
] == empty
)
205 var tryNewDir = function (i
, j
, fn
) {
208 var dir
= walker
.dir
;
210 while (retr
-- > 0 && next
== null) {
211 var dir
= rndi(numdirs
);
214 next
= getValidNext([i
, j
], dir
);
220 var branchSmall
= .2;
224 var numwalkers
= numdirs
*2;
225 var fillfactor
= .25;
226 var startingPower
= Math
.round(w
* h
* fillfactor
/ numwalkers
);
228 var o
= [Math
.floor(h
/ 2), Math
.round(w
/ 2 + w
/ 8)];
229 var makeWalker = function (i
) { var dir
= getDir(i
, o
[0], o
[1]); return new Walker([o
[0] + dir
[0], o
[1] + dir
[1]], i
, startingPower
) };
231 var walkers
= mkArray(numwalkers
/ 2, makeWalker
).concat((function () { o
= [Math
.floor(h
/ 2), Math
.round(w
/ 2 - w
/ 8)]; allColor
= Color
.random(); return mkArray(numwalkers
/ 2, makeWalker
) })());
236 while (walker
= walkers
.pop()) {
241 if (walker
.power
<= 0) {
242 map
[i
][j
] = walker
.fill
.dim(.9);
243 --walker
.power
; // dead will have -1;
247 map
[i
][j
] = walker
.fill
;
251 var loan
= Math
.round(rnd(pool
));
252 walker
.power
+= loan
;
258 if (rnd() < .1) { // random change of direction
259 nextdir
= tryNewDir(i
, j
);
262 if (next
) walker
.dir
= dir
;
266 next
= getValidNext([i
, j
], walker
.dir
);
268 if (!next
) { // forced change of direction
269 nextdir
= tryNewDir(i
, j
);
273 if (next
) walker
.dir
= dir
;
280 walker
.fill
= walker
.fill
.dim(.97);
283 walkers
.unshift(walker
);
285 var shareRatio
= rnd() < pbig
? branchBig
: branchSmall
;
286 var share
= Math
.round(rnd(walker
.power
* shareRatio
));
289 var nextdir
= tryNewDir(i
, j
, function (dir
) { return dir
!= walker
.dir
&& dir
!= walker
.dir
});
293 if (next
) { // add new spawn to the end
294 walkers
.push({ i
: next
.i
, j
: next
.j
, dir
: dir
, power
: share
, parent
: walker
, fill
: walker
.fill
});
295 walker
.power
-= share
;
302 if (walker
.parent
.power
== -1) {
303 walker
.parent
.power
= walker
.power
;
304 walkers
.push(walker
.parent
);
307 walker
.parent
.power
+= walker
.power
;
312 pool
+= walker
.power
;
321 console
.log('wasted: ' + pool
);
327 var map
= renderMap();
329 var text
= ['<div class="field">'];
331 for (var i
= 0; i
< h
; ++i
) {
332 if (i
% 2) text
.push('<div class="row odd">');
333 else text
.push('<div class="row">');
335 for (var j
= 0; j
< w
; ++j
) {
336 text
.push('<div class="cell" style="background-color:' + map
[i
][j
] + '"></div>');
343 return text
.join('');
346 t
.innerHTML
= render();