aa47e743b1a3040f28b93265dc2eaeff11baf272
4 Placed in the public domain.
6 This code is designed for use with Perlenspiel, by Brian Moriarty,
7 which is released under the terms of the GNU LGPL version 3 or
28 [0, 2], [1, 2], [2, 2],
29 [0, 1], [1, 1], [2, 1],
30 [0, 0], [1, 0], [2, 0]
33 var state
= LEVEL_SELECT
;
36 var current_level
= 1;
37 var current_level_inst
= null;
39 function QueueChange(bead
, sound
) {
43 bead_change
.push(bead
);
48 for (var i
= a
.length
- 1; i
>= 1; --i
) {
49 var j
= PS
.Random(i
) - 1;
58 return a
[PS
.Random(a
.length
) - 1];
61 function CheckExact(pos
) {
62 for (var n
= 1; n
<= 9; ++n
) {
63 var x
= LEVEL_POS
[n
][0];
64 var y
= LEVEL_POS
[n
][1];
65 var on
= PS
.BeadColor(x
, y
) != PS
.COLOR_WHITE
;
66 var should
= pos
.indexOf(n
) >= 0;
67 if ((on
&& !should
) || (!on
&& should
)) {
74 function FollowMe () {
76 PS
.BeadColor(PS
.Random(3) - 1, PS
.Random(3) - 1, PS
.COLOR_BLACK
);
78 this.Press = function (x
, y
) {
79 if (PS
.BeadColor(x
, y
) == PS
.COLOR_BLACK
) {
80 PS
.BeadColor(x
, y
, PS
.COLOR_WHITE
);
85 PS
.BeadColor(PS
.Random(3) - 1, PS
.Random(3) - 1,
87 PS
.AudioPlay(PS
.Xylophone(count
== 3 ? 14 : 13), 0.5);
96 function Enumerate () {
97 this.Press = function (x
, y
) {
98 for (var n
= 1; n
< LEVEL_IDX
[y
][x
]; ++n
) {
99 if (PS
.BeadColor(LEVEL_POS
[n
][0], LEVEL_POS
[n
][1])
105 if (PS
.BeadColor(x
, y
) == PS
.COLOR_BLACK
) {
108 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
109 if (LEVEL_IDX
[y
][x
] == 9)
111 else if (LEVEL_IDX
[y
][x
] == 3)
112 PS
.AudioPlay(PS
.Xylophone(15), 0.5);
113 else if (LEVEL_IDX
[y
][x
] == 6)
114 PS
.AudioPlay(PS
.Xylophone(16), 0.5);
115 else if (LEVEL_IDX
[y
][x
] > 6)
116 PS
.AudioPlay(PS
.Xylophone(15), 0.5);
117 else if (LEVEL_IDX
[y
][x
] > 3)
118 PS
.AudioPlay(PS
.Xylophone(14), 0.5);
120 PS
.AudioPlay(PS
.Xylophone(13), 0.5);
126 var repeatorder
= Shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9]).slice(0, 6);
128 for (var n
= 0; n
< repeatorder
.length
; ++n
) {
129 QueueChange([[PS
.COLOR_BLACK
, repeatorder
[n
]]],
130 [PS
.Xylophone(2 + n
)]);
132 this.Press
= function Press (x
, y
) {
133 var n
= repeatorder
.shift();
134 if (LEVEL_IDX
[y
][x
] == n
) {
135 PS
.BeadColor(x
, y
, PS
.COLOR_GREEN
);
136 if (repeatorder
.length
== 0) {
139 PS
.AudioPlay(PS
.Xylophone(9 + repeatorder
.length
), 0.5);
140 PS
.AudioPlay(PS
.Xylophone(9 + repeatorder
.length
), 0.5);
149 function TickMissing() {
157 repeatorder
= Shuffle([1, 2, 3, 4, 5, 6, 7, 8, 9]).slice(0, 6);
158 repeatorder
= Shuffle(repeatorder
.concat(repeatorder
));
159 for (var n
= 0; n
< repeatorder
.length
; ++n
) {
160 if (d
[repeatorder
[n
]]) {
161 QueueChange([[PS
.COLOR_WHITE
, repeatorder
[n
]]],
162 [PS
.Xylophone(15 - n
)]);
164 d
[repeatorder
[n
]] = true;
165 QueueChange([[PS
.COLOR_RED
, repeatorder
[n
]]],
166 [PS
.Xylophone(13 + n
)]);
170 for (var n
= 1; n
<= 9; ++n
)
171 if (repeatorder
.indexOf(n
) < 0)
172 missing_valid
.push(n
);
174 this.Press = function (x
, y
) {
175 if (missing_valid
.indexOf(LEVEL_IDX
[y
][x
]) < 0) {
178 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
179 if (CheckExact(missing_valid
)) {
183 PS
.AudioPlay(PS
.Xylophone(count
== 2 ? 14 : 13), 0.5);
189 function ThreeRow () {
195 function Generate() {
196 third_row
= Shuffle(Choose([
197 [1, 2, 3], [4, 5, 6], [7, 8, 9],
198 [1, 4, 7], [2, 5, 8], [3, 6, 9],
199 [1, 5, 9], [3, 5, 7]]));
200 QueueChange([[PS
.COLOR_BLACK
, third_row
[0]]], [PS
.Xylophone(13)]);
201 QueueChange([[PS
.COLOR_BLACK
, third_row
[1]]], [PS
.Xylophone(13)]);
204 this.Press = function (x
, y
) {
205 if (LEVEL_IDX
[y
][x
] == third_row
[2]) {
207 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
208 PS
.Clock(PS
.Clock());
212 PS
.AudioPlay(PS
.Xylophone(14), 0.5);
213 QueueChange([[PS
.COLOR_GREEN
, third_row
[2]],
214 [PS
.COLOR_GREEN
, third_row
[1]],
215 [PS
.COLOR_GREEN
, third_row
[0]]],
217 QueueChange([[PS
.COLOR_WHITE
, third_row
[2]],
218 [PS
.COLOR_WHITE
, third_row
[1]],
219 [PS
.COLOR_WHITE
, third_row
[0]]]);
229 function SudokuRow () {
235 function Generate() {
236 sudoku_row
= Shuffle(
237 Choose([[1, 8, 6], [4, 8, 3], [4, 2, 9], [7, 2, 6]]));
238 QueueChange([[PS
.COLOR_RED
, sudoku_row
[0]]],
240 QueueChange([[PS
.COLOR_RED
, sudoku_row
[1]]],
244 this.Press = function (x
, y
) {
245 if (LEVEL_IDX
[y
][x
] == sudoku_row
[2]) {
247 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
251 PS
.AudioPlay(PS
.Xylophone(13), 0.5);
252 QueueChange([[PS
.COLOR_GREEN
, sudoku_row
[2]],
253 [PS
.COLOR_GREEN
, sudoku_row
[1]],
254 [PS
.COLOR_GREEN
, sudoku_row
[0]]],
256 QueueChange([[PS
.COLOR_WHITE
, sudoku_row
[2]],
257 [PS
.COLOR_WHITE
, sudoku_row
[1]],
258 [PS
.COLOR_WHITE
, sudoku_row
[0]]]);
269 QueueChange([[PS
.COLOR_BLACK
, 1]], ["perc_hihat_closed"]);
270 QueueChange([[PS
.COLOR_WHITE
, 1],
271 [PS
.COLOR_BLACK
, 4]], ["perc_hihat_closed"]);
272 QueueChange([[PS
.COLOR_WHITE
, 4],
273 [PS
.COLOR_BLACK
, 7]], ["perc_hihat_closed"]);
274 QueueChange([[PS
.COLOR_WHITE
, 7]]);
276 QueueChange([[PS
.COLOR_BLACK
, 2],
278 [PS
.COLOR_BLACK
, 8]],
280 QueueChange([[PS
.COLOR_GREEN
, 2],
282 [PS
.COLOR_GREEN
, 8]],
284 QueueChange([[PS
.COLOR_WHITE
, 2],
286 [PS
.COLOR_WHITE
, 8]]);
289 this.Press = function (x
, y
) {
290 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
) {
291 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
293 PS
.BeadColor(x
, y
, PS
.COLOR_WHITE
);
296 if (count
== 4 && ApproveIfExact([7, 9, 4, 5, 6, 3]))
298 if (count
== 7 && (CheckExact([7, 8, 9, 6, 3])
299 || CheckExact([7, 8, 9, 6, 2]))) {
304 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
) {
305 PS
.AudioPlay(PS
.Xylophone(10), 0.5);
307 PS
.AudioPlay(PS
.Xylophone(13), 0.3);
314 QueueChange([[PS
.COLOR_BLACK
, 1]], [PS
.Xylophone(13)]);
315 QueueChange([[PS
.COLOR_GREEN
, 1]], [PS
.Xylophone(14)]);
316 QueueChange([[PS
.COLOR_BLACK
, 1]]);
317 QueueChange([[PS
.COLOR_BLACK
, 4]], [PS
.Xylophone(13)]);
318 QueueChange([[PS
.COLOR_BLACK
, 7]], [PS
.Xylophone(13)]);
320 QueueChange([[PS
.COLOR_GREEN
, 1],
322 [PS
.COLOR_GREEN
, 7]],
324 QueueChange([[PS
.COLOR_BLACK
, 1],
326 [PS
.COLOR_BLACK
, 7]]);
329 this.Press = function (x
, y
) {
330 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
) {
331 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
333 PS
.BeadColor(x
, y
, PS
.COLOR_WHITE
);
337 && (ApproveIfExact([1, 4, 7, 2, 5, 3], PS
.COLOR_BLACK
)
338 || ApproveIfExact([1, 4, 7, 8, 5, 3], PS
.COLOR_BLACK
))) {
340 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
)
341 PS
.AudioPlay(PS
.Xylophone(10), 0.3);
343 PS
.AudioPlay(PS
.Xylophone(13), 0.5);
344 } else if (count
== 4 && CheckExact([1, 2, 3, 4, 5, 6, 7, 8, 9])) {
347 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
)
348 PS
.AudioPlay(PS
.Xylophone(10), 0.3);
350 PS
.AudioPlay(PS
.Xylophone(13), 0.5);
355 function ApproveIfExact(a
, color
) {
357 color
= PS
.COLOR_WHITE
;
361 for (var n
= 0; n
< a
.length
; ++n
) {
362 green
.push([PS
.COLOR_GREEN
, a
[n
]]);
363 white
.push([color
, a
[n
]]);
365 QueueChange(green
, [PS
.Xylophone(14)]);
367 PS
.Clock(PS
.Clock());
368 if (PS
.StatusText() != "…")
378 QueueChange([[PS
.COLOR_BLACK
, 5]], [PS
.Xylophone(13)]);
379 QueueChange([[PS
.COLOR_GREEN
, 5]], [PS
.Xylophone(14)]);
380 QueueChange([[PS
.COLOR_WHITE
, 5]]);
381 QueueChange([[PS
.COLOR_BLACK
, 1]], [PS
.Xylophone(13)]);
382 QueueChange([[PS
.COLOR_BLACK
, 9]], [PS
.Xylophone(13)]);
383 QueueChange([[PS
.COLOR_GREEN
, 1],
384 [PS
.COLOR_GREEN
, 9]], [PS
.Xylophone(14)]);
385 QueueChange([[PS
.COLOR_WHITE
, 1],
386 [PS
.COLOR_WHITE
, 9]]);
389 this.Press = function (x
, y
) {
390 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
) {
391 PS
.BeadColor(x
, y
, PS
.COLOR_BLACK
);
393 PS
.BeadColor(x
, y
, PS
.COLOR_WHITE
);
397 if (ApproveIfExact([1, 5, 9]) || ApproveIfExact([7, 5, 3]))
401 if (ApproveIfExact([1, 3, 7, 9]))
405 if (ApproveIfExact([1, 3, 5, 7, 9]))
409 if (CheckExact([1, 2, 3, 7, 8, 9])
410 || CheckExact([1, 4, 7, 3, 6, 9])) {
416 if (PS
.BeadColor(x
, y
) == PS
.COLOR_WHITE
) {
417 PS
.AudioPlay(PS
.Xylophone(14), 0.5);
419 PS
.AudioPlay(PS
.Xylophone(13), 0.3);
437 function Reset(color
) {
438 if (max_level
< 10 && PS
.StatusText() != "?")
440 if (max_level
== 10 && PS
.StatusText() != ".")
445 PS
.BeadColor(PS
.ALL
, PS
.ALL
, color
);
449 Reset(PS
.COLOR_GREEN
);
452 if (max_level
< current_level
) {
453 max_level
= current_level
;
454 if (max_level
== 10) {
455 setTimeout(function() {
456 PS
.AudioPlay(PS
.Xylophone(25), 0.5)
458 setTimeout(function() {
459 PS
.AudioPlay(PS
.Xylophone(30), 0.5)
461 setTimeout(function() {
462 PS
.AudioPlay(PS
.Xylophone(30), 0.5)
464 setTimeout(function() {
465 PS
.AudioPlay(PS
.Xylophone(31), 0.5)
467 setTimeout(function() {
468 PS
.AudioPlay(PS
.Xylophone(37), 0.5)
471 PS
.AudioPlay(PS
.Xylophone(34), 0.5);
472 PS
.AudioPlay(PS
.Xylophone(38), 0.5);
473 PS
.AudioPlay(PS
.Xylophone(39), 0.5);
476 PS
.AudioPlay(PS
.Xylophone(34), 0.5);
477 PS
.AudioPlay(PS
.Xylophone(38), 0.5);
478 PS
.AudioPlay(PS
.Xylophone(39), 0.5);
484 PS
.AudioPlay(PS
.Xylophone(2), 0.5);
485 PS
.AudioPlay(PS
.Xylophone(8), 0.5);
486 PS
.AudioPlay(PS
.Xylophone(22), 0.5);
491 PS
.Init = function (options
) {
492 var path
= window
.location
.href
;
493 PS
.AudioPath(path
.substr(0, path
.lastIndexOf("/")) + "/audio/");
497 for (var i
= 1; i
< 39; ++i
)
498 PS
.AudioLoad(PS
.Xylophone(i
));
499 PS
.AudioLoad("perc_hihat_closed");
502 function StartLevel(level
) {
503 if (level
> max_level
)
505 PS
.AudioPlay(PS
.Xylophone(1), 0.5);
506 Reset(PS
.COLOR_WHITE
);
507 current_level
= level
;
508 current_level_inst
= new LEVELS
[current_level
]();
512 function LevelSelect() {
513 Reset(PS
.COLOR_WHITE
);
514 for (var n
= 1; n
<= 9; ++n
) {
515 var x
= LEVEL_POS
[n
][0];
516 var y
= LEVEL_POS
[n
][1];
518 PS
.BeadColor(x
, y
, PS
.COLOR_VIOLET
);
519 else if (n
< max_level
)
520 PS
.BeadColor(x
, y
, PS
.COLOR_BLUE
);
523 PS
.BeadColor(PS
.ALL
, PS
.ALL
, PS
.COLOR_BLUE
);
524 state
= LEVEL_SELECT
;
527 PS
.Click = function (x
, y
, data
, options
) {
528 if (PS
.Clock() > 0 && bead_change
.length
)
532 StartLevel(LEVEL_IDX
[y
][x
]);
535 current_level_inst
.Press(x
, y
);
541 StartLevel(current_level
);
548 PS
.Release = function (x
, y
, data
, options
) {
551 PS
.Enter = function (x
, y
, data
, options
) {
552 if (state
== LEVEL_SELECT
&& PS
.BeadColor(x
, y
) != PS
.COLOR_WHITE
) {
553 PS
.AudioPlay( "fx_click" , 0.5);
557 PS
.Leave = function (x
, y
, data
, options
) {
560 PS
.KeyDown = function (key
, shift
, ctrl
, options
) {
561 if (ctrl
&& key
== 32) {
566 case PS
.KEYPAD_1
: case 49: PS
.Click(0, 2); break;
567 case PS
.KEYPAD_2
: case 50: PS
.Click(1, 2); break;
568 case PS
.KEYPAD_3
: case 51: PS
.Click(2, 2); break;
569 case PS
.KEYPAD_4
: case 52: PS
.Click(0, 1); break;
570 case PS
.KEYPAD_5
: case 53: PS
.Click(1, 1); break;
571 case PS
.KEYPAD_6
: case 54: PS
.Click(2, 1); break;
572 case PS
.KEYPAD_7
: case 55: PS
.Click(0, 0); break;
573 case PS
.KEYPAD_8
: case 56: PS
.Click(1, 0); break;
574 case PS
.KEYPAD_9
: case 57: PS
.Click(2, 0); break;
575 case PS
.KEY_ESCAPE
: LevelSelect(); break;
579 PS
.KeyUp = function (key
, shift
, ctrl
, options
) {
582 PS
.Wheel = function (dir
, options
) {
585 PS
.Tick = function (options
) {
586 var beads
= bead_change
.shift();
588 if (PS
.StatusText() != "…")
590 for (var n
= 0; n
< beads
.length
; ++n
) {
592 var x
= LEVEL_POS
[bead
[1]][0];
593 var y
= LEVEL_POS
[bead
[1]][1];
594 PS
.BeadColor(x
, y
, bead
[0]);
598 var sound
= sounds
.shift();
600 for (var n
= 0; n
< sound
.length
; ++n
) {
601 PS
.AudioPlay(sound
[n
], 0.5);
605 if (bead_change
.length
== 0 && PS
.StatusText() != "?")