sunset on lake pichola, udaipur's palaces glowing over the water
scenes 200×100 15 fps 31 colours, on a canvas 26.0 kB [report a bug]
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · • · · ··· ······································●································································ ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··• ··· ··· ··· ··· ··· ··· ··· ··· ·· · · · · · · · ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· · · · · · · · · · · · · · · · · · · ·●· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ········································································································································································································ · · · · · · ··· ··· ··· ··· ··· ··· ··· ··· ··· ··················· ··· ··· ··· ··· ··· ··· ··· ··· ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··································································································································································•·•·•·•·•·•·•·•·•····················· ·················································•·•·•·•·•·•·•················································ ········•·•·•••••·•···· ··· ··· ··· ··· ··· ······•·•·•·•••·•·•·•·•·•·•·•·•···•···•···•·• ····································•···•···•···•···•·•·•·•·•·•·•···•···•···•···•···································································•••••••·•·•·•·•·•···························•···•·•· ···························•·•·•···················································································· ··· ··· ··· ··· ··· ······•·••••••●••••••••·•······ ··· ··· ··· ······•·••●•●•●•●•● ··································•···•···•···•···•···•···•···•···•···•···•···•···•···································································································•·•••••••••·•·•·•· ·············································································································•·•·•·•·•·····················································•·•••••••·•·················· •···•···•···•·•·•···•···•···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·······························•···•·•·•••••••·•·•·•·•·•••·•••• ·······························•···•·•·•·•·•·•·•·•·•·•·•···•···•·······•···•·•·•·••••••••••••••••••••••••••••••••••••••••••●••••••••·······················································•·••••●•●•●•● ··•···•···•···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·••••••••●•••●•••●•●•●•●•●●●•●•●•●•●•●•●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•●•●•●•●•●•●•●••·•···•···•···•···················•···•·•·•·••••••●•●•●•●•●• ·················•·•·•·•·•·•·•·•·•···•···•···•···•·•·•·•·•·•·•·•·•···•···•···•·•·••••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●••••••·•·•·•···············································•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••••••••••·•·•·•·•·•·•·•••·••••●•●•●●●•●●●•●•●•●••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ···········•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·••••••••••●•••●••••••••·•·•·•·•·•·•·•·•···•···•···•···•···································································•·•••••••·•·················· •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•••••••••••••••••••••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•···•···•···•···•···•···•···•···•···•···•·······················•···•···•···•·· •·•·•·•·•·•·•••·•••·•••·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•••·•••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•···•···•···•···•·●·•···•·•·•••••••••••••·•·•·•·•·•·•·•·• •·•••·•••·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•●•·•·••••●•●•●•●•●•●•●•●•●••••••••••••• ·•·•·•·•·•·•••·•••·•••·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·• ••••••••••••••••••••••••••·•●•••●•••●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••●●●●••••·•••·•••·•••·•••••••••••••••••••• ·•••·•••·•••·••••••••••• · · ••••••••••••••••••●•••●•••●•••●•••●••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·●•●•●·•·•·•·•·•·•·•·•·●••·•••·••••••••••● ••••••••••••••••••●•••●•· ···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•··· ·•●•●•●•●•••●•••●•••●•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••●●●•●●●••••••••••••••••●●•●•●•●•●•●•●•●•●• •••••••••••••••••••••••• · · ••••●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••••••••••••••••••••••••••••••••••••••••••••••••••••••●••••••••••••·••••●•●•●••·•••·•••·•••·••●·••••••●•●•●•●•●•● ●•••●•●•●•●•●•●•●•●•●•●•··· ·•●•●•●•●•●•●●●•●●●•●●●●●●●●●●●●●●●●●●●•●●●•●•·····•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•••●••••••••●••••••••••••••••●●●●●•●••••••••••••••●●●●•••••••••••••●•●• •••••••••••••••••••●•••● · · ••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••••••••••••••••••••••••••••••••••••••••••••●••••••••••••••••●●•●●●•••••••••••••••●•●•●••••·•••·•••·••• ●•●•●•●•●•●•●•●•●•●•· ●•· ●··•●··•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•··● ·•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●●●•●•••●•••●•••●•••●●●●●●●•●•••••••••••●●●•●••••••••••••••••• •●•••●•••●•●•●•●•●•· · ● · · ● · ·•●•●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•● ●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•••●•••●•••••●•●•●•••••••••••••••●●·•●●••••••••••••••●•●•●•••••••••••••••• ●•●•●•●•●•●•●•●•●●●•··· ··· ··· ·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●·●●●·●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●●●•●•●•●•●•●•●•●•●●•··●●•●•●•●•●•●•●•●●●●●●●•●•●•●•●•●•●•●• •●•●•●•●•●•●•●•●•●•● · · · · · · ●•●•●•●•●●●•●●●●●●●●●●●●·●●●·●●●● ●●● ●•● ● ●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•●•●••••••••••••••●●···●•••●•●•••●•●••●●•●•●•••••••••••••••• ●•●•●•●●●•●●●•●●●•●●· ●··•··● ·•·●●●●●●●●●●●●●●●●●●●●●●●●●·●·●●●●●●·● ●●●●●·●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●●●●●•●•●•●•●•●•●•●●●●●●●•●●●•●•●●●●●•●●·●●●●•●•●•●•●•●•●•●• •●•●•●•●•●•●•●•●•●•● · · · · · · ●•●●●●●●●●●●●●●●●●●●●●●●●●·●●●●●●●● ●●●●●●●●●●●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●•●•●•●•●•●•●•●•●•●●●•●●●•●•●••●●•●•●•···•●•●•••●•••●•••●•• ●●●•●●●●●●●●●●●●●●····· ··· ··· ···●●●●●●●●●●●●●●●●●●●●●●●●●●●··●··●●·····●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●●•●●●●●●●●●●●●●●•●•●●●•●●●•●●●•●•●●●•●•●·•·●●●•●•●•●•●•●•●•●• •●•●•●•●•●•●•●•●•● · · · · · · · · ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●···•●•●•●•●•●•●•●•●●●•●•●•●●●•●●●•●●●•●●●•●●●•••●•••●•●•●•••● ●●●●●●●●●●●●●●●●●●··· ······· ··· ·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●●●●●•●···●●●•●●●•●●●•●•●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●• •●•●●●•●●●•●●●•●●● · ········· · · ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●●●•●•●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●·●•●•·•●•●•●·●•●•●•●•●•●•●•●•●•● ●●●●●●●●●●●●●●●●●●·················●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●·•·●●•··●●●●·•·●●●●●•●●●•●●●•●●●• •●●●•●●●•●●●●●●●●● ············· · ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●●●•●•●•●•●·●•●•●•●•●●●•·•●•●•···•●···●•●●···•●•●•●•●•●•●•●•●•● ●●●●●●●●●●●●●●●●●················ ·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●·•·●●●●●●●•●●···●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●● ●●●●●●●●●●●●●●·•·················· ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•●•●•●•●•●•●•●•●•···•●●●•●•●•●···●•●•●•●•●•●•●•●•●●●•●•●·●•●•·•●•●·●•● ●●●●●●●●●••·•·•·•···•···········•··●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•·●●•●·●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•·●●•●•●•●●●●•●●•●···●●···●●···●• ●●●●●●●•················ ··· ······•●●●●●●●●●●●●●●●●●●●●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●●●•···•●···●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•···•●•••●•●•···•●•···•●···●•···•● ●●●●●·•···•·······················•·••●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●●●●●•●···●•···•●•●●·•●•●•●•●•●•●·●•●•●●●·●•●•●···●•●•●•●•●···●•●•●●●•●●●•●●●•●● ●●●●·················· ··· ··········•·●●●●●●●●●●●●●●●•●●●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●•●●●●●●●•●•●•●•●•●•●•···•●•●•●•●•●···●•●•●···●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•● ●●●·•·······························•·•·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●●●•●•●•●•●•●•●•●···●•●•●•●•●•···•●•●•···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•·•●• ●●······ ······· ··· ··· ··· ············•●●●●●●●●●●●●●●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●••●•••●•••●•••••••●•••●•·•●•••●•••●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•••●•••••●•●•••●•••· ·•● ●·•···································•·•·••●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●•●•●•••●•●•●•●•●•●•●•●•●•···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●●●•●•●•●•●•●•●•●•●●●•●•●•●···●• ·················· ··· ··· ··· ··············•·•●●●●●●•●•●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•••••••••••••●•••●•••●•●•●••·· ••●•••••••●•••●•••●•••●•••·•••●•●●●•••●•••●•●•●•••●•••●•••●•••●•• •···································•···•·•·•·•·••••●●●•●•●•●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●•●•●•●•••●•●•●•●•●·●•●•●•●•●•●•●•●•●•●●●•●•●●●●●•●•●•●•●•···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●• ···· ··· ··· ··· · · · · ··· ··· ··················•·••••••••●●●●●●●●●●●●●●●●●●●●●•●●●●●●●●●●●●●●●•●•••••••••••••••●•●•• ··••••••••••••••••●•●•••••●•●•••••••••• ··••••••••••••••••••••••••••••·•••••••• ··········································•···•···•·•·••••●•●●●●●●●●●●●●●●●●●●●●●•●•●●●●●●●●●•●•●•●•●•●•●•●•••●•••●●●●●•···•••●•·•●••·●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•·•●••·●•••●•·•●•••●•••···•●●●●●• ······ ··· ··· ··· ··· ··· ··· ··· ······················•·•●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••••••••••••••••••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•• ··· ··· · · ··· ····························•···•·•·•·•·•·•·••●●●●●•●●●●●●●•●•●●●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●• · · · · · · · · · · · · · · ··· ··· ··· ······················•·●•●•●•●•••●•••●•●•●•••●•••●•••••••••••••••••••••••••••·•••••••••••·•••••●•••••●•••••●•••••●•••••·•••••●•••••·•••••●•••••·•••••·•••••·•• · · · · · · · · · · · · · ····· ··················•···•···• · · •·•••●●●●•●•●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••••●••··•●•●•●•●••··•●•●●●•●•●●●•●•●●●•●•●•●•●•··••●•●•●•●•··••●•●●●•●•··••●••··•●•··•• · · · · · · · · · · · · · · · · · ··· ········· · · · · · · · · · ··•••·●·•·••●•●•●•●•··•·●·•••·•·•·•·•·•·•·•···•·••●···●•••●•••●···●••●●•••●•●•●•••●•••●•●●●••···••●•●•●••···••●•●•●••···••●···●••···• · · ··· ··· ··· · · · · ··· · · · · ··· ··· ··· ··· · · ··· · · ··· ·●●●●●●●●●●●●●●●●●●●●●●•●●●·•·•·•·· ··· · ··•··•●•··••●•●•●•●•··••●•●●●•●•●●●•●•●●●•●•●•●•●••··•●•●•●•●••··•●•●●●•●••··•●•··••●••··• · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·•· ●•●•●•●•●•●•●•●•●•●•●•●•●•· • · · · · · ·•• ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• · ··· ··· · · · · · · · · · · · · · · ··· · · · · · · · · · · · ·●●●·●●·●●●●••●●●•●●●••●●•●•●•● ●•● · · · · · ●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●● ·········· ··· ··· ··········· ··· ··· ··· ··················· ·●●•●•●···●•··••●•●•●••··•●•●•●•●•●••······ ··•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·••••••••• ··························································•••····●●·●●•·•●●·•·●●●●●•●·•·●●●•●●●·●•·•··········•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••••••••••••••••••••••••••·•·•·•·•·•·•·•·•·•·•· · · · · ··· ··· ··· ··· ··· · · · · · · · · · · · · · · · · · ·•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●···· · · · · ······· ··········· ················•·•········ · ······•·•···•·•••••·• ····· · ··· ··· · ··· ······················· ··· ··············· ··· ··· ··· ··●●●●●●●●●●●●●•●●●•●●●•●●●•●•●•●•●•●•··•···•···•···········•·•·•·•···•·•••••••••·•·•·•·•·•·•·•·••···••·•·•·•·······•···············••···• ·· ··· ··· ··· ··· ··· ··· ··· · · · · · · ··············· · · ·●●·●●●•·•●•●•●•●•••●•●·●•●•●•●•●·●•●••••••········ ··· ··•·•••·••····•·•·•·•·•·············•••·•···•••·•••·•···•••••••·•·· ··•···•·•···• ························································••●•●•●•●·•·●●•·•●●•●•●●•·••●·•·●●●•●●●·•·●•••••••••••••••••●••·•••·•·•·•·•·•·•·•••·•••••••••••••••·•···•···•···•••••··••••••••••·••••·••••••·•• · · · · · · ··· ··· · · · · · · · · · · ··· ··· ··· ··· ····•·••··••●·•·●•●•●•●···●•···•●•●•●•···•●••••••••·•••·•••·•·•···········•·•••·•••·•••·•••·•••·•••·•·•·•·•·······························•·•·• ············· ··· ··· ··· ··· ··· ················•·•·•·•·••●•●•●●●●●●●●●●●●●•●●●•●●●•●●●•●•●•●•●•●••••••••••••••••••••••·•·•·•·•·•••••••••••••••••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•····· ······ · · · · · · · · · · · · ······························•··•●·●•●•·•●•●·●•●•·•●•●·●•●•·•●•●·●••·····•·•••·•••·••●·•·· ··•···•·•·•·•••••••·•·•·•·····•·•••·•••·•••·•·•·•···•·•·•·•·•·•·•·• ········· ············································•·•·••••●•●●●••·•••·●●••●●●·●●●••●●•●·●•●•••●•●·●•●•••●••••••••••···•···•·•·•···••••••••••••••••●••·•···•···•···············•·•••·•·••••·••·•••·•·•·•••·•••· ··········· ··· ··· ··· ··· · · · · · · · ····•·••••●••••·•···•···•·•···•·•·•·•··••••··••••·•·•·······•·•·•·•••·•••·•••·•••·•••·•••·•••·•••••·•·•·•••·•·•••·•·• ··•·•·•·•·•···························· ····················· ··· ··· ·············••···•·•···•·••●●●●●●●•●••···•·•·•·•···••••••●●●●●●••·••••••••••••·•···•···•···•···•······ ····•···················•···•·•·•••·•···•···•·•·•••••••·•••·•••·•• ·········· · · · · · · · · · · ··········•·●••·•·•···•···•·•·•••••••••••••••••••••·····●•●•●•●•••••••●•●••·•···························•·•·•·•·•••·•••·•••·•·················•·•·•·•·•·•·•·•·•·•···· ··· ●••·•·······························•·•·•●●•●••••••·•·•·•·•·•·•·····•···•••••••·•·••• •·●··•·•••●•••●•●•●•••••••••••●•••••••••••••••··•·•·•·•···•···•···•···•···•···•·······•···•·•·•••••••••••••••····· ·•••················ ··· ··· ··········••●●●●●●●●●●●••••·•·•···•···•···••••••••···••· ··•· · •·· ··········•···•·•·•···•·•·•···•·•·•·•••·•••··••·•·•···• ····•·•·•·•·•·•·•···························· · ●•●•●·•·································•·•••·•••••••·•·•·••••••••••●•●•●•●•●•●•●·•••●●●●●●●●●●●●•••●•●•●•●•●•●•●•●•●•●•••●••••••·•·· ····•·· •···•···•·•···•••••···•••••••·········· ·················· •••••●•··············· · · · · ······•·●●●●●●●●●●●●●●●●●●●•••••●•••••●•••●•●•●•●•••●••·•·•·•·•·•·•·•·••••●•●•●•●•●••••••·•···•·· · ·····••••··••••·•·•···• •••·••···••·•·· ········· · •·•·•·•·•·•·•···· ●•●•●•●••···•·······················••••••●•●●●●●●●●●●●•●••·•••·••••●•●•●•●•●●●●●•●●●●•·•·•·•·•·••••●•●•●••·•·•·•·•·•·•·•·•·•·•···•····•••••·••••●●●●●●●●●●••···•···•·······••••••••···•••···••··••••••• •••●•••●••·············· ··· ·····•●•••••••••••●•••●••·•·•·•·•••·•••·•·•••·•·••●••••••··········••·•·•·•·••••••●••••••••·•·•···· ··•··•••••••••••●•●•●•●•●•●·•·•···········•·•·•·•·•······ · ··· ··· ··· ●•●•●••·•·•·•·•·· ··············· ••••••••●●●●●●●●●●●●●●●●●●●●●●●●●●●·•·••····•·•·•···············•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•·•·•·•·•●●•●●●•●●●•●●●·•·• ····•·•·•·•·•·•·•·················· •· ·····•·••●••••·················· ··•·•·•·•·••●●●●●●●●●●●●●●●●●●●●●••●•···········•·••··•·•·•·················•·•••·•·•·············••••••••••••••● · ·•· ·•••• ••···••••••·•·•·•·•·•·•·•·•·•·•···•······ •·•·•·••••••●•●•●···•·············•••••••••••••·•••·••••●●●●●●●●●●●●●●●·●•●•••••●••••••••••·•···•·•·•·•·•·•·•·•·•·•·•·•·••••●••••••·•·•·•·•·•·•·••········●•••·•••··•·•·········•·····•·•••••••••••••••• ••••••••·•·•·•·•·· ··········· · ●●●•●●●•●●●•●●●•●●●●●•●••••·•·•·•·•••••••••••••••·•·•·•·•·•·•·•••••••••••••••••••••••••·•·•···•·······•···•·•·•·• · · · ·••·• •·•·•·•·· ·•• ··•·••· ······•···•···•···• ••••••●•••●•●•●•••··· ······· ··●•●●●•●●●•●●●•●●●•●•●•●●●•●●●•●•●•●••·•···•·•·•···••••••••●••••••·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•·•·•·●●●●●●●●●●●●●●●●●●●●•••••·•···•···•·•·•·•·•••••••••••·•·•·•· •••••••••••••••••• ··· ··· ··· ●•●•●•●•●•●•●•●•●•●●●●●●●●●●●●●●●●●●●●●••·•·•·•·•·•·•·•·•••·•••••••••••••••·•·•·•·•·•·•·•••••••••••·•••·•·• ··•·•·•·•·•·•·•·•·•·•·····•·•·••••●••••••••·•••·•••·•·•·•·•·• •·•·•·•·•···•···•·· ··· ··· ···•●●●•●●●•●●●•●●●•●●●●●●●●●●●●●●●●●●·•●••••••••••·•···•···•···•·•·•·•·•••·•••·•••••••·•·•·•···•···•·········· •·•·•·•·•·•·•·•·•·•·●•••••••●•●•●••••••••••••••••••·•••·•·•· ······················ · · · · · • · · · • · · ●•••●•●•●•●•●•●•●•••●•●•●•••●••••·•·•·•·•••••·•••·•·•·•·•·································•·······················•••••·•••••·•·•···· ··············•···• ······•••••••••••••·· ····· ·····•·············•●•●●●•●••·• ··•·······•···········•·•·•••••••••••·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•·········· ··· ··· · · ··· ··••••●•●•••●••·•••·•••··••·•·•·•········· ·•·•·•················ · · · · ● · · · · · · ●·•···•·•·····•·•·• • •···· ······•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•········ ··· ··· ··· ······· · · · · · · · · ··· · ··········•·•·•·•·•••·•·•········ · •••·•·•·•···•···•·•···• •·· ··· ••·············••·•·•·•·••··••·•••• •·• •·· • ··················•·•·•·•·•·•·•·•·•·•·•···························•···•···•···•···•·•·•·•·•·•·············•···•·•···•·•··· ···•·•·•·•·•·•·•···• · · ●•●•●•●•●•●•●•●•●•●•●•●•●•●•··· ··· ··· ··· ····· ··· · · · · · · · · · · · · · · · ······················· · · · · ··················· · · · · · · · · · · ······· ··· · · · · ··•···•·•·•·•·•••·•••····••••••••••••••••••••••••••••·•·•·•·•·•·•·•···•·······································•···•···•···•···•·······························•·· •···············•···•················· · · · ················•···•·•·•·•·•·•·•·•·•·•·•·•·• · · · · · · · ····•·•·•·•···· · · · · · · · · · · · · · · · · · · ··············· ······· · · · · · · · ······· · · · · · · · · · ··· ··· ··· · · · ············•·•·•···•·•···· •·•·•·•·•·•·•·•·•·•·•·•·•••·•······ ······•·•·•·•·•···· ··· ··· · · ··· ··· ··············· · · · · · · ··············· ··· ··················· · · · · ··················· · · ··· ············· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· ······· ··· · · ··· · · · · · · · · · · · · ······· ··· ··· · · · · · · · · ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · • · · ··· ······································●································································ ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··• ··· ··· ··· ··· ··· ··· ··· ··· ·· · · · · · · · ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· · · · · · · · · · · · · · · · · · · ·●· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ········································································································································································································ · · · · · · ··· ··· ··· ··· ··· ··· ··· ··· ··· ··················· ··· ··· ··· ··· ··· ··· ··· ··· ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··································································································································································•·•·•·•·•·•·•·•·•····················· ·················································•·•·•·•·•·•·•················································ ········•·•·•••••·•···· ··· ··· ··· ··· ··· ······•·•·•·•••·•·•·•·•·•·•·•·•···•···•···•·• ····································•···•···•···•···•·•·•·•·•·•·•···•···•···•···•···································································•••••••·•·•·•·•·•···························•···•·•· ···························•·•·•···················································································· ··· ··· ··· ··· ··· ······•·••••••●••••••••·•······ ··· ··· ··· ······•·••●•●•●•●•● ··································•···•···•···•···•···•···•···•···•···•···•···•···•···································································································•·•••••••••·•·•·•· ·············································································································•·•·•·•·•·····················································•·•••••••·•·················· •···•···•···•·•·•···•···•···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•·······························•···•·•·•••••••·•·•·•·•·•••·•••• ·······························•···•·•·•·•·•·•·•·•·•·•·•···•···•·······•···•·•·•·••••••••••••••••••••••••••••••••••••••••••●••••••••·······················································•·••••●•●•●•● ··•···•···•···•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·••••••••●•••●•••●•●•●•●•●●●•●•●•●•●•●•●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•●•●•●•●•●•●•●••·•···•···•···•···················•···•·•·•·••••••●•●•●•●•●• ·················•·•·•·•·•·•·•·•·•···•···•···•···•·•·•·•·•·•·•·•·•···•···•···•·•·••••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●••••••·•·•·•···············································•·• •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••••••••••·•·•·•·•·•·•·•••·••••●•●•●●●•●●●•●•●•●••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ···········•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·••••••••••●•••●••••••••·•·•·•·•·•·•·•·•···•···•···•···•···································································•·•••••••·•·················· •·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•••••••••••••••••••••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•···•···•···•···•···•···•···•···•···•···•·······················•···•···•···•·· •·•·•·•·•·•·•••·•••·•••·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•••·•••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•···•···•···•···•·●·•···•·•·•••••••••••••·•·•·•·•·•·•·•·• •·•••·•••·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•●•·•·••••●•●•●•●•●•●•●•●•●••••••••••••• ·•·•·•·•·•·•••·•••·•••·•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·• ••••••••••••••••••••••••••·•●•••●•••●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••●●●●••••·•••·•••·•••·•••••••••••••••••••• ·•••·•••·•••·••••••••••• · · ••••••••••••••••••●•••●•••●•••●•••●••••••••••••••••••••••••••••••••••••••••·•••·•••·•••·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·●•●•●·•·•·•·•·•·•·•·•·●••·•••·••••••••••● ••••••••••••••••••●•••●•· ···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•··· ·•●•●•●•●•••●•••●•••●•••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••●●●•●●●••••••••••••••••●●•●•●•●•●•●•●•●•●• •••••••••••••••••••••••• · · ••••●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••••••••••••••••••••••••••••••••••••••••••••••••••••••●••••••••••••·••••●•●•●••·•••·•••·•••·••●·••••••●•●•●•●•●•● ●•••●•●•●•●•●•●•●•●•●•●•··· ·•●•●•●•●•●•●●●•●●●•●●●●●●●●●●●●●●●●●●●•●●●•●•·····•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•••●••••••••●••••••••••••••••●●●●●•●••••••••••••••●●●●•••••••••••••●•●• •••••••••••••••••••●•••● · · ••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••••••••••••••••••••••••••••••••••••••••••••●••••••••••••••••●●•●●●•••••••••••••••●•●•●••••·•••·•••·••• ●•●•●•●•●•●•●•●•●•●•· ●•· ●··•●··•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•··● ·•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●●●•●•••●•••●•••●•••●●●●●●●•●•••••••••••●●●•●••••••••••••••••• •●•••●•••●•●•●•●•●•· · ● · · ● · ·•●•●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•● ●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•••●•••●•••••●•●•●•••••••••••••••●●·•●●••••••••••••••●•●•●•••••••••••••••• ●•●•●•●•●•●•●•●•●●●•··· ··· ··· ·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●·●●●·●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●●●•●•●•●•●•●•●•●•●●•··●●•●•●•●•●•●•●•●●●●●●●•●•●•●•●•●•●•●• •●•●•●•●•●•●•●•●•●•● · · · · · · ●•●•●•●•●●●•●●●●●●●●●●●●·●●●·●●●● ●●● ●•● ● ●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•●•●••••••••••••••●●···●•••●•●•••●•●••●●•●•●•••••••••••••••• ●•●•●•●●●•●●●•●●●•●●· ●··•··● ·•·●●●●●●●●●●●●●●●●●●●●●●●●●·●·●●●●●●·● ●●●●●·●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●●●●●•●•●•●•●•●•●•●●●●●●●•●●●•●•●●●●●•●●·●●●●•●•●•●•●•●•●•●• •●•●•●•●•●•●•●•●•●•● · · · · · · ●•●●●●●●●●●●●●●●●●●●●●●●●●·●●●●●●●● ●●●●●●●●●●●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●•●•●•●•●•●•●•●•●•●●●•●●●•●•●••●●•●•●•···•●•●•••●•••●•••●•• ●●●•●●●●●●●●●●●●●●····· ··· ··· ···●●●●●●●●●●●●●●●●●●●●●●●●●●●··●··●●·····●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●●•●●●●●●●●●●●●●●•●•●●●•●●●•●●●•●•●●●•●•●·•·●●●•●•●•●•●•●•●•●• •●•●•●•●•●•●•●•●•● · · · · · · · · ●●●●●●●●●●●●●●●●●●●●●●●●●●●●● ●●●●●●●●●●●●●●●●●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●···•●•●•●•●•●•●•●•●●●•●•●•●●●•●●●•●●●•●●●•●●●•••●•••●•●•●•••● ●●●●●●●●●●●●●●●●●●··· ······· ··· ·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●●●●●•●···●●●•●●●•●●●•●•●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●• •●•●●●•●●●•●●●•●●● · ········· · · ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●●●•●•●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●·●•●•·•●•●•●·●•●•●•●•●•●•●•●•●•● ●●●●●●●●●●●●●●●●●●·················●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●·•·●●•··●●●●·•·●●●●●•●●●•●●●•●●●• •●●●•●●●•●●●●●●●●● ············· · ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●●●•●•●•●•●·●•●•●•●•●●●•·•●•●•···•●···●•●●···•●•●•●•●•●•●•●•●•● ●●●●●●●●●●●●●●●●●················ ·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●·•·●●●●●●●•●●···●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●•●●●•●● ●●●●●●●●●●●●●●·•·················· ●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●•●•●•●•●•●•●•●•●•●•···•●●●•●•●•●···●•●•●•●•●•●•●•●•●●●•●•●·●•●•·•●•●·●•● ●●●●●●●●●••·•·•·•···•···········•··●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•·●●•●·●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•·●●•●•●•●●●●•●●•●···●●···●●···●• ●●●●●●●•················ ··· ······•●●●●●●●●●●●●●●●●●●●●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●•●●●●●•···•●···●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•···•●•••●•●•···•●•···•●···●•···•● ●●●●●·•···•·······················•·••●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●●●●●•●···●•···•●•●●·•●•●•●•●•●•●·●•●•●●●·●•●•●···●•●•●•●•●···●•●•●●●•●●●•●●●•●● ●●●●·················· ··· ··········•·●●●●●●●●●●●●●●●•●●●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●•●●●●●●●•●•●•●•●•●•●•···•●•●•●•●•●···●•●•●···●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•● ●●●·•·······························•·•·●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●●●●●•●•●•●•●•●•●•●···●•●•●•●•●•···•●•●•···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•·•●• ●●······ ······· ··· ··· ··· ············•●●●●●●●●●●●●●●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●••●•••●•••●•••••••●•••●•·•●•••●•••●•●•●•●•●•●•●•●•●•••●•••●•••●•••●•••●•••••●•●•••●•••· ·•● ●·•···································•·•·••●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●•●•●•••●•●•●•●•●•●•●•●•●•···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●●●●●•●•●•●•●•●•●•●•●●●•●•●•●···●• ·················· ··· ··· ··· ··············•·•●●●●●●•●•●•●●●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•••••••••••••●•••●•••●•●•●••·· ••●•••••••●•••●•••●•••●•••·•••●•●●●•••●•••●•●•●•••●•••●•••●•••●•• •···································•···•·•·•·•·••••●●●•●•●•●•●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●•●•●•●•●•••●•●•●•●•●·●•●•●•●•●•●•●•●•●•●●●•●•●●●●●•●•●•●•●•···•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●• ···· ··· ··· ··· · · · · ··· ··· ··················•·••••••••●●●●●●●●●●●●●●●●●●●●●•●●●●●●●●●●●●●●●•●•••••••••••••••●•●•• ··••••••••••••••••●•●•••••●•●•••••••••• ··••••••••••••••••••••••••••••·•••••••• ··········································•···•···•·•·••••●•●●●●●●●●●●●●●●●●●●●●●•●•●●●●●●●●●•●•●•●•●•●•●•●•••●•••●●●●●•···•••●•·•●••·●•••●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•·•●••·●•••●•·•●•••●•••···•●●●●●• ······ ··· ··· ··· ··· ··· ··· ··· ······················•·•●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••••••••••••••••••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•••●•• ··· ··· · · ··· ····························•···•·•·•·•·•·•·••●●●●●•●●●●●●●•●•●●●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●•●• · · · · · · · · · · · · · · ··· ··· ··· ······················•·●•●•●•●•••●•••●•●•●•••●•••●•••••••••••••••••••••••••••·•••••••••••·•••••●•••••●•••••●•••••●•••••·•••••●•••••·•••••●•••••·•••••·•••••·•• · · · · · · · · · · · · · ····· ··················•···•···• · · •·•••●●●●•●•●•●●●•●•●•●•●•●•●•●•●•●•●•●•●•●•••●•••••●••··•●•●•●•●••··•●•●●●•●•●●●•●•●●●•●•●•●•●•··••●•●•●•●•··••●•●●●•●•··••●••··•●•··•• · · · · · · · · · · · · · · · · · ··· ········· · · · · · · · · · ··•••·●·•·••●•●•●•●•··•·●·•••·•·•·•·•·•·•·•···•·••●···●•••●•••●···●••●●•••●•●•●•••●•••●•●●●••···••●•●•●••···••●•●•●••···••●···●••···• · · ··· ··· ··· · · · · ··· · · · · ··· ··· ··· ··· · · ··· · · ··· ·●●●●●●●●●●●●●●●●●●●●●●•●●●·•·•·•·· ··· · ··•··•●•··••●•●•●•●•··••●•●●●•●•●●●•●•●●●•●•●•●•●••··•●•●•●•●••··•●•●●●•●••··•●•··••●••··• · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·•· ●•●•●•●•●•●•●•●•●•●•●•●•●•· • · · · · · ·•• ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• · ··· ··· · · · · · · · · · · · · · · ··· · · · · · · · · · · · ·●●●·●●·●●●●••●●●•●●●••●●•●•●•● ●•● · · · · · ●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●●●•●● ·········· ··· ··· ··········· ··· ··· ··· ··················· ·●●•●•●···●•··••●•●•●••··•●•●•●•●•●••······ ··•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••·•·•·•·•·•·•·••••••••• ··························································•••····●●·●●•·•●●·•·●●●●●•●·•·●●●•●●●·●•·•··········•···•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•••••••••••••••••••••••••••••••••••·•·•·•·•·•·•·•·•·•·•· · · · · ··· ··· ··· ··· ··· · · · · · · · · · · · · · · · · · ·•●●●•●●●•●●●•●•●•●•●•●•●•●•●•●•●•●•●···· · · · · ······· ··········· ················•·•········ · ······•·•···•·•••••·• ····· · ··· ··· · ··· ······················· ··· ··············· ··· ··· ··· ··●●●●●●●●●●●●●•●●●•●●●•●●●•●•●•●•●•●•··•···•···•···········•·•·•·•···•·•••••••••·•·•·•·•·•·•·•·••···••·•·•·•·······•···············••···• ·· ··· ··· ··· ··· ··· ··· ··· · · · · · · ··············· · · ·●●·●●●•·•●•●•●•●•••●•●·●•●•●•●•●·●•●••••••········ ··· ··•·•••·••····•·•·•·•·•·············•••·•···•••·•••·•···•••••••·•·· ··•···•·•···• ························································••●•●•●•●·•·●●•·•●●•●•●●•·••●·•·●●●•●●●·•·●•••••••••••••••••●••·•••·•·•·•·•·•·•·•••·•••••••••••••••·•···•···•···•••••··••••••••••·••••·••••••·•• · · · · · · ··· ··· · · · · · · · · · · ··· ··· ··· ··· ····•·••··••●·•·●•●•●•●···●•···•●•●•●•···•●••••••••·•••·•••·•·•···········•·•••·•••·•••·•••·•••·•••·•·•·•·•·······························•·•·• ············· ··· ··· ··· ··· ··· ················•·•·•·•·••●•●•●●●●●●●●●●●●●•●●●•●●●•●●●•●•●•●•●•●••••••••••••••••••••••·•·•·•·•·•••••••••••••••••••••••••••·•·•·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•····· ······ · · · · · · · · · · · · ······························•··•●·●•●•·•●•●·●•●•·•●•●·●•●•·•●•●·●••·····•·•••·•••·••●·•·· ··•···•·•·•·•••••••·•·•·•·····•·•••·•••·•••·•·•·•···•·•·•·•·•·•·•·• ········· ············································•·•·••••●•●●●••·•••·●●••●●●·●●●••●●•●·●•●•••●•●·●•●•••●••••••••••···•···•·•·•···••••••••••••••••●••·•···•···•···············•·•••·•·••••·••·•••·•·•·•••·•••· ··········· ··· ··· ··· ··· · · · · · · · ····•·••••●••••·•···•···•·•···•·•·•·•··••••··••••·•·•·······•·•·•·•••·•••·•••·•••·•••·•••·•••·•••••·•·•·•••·•·•••·•·• ··•·•·•·•·•···························· ····················· ··· ··· ·············••···•·•···•·••●●●●●●●•●••···•·•·•·•···••••••●●●●●●••·••••••••••••·•···•···•···•···•······ ····•···················•···•·•·•••·•···•···•·•·•••••••·•••·•••·•• ·········· · · · · · · · · · · ··········•·●••·•·•···•···•·•·•••••••••••••••••••••·····●•●•●•●•••••••●•●••·•···························•·•·•·•·•••·•••·•••·•·················•·•·•·•·•·•·•·•·•·•···· ··· ●••·•·······························•·•·•●●•●••••••·•·•·•·•·•·•·····•···•••••••·•·••• •·●··•·•••●•••●•●•●•••••••••••●•••••••••••••••··•·•·•·•···•···•···•···•···•···•·······•···•·•·•••••••••••••••····· ·•••················ ··· ··· ··········••●●●●●●●●●●●••••·•·•···•···•···••••••••···••· ··•· · •·· ··········•···•·•·•···•·•·•···•·•·•·•••·•••··••·•·•···• ····•·•·•·•·•·•·•···························· · ●•●•●·•·································•·•••·•••••••·•·•·••••••••••●•●•●•●•●•●•●·•••●●●●●●●●●●●●•••●•●•●•●•●•●•●•●•●•●•••●••••••·•·· ····•·· •···•···•·•···•••••···•••••••·········· ·················· •••••●•··············· · · · · ······•·●●●●●●●●●●●●●●●●●●●•••••●•••••●•••●•●•●•●•••●••·•·•·•·•·•·•·•·••••●•●•●•●•●••••••·•···•·· · ·····••••··••••·•·•···• •••·••···••·•·· ········· · •·•·•·•·•·•·•···· ●•●•●•●••···•·······················••••••●•●●●●●●●●●●●•●••·•••·••••●•●•●•●•●●●●●•●●●●•·•·•·•·•·••••●•●•●••·•·•·•·•·•·•·•·•·•·•···•····•••••·••••●●●●●●●●●●••···•···•·······••••••••···•••···••··••••••• •••●•••●••·············· ··· ·····•●•••••••••••●•••●••·•·•·•·•••·•••·•·•••·•·••●••••••··········••·•·•·•·••••••●••••••••·•·•···· ··•··•••••••••••●•●•●•●•●•●·•·•···········•·•·•·•·•······ · ··· ··· ··· ●•●•●••·•·•·•·•·· ··············· ••••••••●●●●●●●●●●●●●●●●●●●●●●●●●●●·•·••····•·•·•···············•·•·•·•·•·•·•·•·•·•·•·•·•·•·•···•···•·•·•·•·•●●•●●●•●●●•●●●·•·• ····•·•·•·•·•·•·•·················· •· ·····•·••●••••·················· ··•·•·•·•·••●●●●●●●●●●●●●●●●●●●●●••●•···········•·••··•·•·•·················•·•••·•·•·············••••••••••••••● · ·•· ·•••• ••···••••••·•·•·•·•·•·•·•·•·•·•···•······ •·•·•·••••••●•●•●···•·············•••••••••••••·•••·••••●●●●●●●●●●●●●●●·●•●•••••●••••••••••·•···•·•·•·•·•·•·•·•·•·•·•·•·••••●••••••·•·•·•·•·•·•·••········●•••·•••··•·•·········•·····•·•••••••••••••••• ••••••••·•·•·•·•·· ··········· · ●●●•●●●•●●●•●●●•●●●●●•●••••·•·•·•·•••••••••••••••·•·•·•·•·•·•·•••••••••••••••••••••••••·•·•···•·······•···•·•·•·• · · · ·••·• •·•·•·•·· ·•• ··•·••· ······•···•···•···• ••••••●•••●•●•●•••··· ······· ··●•●●●•●●●•●●●•●●●•●•●•●●●•●●●•●•●•●••·•···•·•·•···••••••••●••••••·•·•·•·•·•·•·•·•·•·•·•···•···•···•···•·•·•·●●●●●●●●●●●●●●●●●●●●•••••·•···•···•·•·•·•·•••••••••••·•·•·•· •••••••••••••••••• ··· ··· ··· ●•●•●•●•●•●•●•●•●•●●●●●●●●●●●●●●●●●●●●●••·•·•·•·•·•·•·•·•••·•••••••••••••••·•·•·•·•·•·•·•••••••••••·•••·•·• ··•·•·•·•·•·•·•·•·•·•·····•·•·••••●••••••••·•••·•••·•·•·•·•·• •·•·•·•·•···•···•·· ··· ··· ···•●●●•●●●•●●●•●●●•●●●●●●●●●●●●●●●●●●·•●••••••••••·•···•···•···•·•·•·•·•••·•••·•••••••·•·•·•···•···•·········· •·•·•·•·•·•·•·•·•·•·●•••••••●•●•●••••••••••••••••••·•••·•·•· ······················ · · · · · • · · · • · · ●•••●•●•●•●•●•●•●•••●•●•●•••●••••·•·•·•·•••••·•••·•·•·•·•·································•·······················•••••·•••••·•·•···· ··············•···• ······•••••••••••••·· ····· ·····•·············•●•●●●•●••·• ··•·······•···········•·•·•••••••••••·•·•·•·•·•·•·•·•·•·•·•••·•••·•••·•·········· ··· ··· · · ··· ··••••●•●•••●••·•••·•••··••·•·•·•········· ·•·•·•················ · · · · ● · · · · · · ●·•···•·•·····•·•·• • •···· ······•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•········ ··· ··· ··· ······· · · · · · · · · ··· · ··········•·•·•·•·•••·•·•········ · •••·•·•·•···•···•·•···• •·· ··· ••·············••·•·•·•·••··••·•••• •·• •·· • ··················•·•·•·•·•·•·•·•·•·•·•···························•···•···•···•···•·•·•·•·•·•·············•···•·•···•·•··· ···•·•·•·•·•·•·•···• · · ●•●•●•●•●•●•●•●•●•●•●•●•●•●•··· ··· ··· ··· ····· ··· · · · · · · · · · · · · · · · ······················· · · · · ··················· · · · · · · · · · · ······· ··· · · · · ··•···•·•·•·•·•••·•••····••••••••••••••••••••••••••••·•·•·•·•·•·•·•···•·······································•···•···•···•···•·······························•·· •···············•···•················· · · · ················•···•·•·•·•·•·•·•·•·•·•·•·•·• · · · · · · · ····•·•·•·•···· · · · · · · · · · · · · · · · · · · ··············· ······· · · · · · · · ······· · · · · · · · · · ··· ··· ··· · · · ············•·•·•···•·•···· •·•·•·•·•·•·•·•·•·•·•·•·•••·•······ ······•·•·•·•·•···· ··· ··· · · ··· ··· ··············· · · · · · · ··············· ··· ··················· · · · · ··················· · · ··· ············· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· ······· ··· · · ··· · · · · · · · · · · · · ······· ··· ··· · · · · · · · · ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
download
use it
[docs][copy it in]html
<script type="module" src="https://ascii.rest/ascii.js"></script> <ascii-art piece="lake-pichola"></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 ascii.rest
import { Ascii } from "ascii.rest/react";
import { lakePichola } from "ascii.rest/pieces";
<Ascii piece={lakePichola} /> A client component, so it works in the Next.js app router as it is. Pass the name instead, piece="lake-pichola", to fetch the piece only when it mounts.
astro
--- // npm install ascii.rest import Ascii from "ascii.rest/astro"; --- <Ascii piece="lake-pichola" />
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 ascii.rest
import { mount } from "ascii.rest";
import { lakePichola } from "ascii.rest/pieces";
const el = document.querySelector<HTMLCanvasElement>("canvas")!;
const stop = mount(el, lakePichola); 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.
terminal
npx ascii.rest lake-pichola
Plays it in your terminal, in colour, until you press a key. Add --seconds 5 to stop it on its own; npx ascii.rest list shows every piece. In a CLI of your own, play("lake-pichola", { seconds: 2 }) from ascii.rest/terminal shows it as a splash screen.
/*
* lake pichola: sunset over Udaipur's lake. The long white City Palace glows
* on the right shore in the last light, the Lake Palace floats mid-water, and
* the Aravalli hills stand purple behind with the Monsoon Palace on its peak.
* Clouds drift, boats cross trailing wakes, birds pass, and one by one the
* palace lamps flicker on.
*
* Each frame is shaded in colour cell by cell on a square grid, then drawn as
* a halftone: every cell is a dot whose size is its brightness, ordered-
* dithered so gradients read as texture, in the palette colour nearest its hue.
* The lake is shaded last, from the rows above it, mirrored and rippled.
*/
import type { Frame, Meta } from "../types.ts";
export const meta = {
name: "lake pichola",
category: "scenes",
note: "sunset on lake pichola, udaipur's palaces glowing over the water",
cols: 200,
rows: 100,
cell: 1,
fps: 15,
ground: "#120a1a",
palette: [
"#1c1028", "#2a1840", "#3d2058", "#55286a", "#6e3178", "#8a3c7c", "#a8477a", "#c85a6e",
"#e0704e", "#f08a40", "#f8a840", "#ffc65a", "#ffe08a", "#fff2c8", "#fffaf0",
"#2b1c40", "#3c2852", "#4f3666", "#6a4a7e", "#9a7aa0",
"#f6e6d0", "#e8cdb0", "#d4a888", "#b88a78", "#8e6a6a", "#6a4a58", "#c88a9a",
"#ffd070", "#ff9a3c", "#b8323a", "#140c1c",
],
} satisfies Meta;
const W = 200, H = 100;
const HORIZON = 62; // the far shore: the lake begins on this row
const SUN = [58, 48];
const LP_Y = 72; // the Lake Palace's waterline
const PLINTH = 54; // where the City Palace stands on its terrace
const DOTS = " ·•●";
const COVER = [0, 0.3, 0.6, 1]; // how much each dot fills, against the largest
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 AIR = 0, FAR = 1, NEAR = 2, BUILT = 3, LAMP = 4;
// The City Palace, left to right: [x0, x1, roof row, tower with a dome].
const BLOCKS: [number, number, number, boolean][] = [
[114, 125, 49, false],
[125, 138, 41, false],
[138, 144, 33, true],
[144, 158, 38, false],
[158, 165, 28, true],
[165, 178, 36, false],
[178, 184, 31, true],
[184, 200, 40, false],
];
// Boats, bottom row on the waterline: c canopy, p post, s shade under the
// canopy, r boatman, o lantern, g gilded rail, h hull.
const SMALL = [
"...cccccc...",
"..cccccccc..",
"r..pssosp...",
"r..pssssp...",
"gggggggggggg",
"hhhhhhhhhhhh",
".hhhhhhhhhh.",
];
const MEDIUM = [
".....cccccccccc.....",
"....cccccccccccc....",
"...cccccccccccccc...",
".r...psssossssp.....",
".r...pssssssssp.....",
".r...pssssssssp.....",
"gggggggggggggggggggg",
"hhhhhhhhhhhhhhhhhhhh",
".hhhhhhhhhhhhhhhhhh.",
"...hhhhhhhhhhhhhh...",
];
const LARGE = [
"........cccccccccccccc......",
".......cccccccccccccccc.....",
"......cccccccccccccccccc....",
"......cccccccccccccccccc....",
"..r.....psssssssosssssp.....",
"..r.....psssssssssssssp.....",
".rr.....psssssssssssssp.....",
"..r.....psssssssssssssp.....",
"gggggggggggggggggggggggggggg",
"hhhhhhhhhhhhhhhhhhhhhhhhhhhh",
".hhhhhhhhhhhhhhhhhhhhhhhhhh.",
"...hhhhhhhhhhhhhhhhhhhhhh...",
];
const BOATS: { art: string[]; y: number; v: number; x0: number; h: number }[] = [
{ art: SMALL, y: 79, v: 1.8, x0: 120, h: 0.31 },
{ art: MEDIUM, y: 88, v: -2.6, x0: 175, h: 0.62 },
{ art: LARGE, y: 95, v: 3.2, x0: 60, h: 0.87 },
];
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;
}
// Value noise, wrapping every `period` lattice cells in x when period > 0.
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 sky from zenith to horizon: violet, magenta, rose, orange, gold.
const STOPS: number[][] = [
[0, 0.05, 0.025, 0.12],
[0.25, 0.18, 0.07, 0.27],
[0.5, 0.7, 0.2, 0.42],
[0.7, 1.0, 0.4, 0.3],
[0.85, 1.0, 0.58, 0.3],
[1.0, 1.0, 0.72, 0.4],
];
const ramp = (v: number, i: number) => {
for (let s = 1; s < STOPS.length; s++) {
if (v <= STOPS[s][0]) {
const a = STOPS[s - 1], b = STOPS[s];
return mix(a[i], b[i], (v - a[0]) / (b[0] - a[0]));
}
}
return STOPS[STOPS.length - 1][i];
};
// A lamp's glow at t: each switches on with a stutter once a cycle, at its own
// moment, then burns with a slow flame flicker.
const lampGlow = (h: number, t: number) => {
const c = (((t / 36 + h * 7.3) % 1) + 1) % 1;
let on = smooth(0, 0.035, c);
if (c < 0.06 && Math.sin(t * 31 + h * 90) < 0) on *= 0.3;
return on * (0.86 + 0.14 * Math.sin(t * (3 + h * 5) + h * 60));
};
export default function lakePichola(): Frame {
const P = meta.palette.map(hex);
const N = W * H;
const out: string[] = new Array(N);
// Nearest palette colour, cached on a 32-step cube.
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 < P.length; 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 sky's base, built once -----------------------------------------
const skyR = new Float32Array(W * HORIZON), skyG = new Float32Array(W * HORIZON), skyB = new Float32Array(W * HORIZON);
for (let r = 0; r < HORIZON; r++) {
for (let x = 0; x < W; x++) {
const k = r * W + x;
const y = r + 0.5, v = y / HORIZON;
const away = Math.abs(x + 0.5 - SUN[0]) / 200; // cooler away from the sun
const veil = 0.93 + 0.14 * fbm(x * 0.04, y * 0.1, 3, 0);
let cr = (ramp(v, 1) - 0.2 * away * v) * veil;
let cg = (ramp(v, 2) - 0.08 * away * v) * veil;
let cb = (ramp(v, 3) + 0.06 * away * v) * veil;
const dx = x + 0.5 - SUN[0], dy = y - SUN[1];
const dm = Math.sqrt(dx * dx + dy * dy);
const g = Math.exp(-dm / 8) * 0.6 + Math.exp(-dm / 26) * 0.35 + Math.exp(-dm / 70) * 0.18;
cr += g, cg += g * 0.75, cb += g * 0.4;
const disk = smooth(6.2, 5.2, dm);
cr = mix(cr, 1.0, disk), cg = mix(cg, 0.95, disk), cb = mix(cb, 0.8, disk);
(skyR[k] = cr), (skyG[k] = cg), (skyB[k] = cb);
}
}
// --- hills and palaces, built once --------------------------------------
const mat = new Uint8Array(N);
const SR = new Float32Array(N), SG = new Float32Array(N), SB = new Float32Array(N);
const phase = new Float32Array(N); // each lamp's moment in the cycle
const lake = new Uint8Array(N); // the Lake Palace's own cells
const put = (x: number, y: number, cr: number, cg: number, cb: number, m = BUILT) => {
if (x < 0 || x >= W || y < 0 || y >= H) return;
const k = y * W + x;
(mat[k] = m), (SR[k] = cr), (SG[k] = cg), (SB[k] = cb);
};
const lampAt = (x: number, y: number, h: number, cr: number, cg: number, cb: number) => {
put(x, y, cr, cg, cb, LAMP);
if (x >= 0 && x < W && y >= 0 && y < H) phase[y * W + x] = h;
};
// The Aravallis in three layers: a long pale range far off that the sun
// sinks into, a darker one with the Monsoon Palace's peak, a low shore.
const back = (x: number) =>
HORIZON - (6 + 9 * Math.exp(-(((x - 150) / 40) ** 2)) + 5 * Math.exp(-(((x - 52) / 18) ** 2)) + 3 * Math.exp(-(((x - 108) / 12) ** 2))) - 3 * fbm(x * 0.05, 1.7, 3, 0);
const far = (x: number) =>
HORIZON - (3 + 17 * Math.exp(-(((x - 26) / 20) ** 2)) + 6 * Math.exp(-(((x - 26) / 7) ** 2)) + 7 * Math.exp(-(((x - 6) / 10) ** 2)) + 4 * Math.exp(-(((x - 54) / 11) ** 2))) - 2 * fbm(x * 0.06, 5.3, 3, 0);
const near = (x: number) => HORIZON - (1.5 + 5 * Math.exp(-(((x - 8) / 22) ** 2)) + 1.5 * Math.exp(-(((x - 60) / 14) ** 2))) - 2.2 * fbm(x * 0.25, 4.1, 2, 0);
for (let r = 0; r < HORIZON; r++) {
for (let x = 0; x < W; x++) {
const y = r + 0.5, k = r * W + x;
const fr = far(x + 0.5), br = back(x + 0.5);
const sunward = Math.exp(-Math.abs(x - SUN[0]) / 45);
if (y >= near(x + 0.5)) {
const s = 0.75 + 0.5 * fbm(x * 0.3, y * 0.3, 2, 0);
put(x, r, 0.1 * s, 0.05 * s, 0.13 * s, NEAR);
} else if (y >= fr) {
// the nearer range: deep purple, its ridge rimmed where the sun is behind it
const dd = y - fr;
const tex = 0.85 + 0.3 * fbm(x * 0.15, y * 0.25, 3, 0);
const rim = Math.exp(-dd / 0.9) * 0.3 * (0.3 + sunward);
put(x, r,
mix(skyR[k], 0.15, 0.86) * tex * (1 - 0.3 * smooth(0, 14, dd)) + rim,
mix(skyG[k], 0.07, 0.86) * tex * (1 - 0.3 * smooth(0, 14, dd)) + rim * 0.55,
mix(skyB[k], 0.21, 0.86) * tex * (1 - 0.3 * smooth(0, 14, dd)) + rim * 0.3, FAR);
} else if (y >= br) {
// the far range: the sky's own colour sunk into hazy mauve
const dd = y - br;
const tex = 0.9 + 0.2 * fbm(x * 0.1, y * 0.2, 3, 0);
const rim = Math.exp(-dd / 1.2) * 0.4 * sunward;
put(x, r,
mix(skyR[k], 0.44, 0.55) * tex + rim,
mix(skyG[k], 0.24, 0.55) * tex + rim * 0.65,
mix(skyB[k], 0.42, 0.55) * tex + rim * 0.35, FAR);
}
}
}
// The Monsoon Palace on the highest peak: a dark crown with a few lit windows.
{
const M = 26; // its centre column
const base = Math.round(far(M + 0.5)) + 1;
const mc = [0.11, 0.05, 0.14];
for (let x = M - 8; x < M + 9; x++) for (let y = base - 1; y < far(x + 0.5) + 1; y++) put(x, y, mc[0], mc[1], mc[2], FAR);
for (let x = M - 6; x < M + 7; x++) for (let y = base - 5; y < base; y++) put(x, y, mc[0], mc[1], mc[2]);
for (let x = M - 2; x < M + 3; x++) for (let y = base - 9; y < base - 5; y++) put(x, y, mc[0], mc[1], mc[2]);
const dome = (cx: number, by: number, rx: number, ry: number) => {
for (let y = Math.floor(by - ry); y < by; y++)
for (let x = Math.floor(cx - rx); x <= cx + rx; x++)
if (((x + 0.5 - cx) / rx) ** 2 + ((by - y - 0.5) / ry) ** 2 < 1) put(x, y, mc[0], mc[1], mc[2]);
};
dome(M + 0.5, base - 9, 3, 3.4);
put(M, base - 13, mc[0], mc[1], mc[2]);
dome(M - 5, base - 5, 1.6, 2);
dome(M + 6, base - 5, 1.6, 2);
for (const x of [M - 4, M - 1, M + 2, M + 5]) lampAt(x, base - 3, hash(x, 7), mc[0], mc[1], mc[2]);
lampAt(M, base - 7, hash(M, 8), mc[0], mc[1], mc[2]);
}
// The City Palace, white stone gone gold: the sun still on its upper floors,
// the lower ones already in the hills' shadow.
const stone = (x: number, y: number, s: number) => {
const k = clamp(s);
return [mix(0.7, 1.0, k), mix(0.5, 0.84, k), mix(0.6, 0.6, k)] as const;
};
BLOCKS.forEach(([x0, x1, top, tower], bi) => {
const w = x1 - x0, cx = (x0 + x1) / 2;
const off = (w % 5) >> 1;
for (let y = top; y < PLINTH; y++) {
for (let x = x0; x < x1; x++) {
let s = smooth(56, 36, y) * (bi & 1 ? 0.92 : 1);
if (tower) s += x + 0.5 < cx ? 0.12 : -0.08;
const ry = y - top, fy = ry % 5;
const g = Math.floor((x - x0 - off) / 5), fx = x - x0 - off - g * 5;
const fits = x - x0 - off >= 0 && x0 + off + g * 5 + 5 <= x1;
const win = fits && ry > 0 && ((fy >= 3 && fx >= 1 && fx <= 3) || (fy === 2 && fx === 2));
if (fy === 0) s += 0.14; // the ledge of each floor's balconies
const [cr, cg, cb] = stone(x, y, s);
if (win) {
const h = hash(g * 31 + bi * 7, Math.floor(ry / 5) + 3);
if (h < 0.55) lampAt(x, y, hash(h * 1e4, 2), cr * 0.3, cg * 0.2, cb * 0.32);
else put(x, y, cr * 0.3, cg * 0.2, cb * 0.32);
} else put(x, y, cr, cg, cb);
}
}
if (tower) {
// an onion dome on a drum, a finial on top
const rx = w / 2 + 0.4, ry = rx * 1.35;
for (let y = Math.floor(top - ry); y < top; y++)
for (let x = x0 - 1; x <= x1; x++) {
const dx = (x + 0.5 - cx) / rx, dy = (top - y - 0.5) / ry;
if (dx * dx + dy * dy < 1) {
const [cr, cg, cb] = stone(x, y, 1.05 - 0.45 * (dx + 1) * 0.5 - 0.1 * (1 - dy));
put(x, y, cr, cg, cb);
}
}
const fx = Math.floor(cx);
put(fx, Math.floor(top - ry) - 1, 1.0, 0.8, 0.5);
put(fx, Math.floor(top - ry) - 2, 1.0, 0.8, 0.5);
} else {
// battlements, and a row of small domed pavilions (chhatris)
for (let x = x0; x < x1; x++) if (!(x & 1)) put(x, top - 1, ...stone(x, top, 0.9));
for (let c = x0 + 3.5; c + 2.5 < x1; c += 6) {
put(Math.floor(c - 1.5), top - 1, ...stone(c, top, 0.85));
put(Math.floor(c + 1.5), top - 1, ...stone(c, top, 0.6));
for (let y = top - 4; y < top - 1; y++)
for (let x = Math.floor(c - 3); x <= c + 3; x++) {
const dx = (x + 0.5 - c) / 2.4, dy = (top - 1.5 - y - 0.5) / 2.4;
if (dx * dx + dy * dy < 1) put(x, y, ...stone(x, y, 0.95 - 0.35 * (dx + 1) * 0.5));
}
}
}
});
// its terrace in shadow, an arcade along the water, the ghat's steps
for (let y = PLINTH; y < HORIZON; y++) {
for (let x = 110; x < W; x++) {
if (y < near(x + 0.5) - 0 && x < 114) continue;
const fx = (x - 110) % 6, ry = y - PLINTH;
let [cr, cg, cb] = stone(x, y, 0.2 + 0.1 * fbm(x * 0.4, y * 0.4, 2, 0));
if (y >= HORIZON - 2) (cr *= 1.2), (cg *= 1.15), (cb *= 1.1); // steps, worn pale
if (y === HORIZON - 2) (cr *= 0.8), (cg *= 0.8), (cb *= 0.8);
const arch = (ry >= 3 && ry <= 5 && fx >= 2 && fx <= 4) || (ry === 2 && fx === 3);
if (arch) {
const h = hash(Math.floor((x - 110) / 6), 11);
if (h < 0.4) lampAt(x, y, hash(x >> 2, 12), cr * 0.4, cg * 0.3, cb * 0.45);
else put(x, y, cr * 0.4, cg * 0.3, cb * 0.45);
} else put(x, y, cr, cg, cb);
}
}
// The Lake Palace, white marble floating on the water, lit from the west.
{
const marble = (x: number, s: number) => {
const k = clamp(s * (0.55 + 0.45 * smooth(122, 82, x)));
return [mix(0.68, 1.0, k), mix(0.48, 0.9, k), mix(0.6, 0.8, k)] as const;
};
const LX = -20; // drawn about x 102, set down left of there
const set = (x: number, y: number, c: readonly number[], m = BUILT) => {
put(x + LX, y, c[0], c[1], c[2], m);
lake[y * W + x + LX] = 1;
};
const storey = (x0: number, x1: number, top: number, bottom: number) => {
for (let y = top; y < bottom; y++)
for (let x = x0; x < x1; x++) {
const ry = y - top, fx = (x - x0) % 5;
let s = 0.95;
if (ry === 0) s = 1.1;
if (y >= LP_Y - 2) s = 0.7;
const c = marble(x, s);
const win = (ry === 2 && fx === 2) || (ry >= 3 && ry <= 4 && fx >= 1 && fx <= 3);
const gate = y >= LP_Y - 2 && fx === 2 && bottom === LP_Y;
if (win || gate) {
const dark = [c[0] * 0.42, c[1] * 0.3, c[2] * 0.42];
if (win && hash(Math.floor((x - x0) / 5), top) < 0.6) {
set(x, y, dark, LAMP);
phase[y * W + x + LX] = hash(Math.floor((x - x0) / 5) + 40, top);
} else set(x, y, dark);
} else set(x, y, c);
}
};
storey(84, 120, 64, LP_Y);
storey(89, 115, 59, 64);
const dome = (cx: number, by: number, rx: number, ry: number) => {
for (let y = Math.floor(by - ry); y < by; y++)
for (let x = Math.floor(cx - rx); x <= cx + rx; x++) {
const dx = (x + 0.5 - cx) / rx, dy = (by - y - 0.5) / ry;
if (dx * dx + dy * dy < 1) set(x, y, marble(x, 1.1 - 0.5 * (dx + 1) * 0.5 - 0.1 * (1 - dy)));
}
};
// the central dome on its drum, chhatris at the corners
for (let x = 98; x < 107; x++) set(x, 58, marble(x, 0.85));
dome(102.5, 58, 4.8, 5.4);
set(102, 52, marble(102, 1.1));
for (const [c, by] of [[86.5, 64], [117.5, 64], [91.5, 59], [112.5, 59]]) {
set(Math.floor(c - 1.5), by - 1, marble(c, 0.8));
set(Math.floor(c + 1.5), by - 1, marble(c, 0.8));
dome(c, by - 1, 2.4, 2.6);
}
}
// --- the clouds: thin bands lit from below, wrapping so they drift forever
const CW = 600;
const cover = new Float32Array(CW * HORIZON);
const lit = new Float32Array(CW * HORIZON);
const density = (x: number, y: number) =>
fbm(x * 0.01, y * 0.12, 4, CW * 0.01) - 0.12 * smooth(16, 6, y) - 0.12 * smooth(34, 44, y);
for (let r = 0; r < HORIZON; r++) {
for (let x = 0; x < CW; x++) {
const y = r + 0.5;
const d = density(x, y);
cover[r * CW + x] = smooth(0.54, 0.64, d);
lit[r * CW + x] = clamp(0.5 + (d - density(x, y + 1.5)) * 9);
}
}
const FR = new Float32Array(N), FG = new Float32Array(N), FB = new Float32Array(N);
const birds = new Uint8Array(N);
const marked: number[] = [];
const emit = (k: number, r: number, x: number, cr: number, cg: number, cb: number, floor: number, fade: number, color?: Uint8Array) => {
(FR[k] = cr), (FG[k] = cg), (FB[k] = cb);
// Dot size from brightness, dithered. Then the colour makes up what the
// dot size could not: a small dot is drawn brighter and a large one
// dimmer, so a gradient stays smooth across the dither's steps.
const peak = Math.max(cr, cg, cb, 1e-4);
const level = clamp(floor + (1 - floor) * Math.pow(peak, 0.85) * 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) {
const want = step ? Math.min(1, (level + 0.06) / COVER[step]) : 0;
const s = (0.3 + 0.7 * want) / peak;
color[k] = nearest(clamp(cr * s), clamp(cg * s), clamp(cb * s));
}
};
return (t, { color } = {}) => {
const drift = t * 0.6;
// the birds: a loose flock crossing the afterglow, wings beating
for (const k of marked) birds[k] = 0;
marked.length = 0;
const mark = (x: number, y: number) => {
x = Math.round(x), y = Math.round(y);
if (x < 0 || x >= W || y < 0 || y >= HORIZON) return;
birds[y * W + x] = 1;
marked.push(y * W + x);
};
const flock = ((t * 2.6 + 130) % 300) - 50;
for (let i = 0; i < 8; i++) {
const bx = flock - [0, 5, 9, 4, 12, 16, 8, 21][i];
const by = 30 + [0, 2, 4, -3, 5, 7, -5, 3][i] + 1.2 * Math.sin(t * 0.7 + i);
const f = Math.sin(t * 6.5 + i * 1.9);
const lift = f > 0.35 ? -1 : f < -0.35 ? 1 : 0;
mark(bx, by);
mark(bx - 1, by - 1 + (lift > 0 ? 1 : 0)), mark(bx + 1, by - 1 + (lift > 0 ? 1 : 0));
mark(bx - 2, by - 1 + lift), mark(bx + 2, by - 1 + lift);
}
const pair = 230 - ((t * 1.8) % 300);
for (let i = 0; i < 2; i++) {
const bx = pair + i * 6, by = 18 + i * 2 + Math.sin(t * 0.5 + i);
const lift = Math.sin(t * 5 + i * 2) > 0 ? -1 : 0;
mark(bx, by), mark(bx - 1, by - 1), mark(bx + 1, by - 1), mark(bx - 2, by - 1 + lift), mark(bx + 2, by - 1 + lift);
}
// where the boats are now
const span = W + 70;
const boats = BOATS.map((b) => {
const w = b.art[0].length, h = b.art.length;
const x = ((((b.x0 + b.v * t) % span) + span) % span) - 35;
return { ...b, w, x: Math.round(x), top: b.y - h + 1, hull: b.art.findIndex((l) => l.includes("h")) };
});
for (let r = 0; r < H; r++) {
for (let x = 0; x < W; x++) {
const k = r * W + x;
const y = r + 0.5;
const m = mat[k];
let cr = 0, cg = 0, cb = 0, floor = 0.12, fade = 1;
if (m === LAMP) {
const on = lampGlow(phase[k], t);
cr = mix(SR[k], 1.0, on), cg = mix(SG[k], 0.8, on), cb = mix(SB[k], 0.4, on);
} else if (m !== AIR) {
(cr = SR[k]), (cg = SG[k]), (cb = SB[k]);
if (m === NEAR) floor = 0.02;
if (m === FAR) floor = 0.05;
if (m === BUILT) floor = 0.04;
} else if (r < HORIZON) {
// sky: the gradient, the sun, a few early stars, the drifting cloud
(cr = skyR[k]), (cg = skyG[k]), (cb = skyB[k]);
floor = 0.04 + 0.08 * smooth(0, 30, y);
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.05 && y < 16 && hash(x, r * 3 + 5) > 0.992) {
const s = (0.55 + 0.45 * Math.sin(t * (1.3 + hash(x, r) * 2) + hash(r, x) * 6.28)) * smooth(16, 4, y);
cr = Math.max(cr, s * 0.95), cg = Math.max(cg, s * 0.9), cb = Math.max(cb, s);
}
if (c > 0.01) {
const l = lit[i0] + (lit[i1] - lit[i0]) * fx;
const dx = x + 0.5 - SUN[0], dy = y - SUN[1];
const nearSun = Math.exp(-Math.sqrt(dx * dx + dy * dy) / 45);
const low = smooth(6, 42, y);
const warm = clamp(0.25 + 0.5 * low + 0.8 * nearSun);
const lr = mix(0.95, 1.0, warm), lg = mix(0.34, 0.78, warm), lb = mix(0.55, 0.42, warm);
const dr = mix(0.24, 0.5, low), dg = mix(0.11, 0.22, low), db = mix(0.32, 0.38, low);
const a = Math.min(1, c * 0.95);
cr = mix(cr, mix(dr, lr, l), a);
cg = mix(cg, mix(dg, lg, l), a);
cb = mix(cb, mix(db, lb, l), a);
}
if (birds[k]) (cr = 0.1), (cg = 0.04), (cb = 0.1);
} else {
// the lake: everything above it, mirrored and broken by ripples
const depth = (y - HORIZON) / (H - HORIZON);
const w1 = noise(x * 0.03 + t * 0.03, y * 0.5 - t * 0.25, 0);
const w2 = noise(x * 0.08 - t * 0.05, y * 1.3 - t * 0.5, 0);
const sx = Math.max(0, Math.min(W - 1, Math.round(x + (w1 - 0.5) * (1.5 + 5 * depth))));
const oy = (w2 - 0.5) * (1 + 3 * depth);
let src = -1;
if (r >= LP_Y) {
const ry = Math.round(2 * LP_Y - 1 - r + oy);
if (ry >= 48 && ry < LP_Y && lake[ry * W + sx]) src = ry * W + sx;
}
if (src < 0) src = Math.max(0, Math.min(HORIZON - 1, Math.round(2 * HORIZON - 1 - r + oy))) * W + sx;
const band = 0.4 + 0.6 * smooth(0.32, 0.68, w2);
const dim = (0.8 - 0.2 * depth) * (1 - 0.22 * smooth(110, 200, x));
cr = FR[src] * band * dim + 0.03;
cg = FG[src] * band * dim * 0.96 + 0.02;
cb = FB[src] * band * dim * 1.05 + 0.06;
// the sun's road, broken into glints
const road = Math.exp(-(((x + 0.5 - SUN[0]) / (2.5 + depth * 16)) ** 2));
const glint = smooth(0.6, 0.85, w2) * road;
cr += 0.8 * glint, cg += 0.6 * glint, cb += 0.3 * glint;
// a soft haze along the far shore
const haze = Math.exp(-(y - HORIZON) / 2) * 0.12;
cr += haze, cg += haze * 0.6, cb += haze * 0.5;
floor = 0.1;
fade = smooth(H + 8, H - 16, y);
for (const b of boats) {
// the wake: two arms spreading behind, and churned water close astern
const a = b.v > 0 ? b.x - x : x - (b.x + b.w);
if (a > -1 && a < 70) {
const s = b.w / 22;
const dy = Math.abs(y - b.y - 0.2);
const arm = Math.exp(-(((dy - (a + 1) * 0.09 * s - 0.4) / (0.7 + 0.02 * a)) ** 2)) * Math.exp(-a / (30 * s));
const churn = Math.exp(-((dy / (0.8 * s + 0.4)) ** 2)) * Math.exp(-a / (12 * s));
const lap = 0.5 + 0.5 * smooth(0.3, 0.7, noise(x * 0.6 + b.v * t * 0.6, y * 1.7, 0));
const wk = Math.min(1, arm * 1.3 + churn * 1.1) * lap;
cr = mix(cr, 1.0, wk * 0.8), cg = mix(cg, 0.86, wk * 0.8), cb = mix(cb, 0.66, wk * 0.8);
}
// the boat's dark reflection
if (r > b.y && r <= b.y + 3 && x >= b.x + 1 && x < b.x + b.w - 1) {
const q = 0.35 + 0.15 * (r - b.y);
(cr *= q), (cg *= q), (cb *= q);
}
}
}
// the boats themselves, in front of everything on the water
if (r >= HORIZON) {
for (const b of boats) {
if (r < b.top || r > b.y || x < b.x || x >= b.x + b.w) continue;
const col = b.v > 0 ? x - b.x : b.w - 1 - (x - b.x);
const ch = b.art[r - b.top][col];
if (ch === ".") continue;
const row = r - b.top;
if (ch === "h") {
// wood catching the sunset, darker toward the water
const s = 1 - 0.2 * (row - b.hull);
(cr = 0.55 * s), (cg = 0.26 * s), (cb = 0.16 * s), (floor = 0.04);
} else if (ch === "g") (cr = 0.98), (cg = 0.7), (cb = 0.34);
else if (ch === "p") (cr = 0.8), (cg = 0.55), (cb = 0.32);
else if (ch === "s") (cr = 0.2), (cg = 0.08), (cb = 0.12), (floor = 0.02);
else if (ch === "r") (cr = 0.1), (cg = 0.04), (cb = 0.08), (floor = 0);
else if (ch === "c") {
// the canopy: a pale top, red cloth hanging below it
if (row === 0) (cr = 1.0), (cg = 0.88), (cb = 0.72);
else (cr = 0.88), (cg = 0.22), (cb = 0.24);
} else if (ch === "o") {
const on = 0.85 + 0.15 * Math.sin(t * 7 + b.h * 40);
(cr = on), (cg = 0.8 * on), (cb = 0.42 * on);
}
fade = 1;
}
}
emit(k, r, x, cr, cg, cb, floor, fade, color);
}
}
const lines: string[] = [];
for (let r = 0; r < H; r++) lines.push(out.slice(r * W, (r + 1) * W).join(""));
return lines.join("\n");
};
}