For the next attempt in BetaBlocker bytecode evolution I wanted to favour patterns that had a rhythmic nature by measuring them with this function:
(defn freq [l n] (defn _ [c] (cond (>= (+ c n) (count l)) 0 (= (nth l c) (nth l (+ c n))) (+ 1 (_ (+ c 1))) :else (_ (+ c 1)))) (_ 0))
Which looks for repeating values spaced apart by “n” positions, so (freq ‘(100 1 2 3 100 4 5 6 100 7 8 9 100) 4) returns 3, as it finds 3 pairs of equal values (100) distanced by the specified 4 positions.
With this fitness function:
(+ (* 50 (count (num-unique res))) ; unique notes are very good (freq res 4) ; equal notes every 4 beats are good (freq res 6)) ; equal notes every 6 beats are good
We favour rhythmic components of 4 or 6 beats and boost the uniqueness score by multiplying it by 50. After some generations, we get a high scoring individual: 23 23 13 22 7 12 17 20 12 23 23 5 0 7 12 3
Which disassembles as:
loop: note ; play & remove top of stack (zero when empty) note ; play & remove top of stack dec ; decrement top of stack dup ; duplicate - pushes a copy of stack top pshi 12 ; push the value pointed at by address at 12 (self read) not ; performs bitwise not on stack top pip 12 ; increment value at address 12 note ; play & remove top of stack note ; play & remove top of stack pshl 0 ; pushes this literal number (the 0 is at address 12) pshi 12 ; push the value pointed at by 12 (self read) jmp loop
This program creates a pattern from 4 separate sources, using all 16 bytes of code:
The result: “0 0 232 255 23 1 232 254 13 2 242 253 22 3 233 252 7 4 248 251 12 5 243 250 17 6 238 249 20 7 235 248 12 8” scores poorly for it’s rhythmic patterns, but it’s probable that this surprising local maxima was found by the early influence of the rhythmic fitness criteria on it’s ancestor populations.
This one was strange enough to warrant dialing into Betablocker DS to see how it actually sounded. Here it is in Hungarian Gypsy scale:
Leave a Reply to dave's blog of art and programming | Betablocker DS code patterns (part 1) Cancel reply