varanasi ghats
[github]dusk aarti on the ganga, lamps on the steps and diyas on the water
scenes 200×100 15 fps 46 colours, on a canvas 29.3 kB
···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·•·•·•·•···········•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•·•·•·•·•••·•••·•••·•••·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••·•·•· ···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·•·•·•·•···•·······•·•·•·•••·•·•···········•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••••••••••·•·•·•·•·•·•·•••••••••••·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•· ·•·•·•·•·•·•·•···•···•···•···•···•···•···•···•·•·•·•·•·•·•···•···•···•···•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•••·•••·•·•·•·•·•·•·•·•••••••••••••·•·•·•·•·•·•·•·•·· •·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•••·•••·•·•·•••••••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·••••●•●•●•●•●••••••·•·•·•·•·•••••••••••••••••••·•·•·•·•·•·•·•·•· ···•···•·•·•·•·•·•••·•••·•••·•••·•·•·•·•·•••·•••·•••·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•················ •·•·•·••••••••●•••●•••●••••••·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•·•••••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·······················•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·••••• •·•·•·•·•·•·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••·•••·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·••••••••••••••••••●•●•●• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•••·•·•·•·•·•••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••·•••••••••••·•·•·••••••••••••••• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•••·•••·•••·•••·••••••••••••••••●•●•●•●•●•••••••••••●•●•●•••●••••••·•·•·•·•·•·•·•••·•••·•••·•••·•••·••••••••••••••••••••••••••••●•••●••••••••• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••••••••••••••••••••••••·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• •••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·•···•••·•••·•••·•••·•••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•••·•••· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•••·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·••····•·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·•••·•••·•••·•••·•••·•••·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·• •••••••·•••·•••·•••·•••·•••·••··•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·••••••••••••····•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·• ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•···•···•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•••·•••••••·•·•·····•·•·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·····•••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·······•···•·•·•·•·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···· ··•·•·•·•·•·•·•···•···•···•···•···•···························•·•·•·•·•·•·•·•·•·• •••·•••·•••·•••·•••·•••·•••·•····••·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••••••·•••·•••·•••••••••••••••••••••••·····•••••••·•••••••·•·•·•·•·•·•·•·•·•···•···•···•···•·······•·•·•·•·•·•·•••••••••••• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·•·•·•·•·•···················································•·•·•·•·•·•·• •·•·•·•••·•••·•••·•·•·•••·••······•••·•••·•••·•••·•••·•••·•••·•···•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••••••••·····•·•·•·•·•·•·•·•·······················•·•·····················•·•·•••·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ····•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·······························•···············•···•·······•·•·•·•·•·•·•·• •••·•••·•••·•·•·•·•·•·•·•·•·······•·•••·•••·•••·•••••••·•••·•••··••·••••••••••••••••••••••••••••••••••••••••••••••······•••·•·•·•·•·•·•·•···•·······•·•·•·•·•·•·•·•·•••••••·•••·•••·•·•·•·•·•·•·•••••••• ·•·•·•·•···············•·•·• · · ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• · · ··•·•·•·•·•·•·•·•·•••·•••·•·•·•••·•·•·•·•·•·•·•••••••••••·······•···•···•·•·•·•·• •·•·•·•·•·•···•···•·•·•·•·••······•••·•••·•••·•••·•••·•••·•••·····•••·•••·•••••••••••••••·••••••••••••••••••••••••········••••••••••••••••••••●•••●••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ····•·•·•·•·•·•·•·•·•·•·•·•·•·• ····•·•·•·•·•·•·•·•·•·•·•···•·•·•••·•••·•·•·•·•·•·• · · ··•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•••·••••··•·•·•••••·······•••••••••••••••••••••••••••·····•••••••••••••••••••••••·••••••••••••••••••••••••······•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·•·· ··•·•·•·•·•············ ··· ··•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·• · · ··•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·• •·······•••••·••···················••••••••••••••••••••••••••······••••••••••••••••••••••·••••••••••••••••••••••••········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·········•·•·•·•·············· ··· ······•·•·•·•·•·•·•·•·•·•·· ····•·•·•·•·•••·•••·•••·•····••·•••·•••·•••·•••·••· ··· ····•••·•••·•••·•••·•••·•••·•••••••••••••••••••••••·•••·•••·•••·•••·•••·•••·•••·• •·······••••••••············•···•···•···•·•·•·•••••••••••••••······•••••••••••••••••••••····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ···· ····•·•·•·•·······························•·•·•·•·•·•·•···· ··•·•·•·•·•·•·•·•·•·•·• ····•·•·•·•·•·•·•·•·•·•·· · · · ··•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•••·•••·••• ·········••••••·······●•······················••••••••••••••········••••••••••••••••••••····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·················· ···••··••·· ··· ············•••·•••·•••·•·· ··· ·••·•••·•••·•••·•••······••·•••·•••·•••·•••·••· ··· ····•••••••·•••·•••·•••·•••••••••••••••••••••••••••••••·•••·•••·•••·•••·•••·•••·• ········•···•···•···•·●••·●••···•···••··•···•·••••••••••••••········•••••••••••••••••••·····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ································· ··•······•··•·•·•·•·•·•·• ··· ····•••·•••·•••·•••··•· ····•••·•••·•••·•••·•••·· · · · ··•·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·•••·•••·•••·•••·•••·•••·•••·••• ··········•···•···•···•···•···•···•···•···•·●·•·••••••••••••········•••••••••••••••••·•·····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·· ··· ··· ····•·································•···•·•••·•········••·•••·•••·•••·••·•· · · ····•·•••·•••·••••••· · · · ··•••••·•••••••••·•••·•••••••••••••••••••••••••••••••••••·•••·•••·•••·•••••••·• ········•···•·•••···•·●••···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·········•••·•••••••••••••···············•·•••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• · ··· ········●······•●··········•······•·· ··················· ······· ·········••·· · ··· ··· ··· ·••·•••·•••·· · · · ··•·•••·•••·•••·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·••• ··········•·•·•·•·•·•·●••···•···•·●·•·•·•••···•···•···•·•·●···•···················•·•·················•••••••·•••·········••••••··•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·············•···•···•···•···•···•···•···•···•·······•····•·······•····•·· ······· ··· ··· ··· ··· · ····•·•·••••· · · · ··•••·•·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•·•·•·•·••••• ····•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···●····•··············•·······················•·•·········••••••••••••••••••••••●•••●•••●•••●•••●•••●•••●•••••••••••••••••••●•●•●•●•●••• · ·······•●···●·•·•·•····•●···•···•···•···•···•···•·•·•···················· ··· ··· ·•· ··· ··· ··· ··· ··· ··· · · · · · ··••· ·••·•••••·•••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·••• ··········●••·•••·•·•·•·•·●••·•·•·•·•·•·•·•···•···•·●·•●•···•·•·······························································•···••••••••••••●•••●•••●•●•●•●•●•••●•••●•••●••••••••••••••••••••••••••••• ·· ··· ···•●·•·●·•·•·•···••●·•·•·•·•···•···•·•·•···••••●·•········ ······· ········· · ··· ··· ··· ··· ··· ··· ··· ··· · · ··••····•••••••·••••••••••••••●•••●•••●•••••••••••••••••••••••••••••••••••••• ····•·•·•·•·••••●••••••·•••••••·•••·•••••••·•·•·•·•·•●●••••·•·•·····•··························•····························●••···••●•••●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●••••••• ···········•·••●●●••·•·•·•••·•·•·•·•·••●·•·•···•·•·••●●●·•·•···················· ······· ··· ··· ··· ··· · · ··· ··· · · ····••· ····•·····••••●•••●•●•●•●•●•●•●•●•●•••●•••••••••••••••••••••••••••••••• ······•·•·•·••●●●●●••·••••●●•••••·••••●●●·•·•·•·•·•••●·••·•·•·•···•···•·······················································•·············••●•●•●•●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●• ·········•·•·••●●●••·•·••●●●••·•·•·••●●●••·•·•·•·•·••• •••·•·•································ ············································••●•●•●•●•●•●•●•●●●•●•●•●•●•●•●•●•●•●•●•••●•••●•••••••••••• · ····•·•·•·•·•••··●•••••••●●●●•••••••••··•••·•·•·•••·••·••••·•·•·•·•·•·•·•···········•·•·············•···········•·······•·······•···•·•·•·••●•●•●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•·· ··········•·•·· •·•·•·•·• ·••·•·•·•·••··•·•·•·•·•·•·· •·•••••••·······•·•·•·········●·•···········•●•·····•·•·●••·············•·•·•·•●•·•··•••●•●•●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●••····•●•••••••••· · ······•·•·•·•·· •••••·• ·•·••••••·•••·· •·•·•·•·•·•·• ·●●●●••·•·••••••●●•·•·····•·●••••·········•·••●••·······•••·•·•·••●••·•·•·●••···•···•·●•••●●●●●●●●•●●●●●●●●●●••·•·•·●●●•●●●•●•• ··· ••●•●••·•·• ·· ·········• ··• ··•·•·•·· • •·•···••●•● •●•••●•••●•●•· ·•●·•••·•·····•·•·•·•·•·········•·•···•···········•·····•·•······••·····•••·•·•·•·•·•·•·••●·• •·• ··•·•·•·• · · · ··• •···•·· · · · ··•·· · · · · ········• · · ··•·●•●•● ···•●●●•●•●•●•· ·●●·•·•·•·•·· · •·•·•·•·•••••••••···•···•·····•·•·············•·········•·•·•·•·•••·•·•·•···•···•···•····•······················································ ····•••·• ·•· ●•••●•••· ·•●•········ · ··••••••••• ·••·•·•·•·········•·•···· · · ··•·······················•···············•···•··················•••••●••·•···············•···•·······•·•·•·•·•···• •·••••••••· · ●••·•·•·· · •·•·••●•●•● · ·•●•●•●•●••·· ····•·•·•·················•·•·•·•·········•·•·•·•···········•···•···•···••●•••••●·············•·•·•·●●●••••••·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•· ·•·•······ ······••● · ·•●•●●••●•••· · ········••••· •••·•·•·•·········•···•···········•···•·····················•·•·•••·•·•·•••·•·•·······················•·•·•••••·•••••···············•••••••·•···· ········• · ·•●•●•●•●•· · ●·•·•·•·•·•·· ●•●•●•●•●•●•● ··•·•·•·•·•••·•·•·•·······•·•·•·•·········•···•·············•·•·•••••·••••●•••••●•••••●●••●●•·•·•·•••●●●●●●●●●●••••·•·•···•···•···•···●•●•●••••••· ·•·•·•·•· · ••••····· · ···••••••••• ·•●••········· •••·•·●·•·······························•·························•·•·••●●•···•••···•••••••·•·•·•·••●●●●●•●●••●•●••·•·······················•·•·• •·••••••· · ······•·●•● ·•●•●•●•●•●···· ····••●•••••• ·•··•···•···•·•·•···········•···•·•·•·•·•·························•••••••●●••···•·····•·•·•·••••••••●●●●●●●•● ●•●●●••••·•···•·················•·•• ·· ······· ••••••●••• •·········••• ••••••••······ •••·•·•·•······ ········•·•·•·●·························•••·•·••●●•·•·•·•••···········•·•·••••••••●•●•••••••·•●•●●●••·······••●•••●••••·····•●●•• ···•••••• · ·•••●●··•·· ···•●•●•●•••●•· ·······••••·•·•·•·•·•·······•···•••·•••••••·•••·•·······•·•••••·•·•·•·••●•••••••●••·•·•·•···········•·•·••••••••●•●●●●●●●●● •●●●●●●•●••••••••••·•·•·•·•·•·•·●••• ·•·•·•·•· · ·······•••· ••••••••····· ·•••••••••••· ··· ··················•·•·•·•·•·•••·················•·•·•·●••·········· ··· ··· ··········•·•·••••••●●●••••••••·•••·•·•·······•••••••••••••••••••·· •·•······ · ·•••••••••· · ·······••·•·•·•·•·······•·•·•·•·•·•·•·······•·······•···•···•·•·•·•·•···•···•···•···•·•·•···•·•·•···•···········••●•●•●••••••···•·· •••••●• •●●•●•●•●•••●•●•●•●•●•••●•••●•●•●• · ····••· ••••••··· ··••••••••••····· ··•·•·•·•·•••·●••·•···························•·•·•·•·························•···•••·•·······•·••●•●•●••••·· · · · ····●••••••••••••••·•••·•·•·•·•·••●•• •••·••••• · ······•·•·•·•·•·•·•·······•·•·•·•·•·•••·••●•••●••••·•·•·•·•·•···•···•·······•·•••••·•···•···•·•·•·•·•·•·•·•·•·•·•••·•·••●•●•●•••••••••••●•●••••·•·•·•·•·•·•••·•·•···•···•·•·•·•·•···•···•••• ·•·•·• · · ·••·•••·•••···· · ··•·•···•·······•••·•···········•·•·•·•·············•·•·•············•··············•···•···•·•···••••••●••·••••••••●••••·•·····•·•···•·•••••••••••••·•·•·•·•••••••••···· ······•···•···•·•••·······•·•·•·•·••••●●•·•·•·•·●••···••••●••••••••••·•···•···•·•·•·•••·•·•·•·•···················•···•···•·•·•···••••●••·•···•·•·••••●•●•●●●•●●●•●·•●●••••••••••·•·····•●•••••••••••••• ··•·•·•·•·••● ··· ··•·•·•·•·•·•·•···••●••·•·•·•·•···········•·•·•·•·•·•·•·•·•·······•···•·•·•···············································•·•·•·••••••●•●•●•●•●•··●••••••••••••••·•···•·•••••••••••·• •••·••••········•·•·•·•·•·•·•·•·•·•·••●•●••••·•·•···•···•···•·•·•·•·•••·•••·•·•·•···•···•·•·•·•·•·•·•·•·•···•·•·•···•···•···•···········•·•·••••●•●•●•●•●●●•●●●•●•●·●•●•●•••●•••●••••···•·•·•·•·•·•••••• ·•·· · · ······•···•···········•·•·•·••●••••·•·•·······•·•••·•·•···•·•·····························•·······································••••••••••••••••●•●•••••·•●•●•●••••·•·····················••• ······•·•·•·•·••●••••·•···············••●••·•·•••·······•••••·•·······•···•·•·····················•·•·•···········•·•·•·•·•••••••·•···•···••●•●•●•••••••●•●•●•●••••·•••••●●•••●••••••••••••••·•···•····· ·········•···•·●●●••···················•••••••·•·····•·•••••••·•·•·•·●•··········•·•·•···•···•·•·•···•···•···•·············•••••·•·······•·••●●●••·•·•·•·••●●●•••••··•·•·•••••••••·•·················•·• •·•·•·•·•·•·•·••●●●••••·•·•••···•···•·•·•···•·•·•••••·•••·•·•·•·•·•·•••·········•·•·•·•·•···············•·•·•·•·•••·•·•·•·•·•·•·•·••••••••••●•●•●••·•·••••●●●●●•●••••••·•••••••••••·•·······•·•·•·•·•••· ···•···•···•·•·••●••·•·•··••·•·•···············•·•••···•·•·•···•·•·•·•·· ··· ··············· ·····•············•·•·················•·•••·•·•·•••·•·•·•·•·••••●•●••••·•·•·•·•·•·•·············•·•·•·•·•·• •·•·•·•·•·••••●●●••·•·•·••●••••·•·•···•·······•·•••·•·•·••●••·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•···●·······•·•·•·•·•·•·•···············•·•·•·•·•••·•·•·•·••●••••••·•·•·•·•·•···•···•·········•·•••••••·•· ·······•·•···••●••·•·•···•···········•·•••·•·•••••·•·•···········•···•···········•···•···········••●·•·•·•·•·•···········•·•·•·•••·•••·•••·•••●••••••••••●••••••••·•·•·································· •••·•••·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•···•···•·······•·······•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•●•···•·······················•·•·•·•·••••••●••••••••••••••••••••·•·•·•·•••••••••·•···•···•···•···•·•· ·•·•·········•·•·········•••·•······························ ··········•···•······················•●········ ··· ··· · · ················•·•·•••·•·•·••••••●••••••·•·········•·•·•·•···················· •·•·•·•·•·•··••••••·•·•·••●••·•·····•·•···•···•·······················•···•···•···•···•···········•••·•···················•···•·········•·••••●••••••·•••••••••••••·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·····•·······••●••···•···•••·•···•·•·•·•·•···•·········•·•·•·•···· ··· ··················· ··············· ··· ··························•·•·•••·•···•·•••••••••••·•·•···•·•·•·•·•·•·•···•·•·•·•·•·•·•·• •·•·•·•·•···•·••●●•••·•···•·•·········•·●●•·•···················•···•···•···•···•···•·······•••···········•·•·•···········•·•·•·•···········•···•···•·•·•••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•··· ···············•••••···· ······•·····•·•••······ ··· ··•·•••·································●···•••···•···· ··· · · · · ··········· ······•···•···········•···•···············•········ ··· ··· ······· ··············•••••···············•·•·•••·•···•···•·••●••·●••·•·································•·•·•·•·········· ············•···•·•·•·•·•·•·•·•·•···•···•·•·•••·•···································•· ······ ··· ······•···· ··· ··· ··· ····•·•···········•••·•••·············· ··· ··· · · · · ··· · · ··· ··· · · ··· ··· ······················································· · · · · · · ··· ··· ····· ········•·······•••·•·····•••·· ······•·•·············································· ····································•·······················•···•·•·•···•·················· ··· ····•··········· ··· ··· · · ··•·•·· · · · · · · · · ··•···· · · ····•······ ··• ··· · · · · · · ··· · · · · · · · · · · · · · · · · · · · · ··· ··· ··· · · · · ··············· ··· · · ··· ··· ··· · · · ··· · · · · · · ······· ······· · · · ····· · · · · ··· · · ··· ············••· · · · · · · ··········· ··························· ··· · · · · ··· ······································· ··· ··················· · ··· · · · · · · · · · · · · · · · · ··· · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· ··· · · · · · · · · · · ··· · · ··•·· · · · · · ··· · · · · · · · · · · · · · · · · · · ··· · · · · · · · · ··· · · · · ··· ··· · · ··· ··· · · · · · · ··· · · ··· ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·•·•·•·•···········•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•·•·•·•·•••·•••·•••·•••·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••·•·•· ···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·•·•·•·•···•·······•·•·•·•••·•·•···········•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••••••••••·•·•·•·•·•·•·•••••••••••·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•· ·•·•·•·•·•·•·•···•···•···•···•···•···•···•···•·•·•·•·•·•·•···•···•···•···•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•••·•••·•·•·•·•·•·•·•·•••••••••••••·•·•·•·•·•·•·•·•·· •·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•••·•••·•·•·•••••••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·••••●•●•●•●•●••••••·•·•·•·•·•••••••••••••••••••·•·•·•·•·•·•·•·•· ···•···•·•·•·•·•·•••·•••·•••·•••·•·•·•·•·•••·•••·•••·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•················ •·•·•·••••••••●•••●•••●••••••·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•·•••••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·······················•·•·•·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·••••• •·•·•·•·•·•·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••·•••·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·••••••••••••••••••●•●•●• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•••·•·•·•·•·•••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••·•••••••••••·•·•·••••••••••••••• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•••·•••·•••·•••·••••••••••••••••●•●•●•●•●•••••••••••●•●•●•••●••••••·•·•·•·•·•·•·•••·•••·•••·•••·•••·••••••••••••••••••••••••••••●•••●••••••••• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••••••••••••••••••••••••·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• •••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·•···•••·•••·•••·•••·•••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•••·•••· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•••·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·••····•·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·•••·•••·•••·•••·•••·•••·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·• •••••••·•••·•••·•••·•••·•••·••··•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·••••••••••••····•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·• ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•···•···•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•·•·•·•••·•••••••·•·•·····•·•·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·····•••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•·······•···•·•·•·•·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···· ··•·•·•·•·•·•·•···•···•···•···•···•···························•·•·•·•·•·•·•·•·•·• •••·•••·•••·•••·•••·•••·•••·•····••·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••••••·•••·•••·•••••••••••••••••••••••·····•••••••·•••••••·•·•·•·•·•·•·•·•·•···•···•···•···•·······•·•·•·•·•·•·•••••••••••• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·•·•·•·•·•···················································•·•·•·•·•·•·• •·•·•·•••·•••·•••·•·•·•••·••······•••·•••·•••·•••·•••·•••·•••·•···•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••••••••·····•·•·•·•·•·•·•·•·······················•·•·····················•·•·•••·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ····•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·······························•···············•···•·······•·•·•·•·•·•·•·• •••·•••·•••·•·•·•·•·•·•·•·•·······•·•••·•••·•••·•••••••·•••·•••··••·••••••••••••••••••••••••••••••••••••••••••••••······•••·•·•·•·•·•·•·•···•·······•·•·•·•·•·•·•·•·•••••••·•••·•••·•·•·•·•·•·•·•••••••• ·•·•·•·•···············•·•·• · · ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·• · · ··•·•·•·•·•·•·•·•·•••·•••·•·•·•••·•·•·•·•·•·•·•••••••••••·······•···•···•·•·•·•·• •·•·•·•·•·•···•···•·•·•·•·••······•••·•••·•••·•••·•••·•••·•••·····•••·•••·•••••••••••••••·••••••••••••••••••••••••········••••••••••••••••••••●•••●••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•• ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·· ····•·•·•·•·•·•·•·•·•·•·•·•·•·• ····•·•·•·•·•·•·•·•·•·•·•···•·•·•••·•••·•·•·•·•·•·• · · ··•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·• •·•·•·•·•••·••••··•·•·•••••·······•••••••••••••••••••••••••••·····•••••••••••••••••••••••·••••••••••••••••••••••••······•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·•·· ··•·•·•·•·•············ ··· ··•·•·•·•·•·•·•·•·•·•·•·•·•·· · ··•·•·•·•·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•·•·•·• · · ··•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·• •·······•••••·••···················••••••••••••••••••••••••••······••••••••••••••••••••••·••••••••••••••••••••••••········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·········•·•·•·•·············· ··· ······•·•·•·•·•·•·•·•·•·•·· ····•·•·•·•·•••·•••·•••·•····••·•••·•••·•••·•••·••· ··· ····•••·•••·•••·•••·•••·•••·•••••••••••••••••••••••·•••·•••·•••·•••·•••·•••·•••·• •·······••••••••············•···•···•···•·•·•·•••••••••••••••······•••••••••••••••••••••····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ···· ····•·•·•·•·······························•·•·•·•·•·•·•···· ··•·•·•·•·•·•·•·•·•·•·• ····•·•·•·•·•·•·•·•·•·•·· · · · ··•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•·•·•••·•••·••• ·········••••••·······●•······················••••••••••••••········••••••••••••••••••••····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·················· ···••··••·· ··· ············•••·•••·•••·•·· ··· ·••·•••·•••·•••·•••······••·•••·•••·•••·•••·••· ··· ····•••••••·•••·•••·•••·•••••••••••••••••••••••••••••••·•••·•••·•••·•••·•••·•••·• ········•···•···•···•·●••·●••···•···••··•···•·••••••••••••••········•••••••••••••••••••·····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ································· ··•······•··•·•·•·•·•·•·• ··· ····•••·•••·•••·•••··•· ····•••·•••·•••·•••·•••·· · · · ··•·•••·•••·•••·•••·•••·•••·•••·•••••••••••••••·•••·•••·•••·•••·•••·•••·•••·••• ··········•···•···•···•···•···•···•···•···•·●·•·••••••••••••········•••••••••••••••••·•·····•••••••••••••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·· ··· ··· ····•·································•···•·•••·•········••·•••·•••·•••·••·•· · · ····•·•••·•••·••••••· · · · ··•••••·•••••••••·•••·•••••••••••••••••••••••••••••••••••·•••·•••·•••·•••••••·• ········•···•·•••···•·●••···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·········•••·•••••••••••••···············•·•••••••••••·········•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• · ··· ········●······•●··········•······•·· ··················· ······· ·········••·· · ··· ··· ··· ·••·•••·•••·· · · · ··•·•••·•••·•••·•·•·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·•••·••• ··········•·•·•·•·•·•·●••···•···•·●·•·•·•••···•···•···•·•·●···•···················•·•·················•••••••·•••·········••••••··•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ·············•···•···•···•···•···•···•···•···•·······•····•·······•····•·· ······· ··· ··· ··· ··· · ····•·•·••••· · · · ··•••·•·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•·•·•·•·••••• ····•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···●····•··············•·······················•·•·········••••••••••••••••••••••●•••●•••●•••●•••●•••●•••●•••••••••••••••••••●•●•●•●•●••• · ·······•●···●·•·•·•····•●···•···•···•···•···•···•·•·•···················· ··· ··· ·•· ··· ··· ··· ··· ··· ··· · · · · · ··••· ·••·•••••·•••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·••• ··········●••·•••·•·•·•·•·●••·•·•·•·•·•·•·•···•···•·●·•●•···•·•·······························································•···••••••••••••●•••●•••●•●•●•●•●•••●•••●•••●••••••••••••••••••••••••••••• ·· ··· ···•●·•·●·•·•·•···••●·•·•·•·•···•···•·•·•···••••●·•········ ······· ········· · ··· ··· ··· ··· ··· ··· ··· ··· · · ··••····•••••••·••••••••••••••●•••●•••●•••••••••••••••••••••••••••••••••••••• ····•·•·•·•·••••●••••••·•••••••·•••·•••••••·•·•·•·•·•●●••••·•·•·····•··························•····························●••···••●•••●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●••••••• ···········•·••●●●••·•·•·•••·•·•·•·•·••●·•·•···•·•·••●●●·•·•···················· ······· ··· ··· ··· ··· · · ··· ··· · · ····••· ····•·····••••●•••●•●•●•●•●•●•●•●•●•••●•••••••••••••••••••••••••••••••• ······•·•·•·••●●●●●••·••••●●•••••·••••●●●·•·•·•·•·•••●·••·•·•·•···•···•·······················································•·············••●•●•●•●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●• ·········•·•·••●●●••·•·••●●●••·•·•·••●●●••·•·•·•·•·••• •••·•·•································ ············································••●•●•●•●•●•●•●•●●●•●•●•●•●•●•●•●•●•●•●•••●•••●•••••••••••• · ····•·•·•·•·•••··●•••••••●●●●•••••••••··•••·•·•·•••·••·••••·•·•·•·•·•·•·•···········•·•·············•···········•·······•·······•···•·•·•·••●•●•●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•·· ··········•·•·· •·•·•·•·• ·••·•·•·•·••··•·•·•·•·•·•·· •·•••••••·······•·•·•·········●·•···········•●•·····•·•·●••·············•·•·•·•●•·•··•••●•●•●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●••····•●•••••••••· · ······•·•·•·•·· •••••·• ·•·••••••·•••·· •·•·•·•·•·•·• ·●●●●••·•·••••••●●•·•·····•·●••••·········•·••●••·······•••·•·•·••●••·•·•·●••···•···•·●•••●●●●●●●●•●●●●●●●●●●••·•·•·●●●•●●●•●•• ··· ••●•●••·•·• ·· ·········• ··• ··•·•·•·· • •·•···••●•● •●•••●•••●•●•· ·•●·•••·•·····•·•·•·•·•·········•·•···•···········•·····•·•······••·····•••·•·•·•·•·•·•·••●·• •·• ··•·•·•·• · · · ··• •···•·· · · · ··•·· · · · · ········• · · ··•·●•●•● ···•●●●•●•●•●•· ·●●·•·•·•·•·· · •·•·•·•·•••••••••···•···•·····•·•·············•·········•·•·•·•·•••·•·•·•···•···•···•····•······················································ ····•••·• ·•· ●•••●•••· ·•●•········ · ··••••••••• ·••·•·•·•·········•·•···· · · ··•·······················•···············•···•··················•••••●••·•···············•···•·······•·•·•·•·•···• •·••••••••· · ●••·•·•·· · •·•·••●•●•● · ·•●•●•●•●••·· ····•·•·•·················•·•·•·•·········•·•·•·•···········•···•···•···••●•••••●·············•·•·•·●●●••••••·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•· ·•·•······ ······••● · ·•●•●●••●•••· · ········••••· •••·•·•·•·········•···•···········•···•·····················•·•·•••·•·•·•••·•·•·······················•·•·•••••·•••••···············•••••••·•···· ········• · ·•●•●•●•●•· · ●·•·•·•·•·•·· ●•●•●•●•●•●•● ··•·•·•·•·•••·•·•·•·······•·•·•·•·········•···•·············•·•·•••••·••••●•••••●•••••●●••●●•·•·•·•••●●●●●●●●●●••••·•·•···•···•···•···●•●•●••••••· ·•·•·•·•· · ••••····· · ···••••••••• ·•●••········· •••·•·●·•·······························•·························•·•·••●●•···•••···•••••••·•·•·•·••●●●●●•●●••●•●••·•·······················•·•·• •·••••••· · ······•·●•● ·•●•●•●•●•●···· ····••●•••••• ·•··•···•···•·•·•···········•···•·•·•·•·•·························•••••••●●••···•·····•·•·•·••••••••●●●●●●●•● ●•●●●••••·•···•·················•·•• ·· ······· ••••••●••• •·········••• ••••••••······ •••·•·•·•······ ········•·•·•·●·························•••·•·••●●•·•·•·•••···········•·•·••••••••●•●•••••••·•●•●●●••·······••●•••●••••·····•●●•• ···•••••• · ·•••●●··•·· ···•●•●•●•••●•· ·······••••·•·•·•·•·•·······•···•••·•••••••·•••·•·······•·•••••·•·•·•·••●•••••••●••·•·•·•···········•·•·••••••••●•●●●●●●●●● •●●●●●●•●••••••••••·•·•·•·•·•·•·●••• ·•·•·•·•· · ·······•••· ••••••••····· ·•••••••••••· ··· ··················•·•·•·•·•·•••·················•·•·•·●••·········· ··· ··· ··········•·•·••••••●●●••••••••·•••·•·•·······•••••••••••••••••••·· •·•······ · ·•••••••••· · ·······••·•·•·•·•·······•·•·•·•·•·•·•·······•·······•···•···•·•·•·•·•···•···•···•···•·•·•···•·•·•···•···········••●•●•●••••••···•·· •••••●• •●●•●•●•●•••●•●•●•●•●•••●•••●•●•●• · ····••· ••••••··· ··••••••••••····· ··•·•·•·•·•••·●••·•···························•·•·•·•·························•···•••·•·······•·••●•●•●••••·· · · · ····●••••••••••••••·•••·•·•·•·•·••●•• •••·••••• · ······•·•·•·•·•·•·•·······•·•·•·•·•·•••·••●•••●••••·•·•·•·•·•···•···•·······•·•••••·•···•···•·•·•·•·•·•·•·•·•·•·•••·•·••●•●•●•••••••••••●•●••••·•·•·•·•·•·•••·•·•···•···•·•·•·•·•···•···•••• ·•·•·• · · ·••·•••·•••···· · ··•·•···•·······•••·•···········•·•·•·•·············•·•·•············•··············•···•···•·•···••••••●••·••••••••●••••·•·····•·•···•·•••••••••••••·•·•·•·•••••••••···· ······•···•···•·•••·······•·•·•·•·••••●●•·•·•·•·●••···••••●••••••••••·•···•···•·•·•·•••·•·•·•·•···················•···•···•·•·•···••••●••·•···•·•·••••●•●•●●●•●●●•●·•●●••••••••••·•·····•●•••••••••••••• ··•·•·•·•·••● ··· ··•·•·•·•·•·•·•···••●••·•·•·•·•···········•·•·•·•·•·•·•·•·•·······•···•·•·•···············································•·•·•·••••••●•●•●•●•●•··●••••••••••••••·•···•·•••••••••••·• •••·••••········•·•·•·•·•·•·•·•·•·•·••●•●••••·•·•···•···•···•·•·•·•·•••·•••·•·•·•···•···•·•·•·•·•·•·•·•·•···•·•·•···•···•···•···········•·•·••••●•●•●•●•●●●•●●●•●•●·●•●•●•••●•••●••••···•·•·•·•·•·•••••• ·•·· · · ······•···•···········•·•·•·••●••••·•·•·······•·•••·•·•···•·•·····························•·······································••••••••••••••••●•●•••••·•●•●•●••••·•·····················••• ······•·•·•·•·••●••••·•···············••●••·•·•••·······•••••·•·······•···•·•·····················•·•·•···········•·•·•·•·•••••••·•···•···••●•●•●•••••••●•●•●•●••••·•••••●●•••●••••••••••••••·•···•····· ·········•···•·●●●••···················•••••••·•·····•·•••••••·•·•·•·●•··········•·•·•···•···•·•·•···•···•···•·············•••••·•·······•·••●●●••·•·•·•·••●●●•••••··•·•·•••••••••·•·················•·• •·•·•·•·•·•·•·••●●●••••·•·•••···•···•·•·•···•·•·•••••·•••·•·•·•·•·•·•••·········•·•·•·•·•···············•·•·•·•·•••·•·•·•·•·•·•·•·••••••••••●•●•●••·•·••••●●●●●•●••••••·•••••••••••·•·······•·•·•·•·•••· ···•···•···•·•·••●••·•·•··••·•·•···············•·•••···•·•·•···•·•·•·•·· ··· ··············· ·····•············•·•·················•·•••·•·•·•••·•·•·•·•·••••●•●••••·•·•·•·•·•·•·············•·•·•·•·•·• •·•·•·•·•·••••●●●••·•·•·••●••••·•·•···•·······•·•••·•·•·••●••·•·•·•·•·•·•·•···•·•·•·•·•·•·•·•·•···●·······•·•·•·•·•·•·•···············•·•·•·•·•••·•·•·•·••●••••••·•·•·•·•·•···•···•·········•·•••••••·•· ·······•·•···••●••·•·•···•···········•·•••·•·•••••·•·•···········•···•···········•···•···········••●·•·•·•·•·•···········•·•·•·•••·•••·•••·•••●••••••••••●••••••••·•·•·································· •••·•••·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·•···•···•·······•·······•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•●•···•·······················•·•·•·•·••••••●••••••••••••••••••••·•·•·•·•••••••••·•···•···•···•···•·•· ·•·•·········•·•·········•••·•······························ ··········•···•······················•●········ ··· ··· · · ················•·•·•••·•·•·••••••●••••••·•·········•·•·•·•···················· •·•·•·•·•·•··••••••·•·•·••●••·•·····•·•···•···•·······················•···•···•···•···•···········•••·•···················•···•·········•·••••●••••••·•••••••••••••·•·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·····•·······••●••···•···•••·•···•·•·•·•·•···•·········•·•·•·•···· ··· ··················· ··············· ··· ··························•·•·•••·•···•·•••••••••••·•·•···•·•·•·•·•·•·•···•·•·•·•·•·•·•·• •·•·•·•·•···•·••●●•••·•···•·•·········•·●●•·•···················•···•···•···•···•···•·······•••···········•·•·•···········•·•·•·•···········•···•···•·•·•••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•··· ···············•••••···· ······•·····•·•••······ ··· ··•·•••·································●···•••···•···· ··· · · · · ··········· ······•···•···········•···•···············•········ ··· ··· ······· ··············•••••···············•·•·•••·•···•···•·••●••·●••·•·································•·•·•·•·········· ············•···•·•·•·•·•·•·•·•·•···•···•·•·•••·•···································•· ······ ··· ······•···· ··· ··· ··· ····•·•···········•••·•••·············· ··· ··· · · · · ··· · · ··· ··· · · ··· ··· ······················································· · · · · · · ··· ··· ····· ········•·······•••·•·····•••·· ······•·•·············································· ····································•·······················•···•·•·•···•·················· ··· ····•··········· ··· ··· · · ··•·•·· · · · · · · · · ··•···· · · ····•······ ··• ··· · · · · · · ··· · · · · · · · · · · · · · · · · · · · · ··· ··· ··· · · · · ··············· ··· · · ··· ··· ··· · · · ··· · · · · · · ······· ······· · · · ····· · · · · ··· · · ··· ············••· · · · · · · ··········· ··························· ··· · · · · ··· ······································· ··· ··················· · ··· · · · · · · · · · · · · · · · · ··· · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· ··· · · · · · · · · · · ··· · · ··•·· · · · · · ··· · · · · · · · · · · · · · · · · · · ··· · · · · · · · · ··· · · · · ··· ··· · · ··· ··· · · · · · · ··· · · ··· ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
use it
html
<script type="module" src="https://ascii.rest/ascii.js"></script> <ascii-art piece="varanasi-ghats"></ascii-art>
No install and no build step. ascii.js defines the <ascii-art> tag, loads the piece from ascii.rest, plays it while it is on screen, and holds the first frame for anyone who prefers reduced motion.
react
// npm install github:bas3line/ascii
import { Ascii } from "ascii.rest/react";
import { varanasiGhats } from "ascii.rest/pieces";
<Ascii piece={varanasiGhats} /> A client component, so it works in the Next.js app router as it is. Pass the name instead, piece="varanasi-ghats", to fetch the piece only when it mounts.
astro
--- // npm install github:bas3line/ascii import Ascii from "ascii.rest/astro"; --- <Ascii piece="varanasi-ghats" />
Renders the first frame on the server, so the page is whole before any script runs, then plays the piece once it loads.
typescript
// npm install github:bas3line/ascii
import { mount } from "ascii.rest";
import { varanasiGhats } from "ascii.rest/pieces";
const el = document.querySelector<HTMLCanvasElement>("canvas")!;
const stop = mount(el, varanasiGhats); mount plays a piece in a <pre>, or on a <canvas> for the coloured ones, and returns a function that stops it. Every piece, option and frame is typed.
/*
* varanasi ghats: dusk on the ganga. Stepped ghats run along the bank and
* away toward the afterglow, temple spires black against an indigo to amber
* sky. Priests raise the aarti lamps on the steps, diyas drift downstream on
* the dark water, and a boatman rows slowly across the bright reach.
*
* Shaded in colour cell by cell, then drawn as a halftone: a dot whose size is
* the cell's brightness, ordered-dithered, in the palette colour nearest its hue.
*/
import type { Frame, Meta } from "../types.ts";
export const meta = {
name: "varanasi ghats",
category: "scenes",
note: "dusk aarti on the ganga, lamps on the steps and diyas on the water",
cols: 200,
rows: 100,
cell: 1,
fps: 15,
ground: "#0b0812",
palette: [
// the sky, indigo through violet
"#141230", "#1d1a42", "#272257", "#332b6a", "#45357a", "#5a4388", "#7259a8",
// plum, orchid, mauve and rose
"#6d3a73", "#8a4677", "#a8527a", "#c4607a", "#d97a92", "#b866a0", "#9a68c8", "#c868b0", "#e8707a",
// coral to gold
"#d9705f", "#e88552", "#f29f4a", "#f8b85a", "#fcd07a", "#ffe3a6", "#fff2d2",
// stone in shadow, and the violet treads
"#1a1220", "#24182a", "#301f33", "#3f2838", "#523340", "#3a2c4c", "#4d3a64",
// stone in lamplight
"#5e3524", "#7d4527", "#a0582a", "#c06e2e", "#d98a46",
// flame
"#ffffff", "#fff6d8", "#ffd860", "#ff9f2a", "#f06a1e", "#c8401a", "#8a2a16",
// dark water
"#0f1a2c", "#162540", "#20325a",
// starlight, set directly and never matched
"#d6d4ee",
],
} satisfies Meta;
const W = 200, H = 100;
const HZ = 60; // the far bank
const END = 150; // where the ghats meet the far bank
const GLOW = [156, HZ - 1.5]; // the afterglow, sitting on the far bank
const DOTS = " ·•●";
const COVER = [0, 0.3, 0.6, 1];
// how far a dot's colour may be brightened to make up for its size: small dots
// in dark areas stay dark instead of turning into a pale speckle
const LIFT = [0, 2.5, 1.7, 1.35];
const BAYER = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5].map((v) => v / 16 - 0.47);
const FLAME = [1, 0.62, 0.22];
const WASH = [1, 0.5, 0.2];
const SKY = 0, WATER = 1, BANK = 2, STEPS = 3, BLD = 4, SPIRE = 5, UMB = 6, FIG = 7, PLAT = 8;
// heat, then colour: indigo overhead, violet, plum, rose, coral, amber, gold
const RAMP: [number, number, number, number][] = [
[0.0, 0.085, 0.07, 0.24],
[0.14, 0.13, 0.1, 0.34],
[0.28, 0.22, 0.14, 0.44],
[0.42, 0.34, 0.17, 0.48],
[0.52, 0.47, 0.21, 0.47],
[0.62, 0.6, 0.26, 0.42],
[0.7, 0.7, 0.31, 0.36],
[0.78, 0.8, 0.39, 0.3],
[0.86, 0.88, 0.5, 0.26],
[0.92, 0.95, 0.65, 0.32],
[0.97, 1.0, 0.8, 0.48],
[1.0, 1.0, 0.92, 0.7],
];
function hash(x: number, y: number): number {
let h = Math.imul(x | 0, 374761393) + Math.imul(y | 0, 668265263);
h = Math.imul(h ^ (h >>> 13), 1274126177);
return ((h ^ (h >>> 16)) >>> 0) / 4294967296;
}
function noise(x: number, y: number, period: number): number {
const xi = Math.floor(x), yi = Math.floor(y);
const fx = x - xi, fy = y - yi;
const u = fx * fx * (3 - 2 * fx), v = fy * fy * (3 - 2 * fy);
let x0 = xi, x1 = xi + 1;
if (period) {
x0 = ((xi % period) + period) % period;
x1 = (x0 + 1) % period;
}
const a = hash(x0, yi), b = hash(x1, yi), c = hash(x0, yi + 1), d = hash(x1, yi + 1);
return a + (b - a) * u + (c - a) * v + (a - b - c + d) * u * v;
}
function fbm(x: number, y: number, octaves: number, period: number): number {
let s = 0, n = 0, amp = 0.5, f = 1;
for (let i = 0; i < octaves; i++) {
s += amp * noise(x * f, y * f, period * f);
n += amp;
amp *= 0.5;
f *= 2;
}
return s / n;
}
const clamp = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);
const smooth = (a: number, b: number, v: number) => {
const k = clamp((v - a) / (b - a));
return k * k * (3 - 2 * k);
};
const mix = (a: number, b: number, k: number) => a + (b - a) * k;
const hex = (s: string) => [1, 3, 5].map((i) => parseInt(s.slice(i, i + 2), 16) / 255);
// The heat ramp, tabulated.
const RL = 256;
const RT = new Float32Array((RL + 1) * 3);
for (let i = 0; i <= RL; i++) {
const h = i / RL;
let j = 0;
while (j < RAMP.length - 2 && h > RAMP[j + 1][0]) j++;
const [h0, r0, g0, b0] = RAMP[j], [h1, r1, g1, b1] = RAMP[j + 1];
const k = clamp((h - h0) / (h1 - h0));
RT[i * 3] = mix(r0, r1, k), RT[i * 3 + 1] = mix(g0, g1, k), RT[i * 3 + 2] = mix(b0, b1, k);
}
const rampAt = (h: number) => ((h < 0 ? 0 : h > 1 ? 1 : h) * RL + 0.5) | 0;
// The waterline along the ghats, near at the left and running away to the right.
const wlF = (x: number) => (x < END ? HZ + 0.5 + 20 * Math.pow(1 - x / END, 1.6) : HZ + 0.5);
const scF = (x: number) => 0.45 + 1.75 * Math.pow(Math.max(0, 1 - x / END), 1.3);
const stepTopF = (x: number) => wlF(x) - 9.5 * scF(x) * (0.3 + 0.7 * smooth(END, END - 16, x));
// The dusk sky's heat: low overhead, rising toward the horizon, hottest at the glow.
function skyHeat(x: number, y: number): number {
const v = clamp(y / HZ);
const dx = Math.abs(x - GLOW[0]), dy = Math.abs(GLOW[1] - y);
// a wide warm band along the horizon, and a small hot core on the bank
const wide = 0.46 * Math.exp(-dx / 55 - dy / 23);
const core = 0.24 * Math.exp(-Math.sqrt((dx / 13) ** 2 + (dy / 4.5) ** 2));
return 0.06 + 0.42 * v * v + wide + core;
}
export default function varanasiGhats(): Frame {
const P = meta.palette.map(hex);
const STAR = P.length - 1;
const N = W * H;
const out = new Array<string>(N);
const lut = new Uint8Array(32768).fill(255);
const nearest = (r: number, g: number, b: number): number => {
const k = (Math.min(31, (r * 31.99) | 0) << 10) | (Math.min(31, (g * 31.99) | 0) << 5) | Math.min(31, (b * 31.99) | 0);
if (lut[k] !== 255) return lut[k];
let best = 0, bd = 1e9;
for (let i = 0; i < STAR; i++) {
const dr = P[i][0] - r, dg = P[i][1] - g, db = P[i][2] - b;
const d = 0.3 * dr * dr + 0.5 * dg * dg + 0.2 * db * db;
if (d < bd) (bd = d), (best = i);
}
return (lut[k] = best);
};
// --- the bank -------------------------------------------------------------
// Buildings along the ghats: [x0, x1, height above the steps in scale units, seed]
const blds: [number, number, number, number][] = [];
for (let x = -6; x < END - 10; ) {
const s = scF(Math.max(0, x));
const w = (8 + 10 * hash(x | 0, 3)) * s;
const low = (x > 110 ? 0.8 : 1) * (0.45 + 0.55 * smooth(END - 8, END - 34, x));
blds.push([x, x + w, (7 + 9 * hash(x | 0, 4)) * low, hash(x | 0, 5)]);
x += w;
}
// Temple spires: [centre x, height in rows, half width at the base]
const spires: [number, number, number][] = [[118, 33, 5.2], [64, 19, 4], [31, 15, 3.6], [139, 8, 1.6], [90, 11, 2.4], [129, 10, 2]];
// Aarti stations on the near ghat, unevenly spaced: [x, streak width, streak length]
const aarti: [number, number, number][] = [[11, 1.15, 1.25], [24, 0.8, 0.85], [39, 1.25, 1.1], [54, 0.75, 0.75]];
// Umbrellas on the far steps
const umbs = [70, 83, 98, 109];
const mat = new Uint8Array(N);
const sR = new Float32Array(N), sG = new Float32Array(N), sB = new Float32Array(N);
const flo = new Float32Array(N);
const alb = new Float32Array(N); // how much the lamps' wash lights each cell
const skyH = new Float32Array(N);
const warm = new Float32Array(N);
const roofOf = (x: number) => {
for (const [x0, x1, h] of blds) if (x >= x0 && x < x1) return stepTopF(x) - h * scF(x);
return stepTopF(x);
};
for (let r = 0; r < H; r++) {
for (let x = 0; x < W; x++) {
const k = r * W + x;
const xc = x + 0.5, y = r + 0.5;
const wl = wlF(xc);
if (y >= wl) {
mat[k] = WATER;
alb[k] = 0.25;
continue;
}
let m: number = SKY, cr = 0, cg = 0, cb = 0, fl = 0.06, al = 0;
const s = scF(xc);
// the far bank: an embankment and clumps of trees against the glow
const clump = smooth(0.42, 0.72, fbm(xc * 0.11, 3, 3, 0)) * smooth(160, 172, xc);
const bankTop = HZ - 2.2 - 0.6 * fbm(xc * 0.4, 7, 2, 0) - 4 * clump;
if (xc >= END - 4 && y >= bankTop) (m = BANK), (cr = 0.1), (cg = 0.07), (cb = 0.125), (fl = 0.03);
if (xc < END) {
const st = stepTopF(xc);
// buildings and their rooftop pavilions
let roof = st, bi = -1;
for (let i = 0; i < blds.length; i++) if (xc >= blds[i][0] && xc < blds[i][1]) (roof = st - blds[i][2] * s), (bi = i);
let top = roof;
if (bi >= 0) {
const [x0, x1, , hb] = blds[bi];
const mid = (x0 + x1) / 2, half = (x1 - x0) / 2;
if (hb > 0.45) {
// a chhatri: a small dome on four posts
const cx = hb > 0.75 ? x0 + half * 0.4 : mid;
const dx = Math.abs(xc - cx) / (1.6 * s);
if (dx < 1) top = Math.min(top, roof - 1.4 * s - 1.5 * s * Math.sqrt(1 - dx * dx));
if (dx < 1.1 && dx > 0.7) top = Math.min(top, roof - 1.4 * s);
}
if (Math.abs(xc - x0) < 0.6 * s || Math.abs(xc - x1) < 0.6 * s) top = Math.min(top, roof - 0.6 * s); // parapet ends
}
if (y >= top && y < st) {
m = BLD;
// backlit stone, a little violet from the sky, darker low down
cr = 0.075, cg = 0.05, cb = 0.09;
const fy = (y - top) / Math.max(1, st - top);
cr *= 1.1 - 0.4 * fy, cg *= 1.1 - 0.4 * fy, cb *= 1.1 - 0.3 * fy;
al = 0.5;
// rows of arched openings, a fair number lit on the near ghats
if (bi >= 0 && s > 0.6) {
const fx = (xc - blds[bi][0]) / (2.4 * s), fz = (st - y) / (3 * s);
const ix = Math.floor(fx), iz = Math.floor(fz);
if (fx - ix > 0.35 && fx - ix < 0.7 && fz - iz > 0.25 && fz - iz < 0.75 && iz >= 1 && st - y < blds[bi][2] * s - 1.5 * s) {
const lit = hash(bi * 31 + ix, iz * 7) < (s > 1.2 ? 0.28 : 0.2);
if (lit) (cr += 0.5), (cg += 0.28), (cb += 0.08);
else (cr *= 0.55), (cg *= 0.55), (cb *= 0.65), (al = 0.2);
}
}
fl = 0.14;
}
if (y >= st) {
// the steps: treads catch the violet sky, risers fall in shadow
m = STEPS;
const sp = 1.6 * s;
const near = (wl - y) / (wl - st);
if (sp < 2.2) {
// too far to count the steps: a faint alternating tread
const odd = Math.floor(wl - y) & 1;
(cr = 0.19), (cg = 0.13), (cb = 0.25);
if (odd) (cr *= 0.55), (cg *= 0.55), (cb *= 0.58);
al = odd ? 0.4 : 0.75;
} else {
const ph = ((wl - y) / sp) % 1;
if (ph < 0.6) (cr = 0.24 + 0.05 * (1 - near)), (cg = 0.15), (cb = 0.2), (al = 1);
else (cr = 0.05), (cg = 0.035), (cb = 0.06), (al = 0.3);
}
// the wet bottom steps darker
if (wl - y < 1.2 * s) (cr *= 0.6), (cg *= 0.6), (cb *= 0.75), (al *= 0.6);
fl = 0.12;
}
}
// spires
for (const [sx, sh, sw] of spires) {
const base = roofOf(sx) + 1;
const h = base - y;
if (h < -1 || h > sh + 2.5) continue;
const dx = Math.abs(xc - sx);
const f = h / sh;
// the curved shikhara, an amalaka disc and the kalash on top
let hw = f <= 1 ? sw * Math.pow(Math.max(0, 1 - Math.pow(f, 1.8)), 0.6) : 0;
if (f > 0.92 && f < 1.02) hw = Math.max(hw, sw * 0.32);
if (f >= 1.02 && h < sh + 2.2) hw = Math.max(hw, 0.35 + 0.2 * Math.sin(((h - sh) / 2.2) * Math.PI));
if (h >= -1 && h < 0.5) hw = sw * 1.15;
if (dx <= hw) {
m = SPIRE;
const band = Math.floor(h / 1.6) % 2 ? 0.8 : 1;
cr = 0.085 * band, cg = 0.055 * band, cb = 0.095 * band;
fl = 0.12, al = 0.35;
}
}
// the big umbrellas on the far steps
for (const ux of umbs) {
const s2 = scF(ux), wl2 = wlF(ux);
const cy = wl2 - (wl2 - stepTopF(ux)) * 0.55;
const dx = (xc - ux) / (3 * s2), dy = (cy - y) / (1.4 * s2);
if (dy > 0 && dy < 1 && Math.abs(dx) < Math.sqrt(1 - dy * dy)) (m = UMB), (cr = 0.07), (cg = 0.045), (cb = 0.075), (al = 0.4);
if (dy <= 0 && dy > -0.25 && Math.abs(dx) < 1) (m = UMB), (cr = 0.05), (cg = 0.03), (cb = 0.05), (al = 0.2);
if (Math.abs(xc - ux) < 0.5 && y > cy && y < cy + 2.2 * s2) (m = UMB), (cr = 0.04), (cg = 0.03), (cb = 0.04), (al = 0.1);
}
// the priests on their platforms, dark against the lit steps
for (const [ax] of aarti) {
const s2 = scF(ax), u = 1.3 * s2, base = wlF(ax) - 2.6 * s2;
const dx = (xc - ax) / u;
const fy = (base - y) / u;
// a dhoti, a broad-shouldered torso, a neck and the head
const bw = fy < 0 ? -1 : fy < 2.2 ? 0.66 - 0.04 * fy : fy < 4.1 ? 0.58 + 0.32 * smooth(2.2, 3.7, fy) : fy < 4.5 ? 0.28 : -1;
const head = Math.hypot(dx * 1.05, fy - 5.05) < 0.62;
if (Math.abs(dx) < bw || head) (m = FIG), (cr = 0.035), (cg = 0.022), (cb = 0.035), (fl = 0.02), (al = 0.04);
if (y >= base && y < base + 0.7 * s2 && Math.abs(xc - ax) < 2.3 * u) (m = PLAT), (cr = 0.12), (cg = 0.07), (cb = 0.06), (fl = 0.04), (al = 0.8);
}
if (m === SKY) {
const veil = 0.92 + 0.16 * fbm(x * 0.05, r * 0.1, 3, 0);
const hh = skyHeat(xc, y) + 0.05 * (fbm(x * 0.07 + 11, r * 0.16, 2, 0) - 0.5) + 0.1 * (fbm(x * 0.025 + 3, r * 0.09 + 5, 3, 0) - 0.5);
skyH[k] = hh;
warm[k] = smooth(0.3, 0.9, hh);
const i = rampAt(hh) * 3;
cr = RT[i] * veil, cg = RT[i + 1] * veil, cb = RT[i + 2] * veil;
fl = 0.2;
}
mat[k] = m;
sR[k] = cr, sG[k] = cg, sB[k] = cb, flo[k] = fl, alb[k] = al;
}
}
// rim light: silhouette edges facing the glow, and their tops, take the sky's colour
const rimR = new Float32Array(N), rimG = new Float32Array(N), rimB = new Float32Array(N);
for (let r = 1; r < H - 1; r++) {
for (let x = 2; x < W - 2; x++) {
const k = r * W + x;
const m = mat[k];
if (m === SKY || m === WATER) continue;
// the edge facing the glow takes its orange light, the top the sky's colour
const toward = x < GLOW[0] ? 1 : -1;
const strong = 0.75 * Math.exp(-Math.abs(x - GLOW[0]) / 42);
let a = 0;
if (mat[k + toward] === SKY) a = strong;
else if (mat[k + 2 * toward] === SKY) a = strong * 0.4;
if (a > 0) (rimR[k] = 0.85 * a), (rimG[k] = 0.45 * a), (rimB[k] = 0.26 * a);
if (mat[k - W] === SKY) (rimR[k] += sR[k - W] * 0.3), (rimG[k] += sG[k - W] * 0.3), (rimB[k] += sB[k - W] * 0.3);
}
}
for (let k = 0; k < N; k++) (sR[k] += rimR[k]), (sG[k] += rimG[k]), (sB[k] += rimB[k]);
// small diyas lining the steps near the aarti, twinkling
const stepLamps: [number, number][] = [];
for (let x = 2; x < 118; x++) {
const s = scF(x + 0.5);
for (let r = Math.floor(stepTopF(x + 0.5)); r < wlF(x + 0.5) - 1; r++) {
const k = r * W + x;
if (mat[k] !== STEPS) continue;
const near = Math.exp(-(((x - 33) / 36) ** 2));
if (hash(x * 3 + 7, r * 5) < 0.035 * near + 0.006 && ((wlF(x + 0.5) - r - 0.5) / (1.6 * s)) % 1 < 0.3) stepLamps.push([k, hash(x, r) * 40]);
}
}
// electric lamps along the far ghats, each with its thin road on the water
const sref = new Float32Array(N);
for (let x = 58; x < END - 3; ) {
const s = scF(x);
const ly = stepTopF(x) - 0.4 * s + (wlF(x) - stepTopF(x)) * 0.55 * hash(x | 0, 78) ** 2;
const halo = 1 + 3.2 * s, R = Math.ceil(halo * 3);
for (let r = Math.max(0, Math.floor(ly - R)); r < Math.min(H, ly + R); r++) {
for (let xx = Math.max(0, Math.floor(x - R)); xx < Math.min(W, x + R); xx++) {
const k = r * W + xx;
if (mat[k] === WATER || mat[k] === SKY) continue;
const dx = xx + 0.5 - x, dy = r + 0.5 - ly;
const d = Math.sqrt(dx * dx + dy * dy);
// the lamp, and the pool of light it throws on the stone round it
const v = Math.exp(-((d / 0.6) ** 2)) * 1.3 + Math.exp(-d / 1.4) * 0.12;
const p = Math.exp(-d / halo) * 0.3 * alb[k];
sR[k] += v + p * WASH[0], sG[k] += v * 0.76 + p * WASH[1], sB[k] += v * 0.42 + p * WASH[2];
}
}
const wl = wlF(x), width = 0.35 + 0.35 * s, len = 9 * s;
for (let r = Math.floor(wl); r < H; r++) {
const a = Math.exp(-(r + 0.5 - wl) / len) * 0.5;
if (a < 0.01) break;
for (let xx = Math.floor(x - 3); xx < x + 3; xx++) sref[r * W + xx] += a * Math.exp(-(((xx + 0.5 - x) / width) ** 2));
}
x += (5 + 10 * hash(x | 0, 77)) * Math.max(0.8, s);
}
// --- the reflection: the bank and sky mirrored at the waterline -----------
const refl = [new Float32Array(N), new Float32Array(N), new Float32Array(N)];
const mirK = new Int32Array(N).fill(-1); // the lit cell each water cell mirrors
for (let r = 0; r < H; r++) {
for (let x = 0; x < W; x++) {
const k = r * W + x;
if (mat[k] !== WATER) continue;
const wl = wlF(x + 0.5), d = r + 0.5 - wl;
let ar = 0, ag = 0, ab = 0;
for (let o = 0; o < 2; o++) {
const ym = wl - d * 0.85 - 0.4 - o * 0.8;
let cr: number, cg: number, cb: number;
const q = ym < 0 ? -1 : Math.floor(ym) * W + x;
// the rippled water stretches the sky's light down toward us
const i = rampAt(skyHeat(x + 0.5, Math.max(0, wl - d * 0.36 - 1 - o * 0.6))) * 3;
if (q < 0 || mat[q] === WATER || mat[q] === SKY) (cr = RT[i]), (cg = RT[i + 1]), (cb = RT[i + 2]);
else {
// tilted ripples under the bank still catch a little sky
(cr = sR[q] + RT[i] * 0.22), (cg = sG[q] + RT[i + 1] * 0.22), (cb = sB[q] + RT[i + 2] * 0.22);
if (o === 0) mirK[k] = q;
}
ar += cr, ag += cg, ab += cb;
}
const a = 0.8 - 0.4 * smooth(HZ, H, r);
refl[0][k] = (ar / 2) * a, refl[1][k] = (ag / 2) * a, refl[2][k] = (ab / 2) * a;
}
}
// --- clouds: long dusk streaks, dark on top and lit from below --------------
const CW = 800, CH = HZ - 6;
const cover = new Float32Array(CW * CH);
const clit = new Float32Array(CW * CH);
// stretched, warped noise, gathered into three loose bands
const density = (x: number, y: number) => {
const q = fbm(x * 0.005, y * 0.03, 3, 4);
const d = fbm(x * 0.0125 + q * 1.8, y * 0.09 + q * 0.9, 5, 10);
const env = 0.03 * Math.exp(-(((y - 13) / 4) ** 2)) + 0.1 * Math.exp(-(((y - 29) / 5.5) ** 2));
// and one thin, broken streak low down, to cross the glow
const c = 46.5 + 3 * (fbm(x * 0.01, 9.5, 2, 8) - 0.5);
const th = 1 + 0.9 * fbm(x * 0.05, 3.5, 2, 40);
const streak = Math.exp(-(((y - c) / th) ** 2)) * smooth(0.42, 0.6, fbm(x * 0.0125, 21.5, 3, 10)) * (0.75 + 0.5 * fbm(x * 0.05, y * 0.3, 3, 40));
return Math.max(d + env - 0.08, 0.36 + 0.3 * streak);
};
for (let r = 0; r < CH; r++) {
for (let x = 0; x < CW; x++) {
const y = r + 0.5;
const d = density(x, y);
cover[r * CW + x] = smooth(0.47, 0.62, d);
// the undersides catch the light from below the horizon, the tops go dark
clit[r * CW + x] = clamp(0.4 + (d - density(x, y + 2)) * 5.5 + (density(x, y - 2.5) - d) * 1.5);
}
}
// --- the floating diyas ------------------------------------------------------
const diyas: [number, number, number, number][] = [];
for (let i = 0; i < 34; i++) {
const q = hash(i, 61);
const y = HZ + 5 + 34 * Math.pow(q, 1.3);
diyas.push([hash(i, 62) * 260 - 30, y, hash(i, 63) * 50, 0.6 + 0.6 * hash(i, 64)]);
}
const dyn = [new Float32Array(N), new Float32Array(N), new Float32Array(N)];
const dref = new Float32Array(N); // warm light to be reflected
const arm = new Uint8Array(N); // the priests' raised arms, this frame
const addGlow = (fx: number, fy: number, core: number, halo: number, amp: number) => {
const R = Math.ceil(halo * 3.2);
for (let r = Math.max(0, Math.floor(fy - R)); r < Math.min(H, fy + R); r++) {
for (let x = Math.max(0, Math.floor(fx - R)); x < Math.min(W, fx + R); x++) {
const k = r * W + x;
const dx = x + 0.5 - fx, dy = (r + 0.5 - fy) * 0.85;
const d = Math.sqrt(dx * dx + dy * dy);
// a white-hot heart inside an orange halo; the priests are not lit
const am = mat[k] === FIG ? amp * 0.15 : amp;
const c = Math.exp(-((d / core) ** 2)) * 1.6 * am, v = Math.exp(-d / halo) * 0.35 * am;
dyn[0][k] += c + v * FLAME[0], dyn[1][k] += c * 0.86 + v * FLAME[1], dyn[2][k] += c * 0.55 + v * FLAME[2];
}
}
};
// the lamps' wide warm wash on the stone, by how much each surface takes it
const addWash = (fx: number, fy: number, halo: number, amp: number) => {
const R = Math.ceil(halo * 2.6);
for (let r = Math.max(0, Math.floor(fy - R)); r < Math.min(H, fy + R); r++) {
for (let x = Math.max(0, Math.floor(fx - R)); x < Math.min(W, fx + R); x++) {
const k = r * W + x;
const a = alb[k];
if (!a) continue;
const dx = x + 0.5 - fx, dy = r + 0.5 - fy;
const v = Math.exp(-Math.sqrt(dx * dx + dy * dy) / halo) * amp * a;
dyn[0][k] += v * WASH[0], dyn[1][k] += v * WASH[1], dyn[2][k] += v * WASH[2];
}
}
};
const addStreak = (fx: number, wl: number, width: number, len: number, amp: number) => {
for (let r = Math.max(0, Math.floor(wl)); r < H; r++) {
const dy = r + 0.5 - wl;
const a = Math.exp(-dy / len) * amp * smooth(-0.5, 1, dy);
if (a < 0.01) break;
for (let x = Math.max(0, Math.floor(fx - 3 * width - 1)); x < Math.min(W, fx + 3 * width + 1); x++) {
const k = r * W + x;
if (mat[k] === WATER) dref[k] += a * Math.exp(-(((x + 0.5 - fx) / width) ** 2));
}
}
};
// the boat crossing the bright reach
const BS = 0.85;
const boatAt = (lx: number, ly: number) => {
// local coordinates: lx along the boat, ly up from the waterline
const L = 9;
if (Math.abs(lx) < L && ly > -0.6 && ly < 1.2 + 1.4 * Math.pow(Math.abs(lx) / L, 3)) return 1;
if (lx > 4.6 && lx < 5.8 && ly > 0 && ly < 6.6) return 1; // the boatman
if (Math.abs(lx - 5.2) < 0.7 && Math.abs(ly - 7.2) < 0.7) return 1;
const ox = lx - 5.6, oy = ly - 5.4; // his oar, raked back into the water
const along = ox * 0.42 - oy * 0.91;
if (along > 0 && along < 8 && Math.abs(ox * 0.91 + oy * 0.42) < 0.32) return 1;
if (lx > -4 && lx < -0.5 && ly > 0 && ly < 2.6 - 0.25 * Math.abs(lx + 2.2)) return 1; // a passenger
return 0;
};
return (t, { color } = {}) => {
for (let c = 0; c < 3; c++) dyn[c].fill(0);
dref.fill(0);
// aarti: each lamp is raised and turned in slow circles
arm.fill(0);
aarti.forEach(([ax, sw, sl], i) => {
const s = scF(ax), u = 1.3 * s, base = wlF(ax) - 2.6 * s;
const ph = t * 1.1 + i * 1.3;
const fx = ax + 0.9 * u + Math.cos(ph) * 1.1 * u, fy = base - 7.2 * u + Math.sin(ph) * 0.6 * u;
// the arm from the shoulder to the lamp
const sx0 = ax + 0.62 * u, sy0 = base - 3.8 * u;
const ex = fx - sx0, ey = fy + 0.6 * u - sy0, el = ex * ex + ey * ey;
for (let r = Math.floor(Math.min(sy0, fy) - 1); r <= Math.max(sy0, fy) + 1; r++) {
for (let x = Math.floor(Math.min(sx0, fx) - 1); x <= Math.max(sx0, fx) + 1; x++) {
if (x < 0 || x >= W || r < 0 || r >= H) continue;
const px = x + 0.5 - sx0, py = r + 0.5 - sy0;
const q = clamp((px * ex + py * ey) / el);
if (Math.hypot(px - q * ex, py - q * ey) < 0.28 * u) arm[r * W + x] = 1;
}
}
const fl = 0.85 + 0.15 * Math.sin(t * 13 + i * 5) * Math.sin(t * 7.3 + i);
addGlow(fx, fy, 0.6 * u, 1.7 * u, fl);
addWash(fx, fy + 2 * u, 7.5 * s, 0.34 * fl);
addStreak(fx, wlF(fx), 0.8 * s * sw, 15 * s * sl, 0.75 * fl);
});
// the step lamps
for (const [k, ph] of stepLamps) {
const v = 0.7 + 0.3 * Math.sin(t * 5 + ph);
dyn[0][k] += v * FLAME[0], dyn[1][k] += v * FLAME[1] * 0.95, dyn[2][k] += v * FLAME[2];
}
// diyas drifting downstream, nearer ones faster
for (const [x0, y, ph, sz] of diyas) {
const near = (y - HZ) / (H - HZ);
const x = ((((x0 + t * (0.25 + 0.9 * near)) % 260) + 260) % 260) - 30;
if (x < -3 || x > W + 3 || y < wlF(x) + 0.8) continue;
const fl = 0.8 + 0.2 * Math.sin(t * 9 + ph);
const s = (0.35 + 0.9 * near) * sz;
addGlow(x, y - 0.3, 0.45 + 0.3 * s, 0.6 + 1.2 * s, fl * 0.8);
addStreak(x, y + 0.2, 0.3 + 0.35 * s, 2 + 5 * s, 0.6 * fl);
}
const drift = t * 0.9 + 720; // starts with the long streaks over the glow
const bx = ((((159 - t * 0.1 + 24) % 250) + 250) % 250) - 24, by = 71 + Math.sin(t * 0.9) * 0.15;
for (let r = 0; r < H; r++) {
const y = r + 0.5;
for (let x = 0; x < W; x++) {
const k = r * W + x;
const m = mat[k];
let cr = sR[k], cg = sG[k], cb = sB[k], floor = flo[k], fade = 1, star = false;
if (m === SKY) {
if (r < CH) {
const sx = x + drift, ix = Math.floor(sx), fx = sx - ix;
const i0 = r * CW + (ix % CW), i1 = r * CW + ((ix + 1) % CW);
const c = cover[i0] + (cover[i1] - cover[i0]) * fx;
if (c > 0.01) {
// high streaks glow rose from below; low ones stand dark against
// the afterglow with only their undersides lit, gold near the glow
const l = clit[i0] + (clit[i1] - clit[i0]) * fx;
const lo = smooth(12, 30, y);
const lit = mix(0.3 + 0.7 * l, 0.9 * l * l, lo);
const i = rampAt(0.56 + 0.38 * warm[k] + 0.08 * l) * 3;
const kr = mix(0.075, RT[i], lit), kg = mix(0.05, RT[i + 1], lit), kb = mix(0.15, RT[i + 2], lit);
cr = mix(cr, kr, c), cg = mix(cg, kg, c), cb = mix(cb, kb, c);
floor = mix(floor, 0.06, c * (1 - lit));
} else if (y < 24 && hash(x, r * 3 + 11) > 0.993) {
const tw = 0.4 + 0.25 * Math.sin(t * (1.3 + hash(x, r) * 2) + hash(r, x) * 6.28);
cr = Math.max(cr, tw * 0.9), cg = Math.max(cg, tw * 0.88), cb = Math.max(cb, tw);
star = true;
}
}
} else if (m === WATER) {
const v = (y - HZ) / (H - HZ);
const w = 0.6 * noise(x * 0.05 + t * 0.08, y * 0.45 - t * 0.45, 0) + 0.4 * noise(x * 0.16 - t * 0.15, y * 0.95 - t * 0.9, 0);
const swell = 0.55 + 0.9 * w;
cr = 0.035 * swell, cg = 0.045 * swell, cb = 0.12 * swell;
const wob = (noise(x * 0.04 + 7, y * 0.3 - t * 0.6, 0) - 0.5) * (1.2 + 4 * v);
let sx = x + wob;
if (sx < 0) sx = 0;
if (sx > W - 1.001) sx = W - 1.001;
const i0 = r * W + (sx | 0), fx = sx - (sx | 0);
const dash = smooth(0.25, 0.75, noise(x * 0.12 + 3, y * 0.8 - t * 1.1, 0));
const ref = (a: Float32Array) => a[i0] + (a[i0 + 1] - a[i0]) * fx;
// broken bands, except in the bright reach under the glow
const reach = Math.exp(-(((x + 0.5 - GLOW[0]) / 15) ** 2)) * smooth(HZ + 2.5, HZ + 5.5, y);
const da = mix(0.15 + 1.1 * dash, 0.7 + 0.5 * dash, reach);
cr += ref(refl[0]) * da, cg += ref(refl[1]) * da, cb += ref(refl[2]) * da;
// the lamplit stone above, given back in broken bands
const q = mirK[k];
if (q >= 0) (cr += dyn[0][q] * 0.4 * da), (cg += dyn[1][q] * 0.4 * da), (cb += dyn[2][q] * 0.4 * da);
const fl = (ref(dref) + ref(sref)) * (0.2 + 1.1 * dash);
cr += fl * FLAME[0], cg += fl * FLAME[1], cb += fl * FLAME[2];
// a narrow road of glitter straight under the glow
const gw = 1.3 + (y - HZ) * 0.15;
const gx = (x + 0.5 - GLOW[0]) / gw;
if (gx > -3 && gx < 3) {
const road = Math.exp(-gx * gx) * Math.exp(-(y - HZ) / 24);
const rip = noise(x * 0.45 + y * 0.1 - t * 0.3, y * 1.3 - t * 1.6, 0);
const glint = smooth(0.42, 0.78, 0.45 * w + 0.55 * rip) * road;
cr += 1.0 * glint + 0.12 * road, cg += 0.78 * glint + 0.07 * road, cb += 0.42 * glint + 0.04 * road;
}
floor = 0.12;
fade = smooth(H + 4, H - 16, y);
}
// the boat and its dark reflection
const lx = x + 0.5 - bx;
if (lx > -14 && lx < 15 && r > by - 11 && r < by + 11) {
let cov = 0, rc = 0;
for (let sy2 = 0; sy2 < 2; sy2++)
for (let sx2 = 0; sx2 < 2; sx2++) {
const px = (lx - 0.25 + sx2 * 0.5) / BS, py = (by - (r + 0.25 + sy2 * 0.5)) / BS;
cov += boatAt(px, py);
if (m === WATER) rc += boatAt(px, -py * 0.9);
}
cov /= 4, rc /= 4;
if (cov > 0) {
cr = mix(cr, 0.035, cov), cg = mix(cg, 0.022, cov), cb = mix(cb, 0.035, cov);
floor = mix(floor, 0.02, cov), star = false;
} else if (rc > 0) (cr *= 1 - 0.8 * rc), (cg *= 1 - 0.8 * rc), (cb *= 1 - 0.75 * rc);
}
if (arm[k]) (cr = 0.035 + dyn[0][k] * 0.12), (cg = 0.022 + dyn[1][k] * 0.12), (cb = 0.035 + dyn[2][k] * 0.12), (floor = 0.02);
else (cr += dyn[0][k]), (cg += dyn[1][k]), (cb += dyn[2][k]);
const peak = Math.max(cr, cg, cb, 1e-4);
const level = clamp(floor + (1 - floor) * Math.pow(peak, 0.72) * 0.95) * fade;
const step = Math.max(0, Math.min(3, Math.round(level * 3 + BAYER[(r & 3) * 4 + (x & 3)])));
out[k] = DOTS[step];
if (color) {
if (star) color[k] = STAR;
else {
const want = step ? Math.min(1, (level + 0.06) / COVER[step]) : 0;
const s = Math.min(LIFT[step], (0.3 + 0.7 * want) / peak);
color[k] = nearest(clamp(cr * s), clamp(cg * s), clamp(cb * s));
}
}
}
}
const lines: string[] = [];
for (let r = 0; r < H; r++) lines.push(out.slice(r * W, (r + 1) * W).join(""));
return lines.join("\n");
};
}