aurora fjord
[github]aurora curtains rippling over a still fjord, a cabin lit on the shore
scenes 200×100 15 fps 43 colours, on a canvas 22.6 kB
· · · · · · ······•·•·· ···••·•·•·····•········ ········•······················ · · · · · · · · · · · · · · · · · · · · ● · · · · · · · · · · · · · · · • · · · · · · · ··· · · · · · · · · · · · · · · · ··· ··········•·•·•••·····••·••·•···•···•···•·······•······························ ··· ··· ··· ······· ······· ··· ··· ··············································· ······· ··· ··· ··· ··· ··· ·· · · · ··· · ······••••·····••·•••·····•·················•············ ··········· · · · · ··· ··· ··· · · · · · · · · · · · · · · ··· ··· ··· ··· · ····· ··· ··· ······· · · · · · ··· · · · · · · · · ··· ············•·•·●•●·····••··●·•···•·•·•·•·•·······•·•••·•·•·•·•·························································································•·········································· · · · · ··· ····•·••●••·····•··•··•···•···•···•·········•·········· ··· ··········· · · · · · · · · · · · · ··· · · · · · · ··· ··· · · · · ··· ··· ··· ··········· ··· ··· ··· · · · · · · · · · · · · · ···•···········•••●●●••··•·••·●·•···•••·•·•·••······•···•···•···•···············•······ ················•···································•·······•······································ ··· ······ · · · ········•·•·••●•●·····●•·••·•···•••·•···•·······•·••··•···•·················· · · · ··· ··· ··· · · ····· · ··· ··········· ······· ······················•············ ··· ··· · · · · · ··· · · ················••••●●●●•···•●●·●••·•·•·•••·•·•••·•·•·•·•·•·•·•···•·········•·•·•·•·······················●·····················•·············•·······•·•···•·•·•·•·····•······························· · · · · ··· ······••●●●·····••··●·•···•••·•·•·•·······•··••·······• ··············· · · · · · · ··· ··· · ····· · · ··· ··········· ··· ······•·······•···············•········ ··· ··· · · · · · · · · · ········•·····•·••●•●●•·•·••●·•●•••·•·•••·•·••●·•·•·•·•·••··•···•···•···•···•·•·················································•···········•·······•·•·•···•···•·····•·•·•··························· · · · ······· ··· ··•●•••·•·•●•·●·•···•••·•••·•••·······•·•·•·····•·········•·····•·· · · ··· ··········· ······· ··· ························•·······•·····•·•·········•················ ··· ··· · · · ······················••●••·•·●••●●••···••●·•••·●·•·•·•·•••••·•·•·•·•·•·•···•·•·•···•·······································•···•·•·······•·•·•·•·····•·•···•·•·•·•·•·•·•••·•·······•··················· · · ·•· · · · · • · · ··•·•·•●●·●●•···•·●••·•••••·•···•·•·●···•···•···········•···• · · ··· ··· ··· ··· · · ··· · · ··························•·······•·•·····•···•·····•·············· ····· · · · · · · ··· ··· ··· ··· ········••••●●••●••·•·•●●•••●·●•••··•·•••••·•·•·•·•·····•···•••·•·············································•·•···•···•···•·•·····•·•••·•·•••·•••·•·•••·•··························· · · · · · · · · · · · · ··•••●●·•●•••·••●•••●•••●·•·•··••·●••·····•·······•···•·•···· ··········· ······· ······· ··············•·············•·•······••···•·•·•·•·····•·•·•················ ··· · · · ····························••●●••●•●••·●●●●●●●•●●•·••••••••●·•·•·•••···•·•·•·•·•·•·•·······································•···•·•·····•·•·····•···•·•·•••·•·•·•·•••·•·•••·••··•···•·······•··········· · · · · · · · · · · · · · ··••●••●●••···•●●•●•●•●••·•·•·•••●··•···•···········•·•······ ··· ··· ··· ······· ····· · ··· ··················· ··•·•·····•·•···•·•••·•·····•·•············ ······· ··· ··· · ··· ··· ··· ··· ············•●●•●●●••·••●●●•●●•●●•●•••••●•●·•••·•••···•·•·•·•·•·•·•·························•···················•·····•·······•·····•···•·•···•·•·•·•·•·•·•·•···•····················· · · · · · · · · · · · · · · ··●●•●●•●•••●●●●●●●•●●••••••●••●•·•·•·•·•·······•·•••········ ······· ··· ··· ······· ··········· ··············· ··················•·······•·•·•············ ······· · · · ·······························•●•●●●●●••●●●●●●●●•●•●•●••●●•●●•••••·•••·•·•·•·•·●••·•···············•···•·····•·············•···•·•·····•···•···•·········•·•···••··•···•·•·•·•·····••··•··············· · · · · · · · · · · · · · · · ·•••●●●••·●●●●••●••●●·••••●●•●●·•·•·•·•·····•·•·•·•·•·•·· ··· ········· ····· ··· · · ··· ··································•·····•·········· ··· ··· ··· · · · • · · · · · ●·· ····························•●●●●•••●●●••···•··•●•●•●•●●•••••·•••·•·•·•·••••••••··················•·························•·········•·····•···•···•·•·•··••·····•·•···•························· · · · · · · · · · · · · · · · ····●●●•••●•●·· ··· ····••●●●●●••••·••••··•·•·•·•·•·•·•···· ··· ······· ······· ······· ····································•·•···•···•················ ··· ··· · · · · · ························••··········•·•••···········•···••●●●●●•●••·••●·•••·••••••••••······•···•···•···•·······•···········•·•·•·•·•···•···•···•·•···•·•·•••·•·•••·•••·•·•···•························· · · · · · · · · · · · ··• · · · · · ··· · · · · · · · · ·●●•●●•••••••••·•·•·•·•·●·•·•·· ··························· ··············•·················•·····•·•·•··••·•···•·····• ··· · · · · · · · · · · ······················●•••●·······························•●●●●•●•●•••●•·••••••·●••••·•·············•···•·•·····•·•···········•···•·•·•···•·•·····•···•·•··•••••··●•··•···••······•·····•··············· · · · · · · · · · · ·•••••• · ··· ··· ··· ··· ··· ··· ··· ·•●●•●••••●••·••••••••••••••··················•···· ······· ······•·····•·•·······•·········•·•·•••·•··••·•••·•·•·· •······ ··· ··· · · · · · ············•·········●•●•••····●···························•●●•●●●••●●●••●•••●•●•●•●•●·•···•···•···•·•·•••·····•·•·····•···•·•·•·•·•·•·•·•·••····•·•·•·•••·●••••·●●•·●••••••···•······················· · · · · · · · · · · ●•●••·••· · · ··· · · · · · · · · · · · ·●●•●•●•●•●·•••••●•••●••••··················•·········· ··········•···•·•·····•·•·· ··•···•·•··•●•••·•●···•···•···•···· ··· ··· · · · · · · ·····················●●●●·••●··································•●•●●•●●●•·●•●•●•••●•●••·•·········•···•···•·····•·•·······•·•·•••·•·•·•·•·•···•···•·•·•••••·●●●•●·•••·•••·•••···•······················· · · · · · · · · · ·●●•●●··••● ··· ··· ··· ··· ··· ··· ··· ··· ··●•••●●●•••●•●•●•●●●●•·•·········•·······•·•·· ··•·•·····•···•·•·•·•••·····•·•·····•·•·•••··•●•●••·•·· ····•····•····· ··· ··· ··· · · · ···················•●•●●●•••●●····································••●•••●•●•●•●●●●●●●●•●•·······•·•·•·•···•·•···•••·•···•·•·•••••·•·•••·•·•••·•·•·•·•·••●•●·•●●●••··········•·•·•······················· · · · · · · · · ··•·••●•••••●●· · · · · · · · · · · · · · · · • ······••••●•••●•●●●●●•●···············•··••·····•·•·····•·····•·•·•·•••·•·•··••···•·•·•••••·●●•···· · · · ·●··········· ··· · · · · · · ·····●●···········•·•·••●•●•●●●·············································••●●•●●●●●●●•·•···•·•·•···••··•••·•··••·•·····•·•·•••••·••●••·•••·●•··•••·••●•●••●●•···········●●•··•···•··················· · ·•●•• · · · ··●••·•·••••●●●•●●· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ····••●•●●●•●·•·········•·•·•··••·•···•·······•·•·•·•••·••●••·•·•••••···•••·•●●●●•••··· ··· ···•••••··•········ ··· ··· ··· · ····••●•●·······●•●••••·••●•●●●●●•················································●•●●●•●••·•·•·•·•·•·•••·•••·•·•••·•···•·••••••●•••●●●•••••●·•••·••●•••●●●●●············●●•●•••···············•········ ··•·••●•● · · •·•••••·•·••●•●●●•• · · · · · · · · · ··· ··· ··· ··· · · · ····· ··•●●●•●•·········•·•·•···•·······•······••·•·••●•••●●●•••••••●···••••••●•●···· ··· ···•●•••••●•··· · · · · · · · · · · ·••••·●●●•·····•••●•●•••••●•●•●•••●··············•●·································•●●•●·•·•·•···•••·•••·•••·•···•••·•···••••••●●●••●●●••●•●••●•·••●●●•●●●•···········•●•●•••●•●······················· ••••·••●•●••···•·••••●•••••••●•••●●●·· ··· ··· ··••●●· ··· ··· ··· ··· ··· ··· •·· ···•●●•·•···•·•·•••·•••·●••·•··••·•···•·••••●●●●••●●•••·••●·●••·••●•••●···· ··· ···•••••••●•••• ··· ··· ··· ··· ··· · •••••·●•●•●•●·•·••••●•●•●•••••••●●●●············•·●●●●●································•●••·•·•••·••●·••●••●●••••·●•••··•·••●•●•●●●•●•●●•·•·•●••●••·●●●••············•••●•••●•●••••·············●●●•···· ·•••·••••••●•··•·•·•·•••••·••••••●•●●··· ··· ·••··●●•●●● ··· ··· ··· ··· ··· ··· ··· ····•••·•·•···•••••••·●••·•··••·•·•···●•••●●●●●••·········••••••●••···· ··· ··· •·•·•·•••••·•·• ··· ··· ·•●•●••···· •·•••·●•••●•●·•·•·••••••●·••●•●●●•●●●•·······•●••·●●●●●•················•·················•••·•••·••●•●•●•••●••••·•••••·•·••●•●●●●●●•·············•·•·•·············●••••••·●••••·•·•·········●•●••••··· ·•·••••••●•●••···•·•·•·•••·•●●•●•●•●•••··· ·•••••••●•●•••········· ··· ··· ··· ··· ··· ······•·•••·•••·••●·•●●••·•·●••···•·●●●•●●●●·······························●●••••·•·•••·•·•···· ··· ··●••••·•·•·· •·••●•••●•●•●·•·•·•·••••••●●●•••●●●•●•●····•••••●•●●●•●•●•······································•·••●●••●•••●●●••·•●●••·••••●●●●●•································●●●●●••••·•••••·•·••······●●●••••••·•· ···•·•·••••●•······•···•·••••••●•••••••● ·••···•·••●•••••●·· ··· ··· ··· ··· ··· ··· ··· ··· ············••••●•••··●••••·•·●●●•●···················· ··· ······· ●•●•●••·•·•••·•···•·•·· ·•●•●••·•••···• •·••••••●•●●●·•·•·•·•·•·••••●●●●●•●•●•●●●●●••·•·••●•●•••●●●···············································•·•●●•●·•●●•●•••••●●●•······················●•●•··· ····●●●●●●•••·•••·•·•·•·••·•●●●●●●•·•···•· ·•·•••·••●•●••···•···•·•·••●●●•●•••●•●•●●●●●••···••●••·•●●●··················································•·•••·•●●••·••●•●···········•···········●•••●•····· ··••●•●••·•••·•·•·•·•·••●•●●●•●••······ •·•·••••●•●•●·•·•·•·•·•·••●•●•●•●•●•●●●●●●●●●••·••●••·•●●●●●················································•···••••●●●•••••●···•···········•······•●•●•●•●••·· · ··•●●●●•••●••·••••••••●•●•●●●●●·•····· ·•·•·•·•·••●•······•···•·●•••••••●•●•●●●•●●●••••·•••·•●●•●●●•··········••··· ······· ······························•●•••·•••······················•●•●•●••••·· · · •·●•●••••••·•·•·•·•·••●•●•●••·····• •·•••·••••●•●·•·•·•·•·•·••●•••●•●•●●●●●●●●●●●•●••·•·•●●●●●●●●●●·······••••········································•·•••••·•·····················●•●•●•●•●•●•••••· · · ••●●●•●••••·•••·••••●•●•●●●●····•• ·•·•·•·••••●••·•·•···•···••••●•••●•●●●•●●●·●●●•●••··•●●●●●•●•●●●·····•·••●●····································································●•●•●•●•••●•••••••· · ●·••●●●••••••·•·•·•·••••●•●●●···•·• •·••••••••●•●••·•·•·•·•·••••●•●•●●●●●●●●●●••●●●●●••·●●●●●●●●●●●●•···•••·●•●●•···············•···•···•···•···•···•···•••·•···•···•···•···••··•●●●●●●•●•●•●•●•●•••••• · •••●●●●•••••••••••••••●•●•●●•·•••• ···•·•·•·••●••••···•···•·••●•●•●•●•●•●●●•●·••●●●•●·●•●●●•●•●•●●●●·••·•·•·••●●●·····················•·············•·•·•·•·•················ · · · · · · · · · · · · · ●·••●••••·•·•·•·•••·••••●•●·•·••• •·•·••••••●●●·•••·•·•·•·••●●●•●●●●●●●●●●●•··•●●●●●•●●●●●●•●●●●●●●••••·•·••●●●●●●··················•·•·•···•···•·•·•••·•••·•···•···•···•·······•••••••·•·•·•·•·•···· ·●·●•·•●●•●•••••••••●•••••●•●●••••●· ·•···•·••●•●••·•••·•·•·•·●•●•●•●●●·●●●●●•●···●●●●●•●•●•●•●•●●●●●••·•·•···•••●●●●●··············•·•·•·•·•·······•·•·•·•·•·•·•·•·······•···· ···•••●•●•• ··•·••●•●·· · · ·••·••●·•••·••••••●••·••••●·•·●·· •·•·••••●•●●●·•·•••••••·•●·●●●●●●●·●●●●●●•··••●·●●●●●●●●●●●●●·●••••·•·•·••••●●●•●●··•·•·•···•·•·•·•·•·•·••··•••·•••·•••·····•••·•·•·•·•·•·····•••●●●●•··•·•·●●●●•·· ··· ●···●•·•••••••••••●•••••••··●•·· ······•••●•●•·····••••·· · ●·●•●•· ●•●•●••······•●•••●·●•●●●· ••······ •·••●•●•·•●●●···•···•·•·•·· · ··•·•·•·•·•·•·•·· · · · •·•·•·•···• · · ·•••●•●•• ··•·••●•●·· · · ··· •·· ··•••••••·•••·•·•·· ••··· •·• •·•·●•●•●·•·• •••••····●·●●●●··●●•●••••···· ●••••··●●·●●· ●••·●·•···••●●●••·●●●●●●•·•·•·•·•·•·······•·•·•·•·•·•···········•••·•·•···· ··· ••••●●●···•·•·●•●●······· · · •·· •••··•●••••••·•·• ·••··· ·•· ··•·•● ●•··• ··•·•·· · ●·●·●●· ●•·•• •·• · ·•●•••· ●··●●···•··••·• •••●●·••·●●•••●●●••·•·•···· ··· ··· ··· ··· ··· ··· ····•·•···· · · · ·•••••••• ··•·•·•···· · · · · ··· ···•· ••••• •·•···· •···· ··· ··· ●··••·•·· ··········· · ●··•· ●•·•··· · ••··•··●· ●●· •···•····•●·●●· · ·●· ●●••●••·•·············································· ··••••••••··•·•·•·•·•·• ··· · · ··· · • ·•·••··•· · •·· ···· · · · ··· · · · · · · ··· · ·· · · · · ··· • ·• ·· · · · · ·· · · ··• ····· · · · · · · · · · · · · · · · · ··· · · · · · ····•·•·•·•·•·•·•·•·•·•·• · · · · · · · · ··· · · · · · · · · · · · ··· ··· · · · · · · · · ··· · · · · · · · · ··· ··· ··· · · · · · · · · · · · · ······································· · · · •·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·· · ··· · · · ··· · · · · · ·· ··· ············•·•·············•·•·•·•·•·•·•···············•·• ··•·•·•·•·········•·•·•·•·•·•·•·•·•···········•·······•·•·•···········•·•••·•••●●••·•·•·••●●•·•·•·•·•·•·•·•···•········ ··· ··· ····· ··· ··· •·············· ········•·····•···· ··········•···•···············•·····•···•···•·············································· ······•·••●●•···•···••●········ ··· ··· ··· ············· ····· ··· · ··•······ · · ··· · · ····· •···• ··· · ········• ·•· ··· ··· ··•·••· · ··•···•·•········ · · · · · · ··· · · · · · · ······· · · · · ··· ··●·· · · ··· · · · · · · · · · ··· ··•······ ··· · · · ·········••·•·······•·•·· ·•··•••···•••••·•·······•••···•··•• ····•·····•·•••·•·•••·•••·•············ ··················· ········•······ · · ····●●•·· ····•●●·· · · · · · ··· ··•···•·•·•·•·•········· ···· · ··•·•··············•·••••··••••·•·•···· ·••·•···•••••···•···········•••·•·•••·•············ · · ··············· · · ··········· · · · ····••●·· ··· ····· · · · · · ··· · ······•·•············ · •···•·•·•••••···•·•·•·•·•·•••••••·••●••••···••·•●•••••••●••·•••·•···•···•·•••••••·•·········•···•·····•·•···•·•·•·•·•·······•·•·•···•·•···· ······•·· ······•••·· · ··· •···•·· ··•·•·•·•·•·•·•·•···•··· ·······•·•••···············••••••••·••••••·····•·•••••••••••••••···········•••·•···· ··· ··· ··············· ··········· ······· ······· · · ····••• · · · ··••· · · ··• ··•···················•········ ······•·•·•••·•···•···•···•••••••••••••••••···•••••••••••••••••••••·•·····•·•••••·····················•···········•···•·················· ··········· · · ····•·· · ····•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ···········•·•·············•·•·•·•·•••••••···•••••··••••••·•••••••·········•••·•·· ··· ··· ··· ··· ······· ··· ··············· ··· ··· ··· ··· · ··•·· · · ··•·· · · ····•·•••·•·•·······•···•·•·•·•···• ········•·•·•••·•···········•·•·•••••••••••·••••••··•••••••••••••···•···•·•••·•·········································•·················· ······•••·······•······ ····•••••·•·•·•·•·•·•·•·•••••···•••· ··········•·············•·•·•·•·•••·•••·•••·•·•···•••••·•·•·•·· · ······•·· · · · · · · · · · · · · · · · · · · · ····· · · · · · · · · · ······•···········•·· · ····•·•••·•·•···········•·•••·······• ······•·•·•···············•·•·•·•·•••••••••••••••·•·•·•••••••·•·· · ··•·•·· · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · •·•·•••·•···•·•···· · ··•·•·•••·•·•·•·•·•·•·•·•·•••·····•· ···········•·•·············•·•·•·•·•·•·•••·•••·•·······•••••••···· · · ····· · · · · · · · · · · · · · · · · · ··· ········· · · · · · · · · · ··············· ··· · · ··•·•·•·•·············•·•·•···· · •···•·•·•••••···········•••••••·•••••••••••••••·•···•···•••••································ · · · · · · · · · · · · · · · · · · · · · · · · · ········•·•·•······ ··•·•••·•·•·•···•·•·•·•·•••••••····· ·······•·•·············•·•·•·•·•·•·•·•·•·•·•·····•·····•·•·· · · · · · · · · · · · · · · · · · · · · · · · · ········•·•········ · · · · · · · · ········· · · ··•·•·•···············•·•·•·•·•···· · · ··•·•·•·•·•···········•·•·•••·•·•·•••·•••·•···•·•·•···••• ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ············•···•·•·····•·········· ······· ··· ········· · ··•·•••••···•·······•···•·•·•••·•········· ·········•·•·· ··········•·•·•·•·•·•·•···········•········ · · · · · · · · · · · · · · · · · · · · ··········•·····•·•·····•·•···· · · · · · · · · ··· · · · ··•·•·················· ··•·•······ ··· · ······•·•·•·•···········•·•·•·•·•·•·•·•·········•·•·•···•·· ················································•·•·•·····•·•·····•••·•···························· ····•••·•···•···············•·•·•······· ··············· ··· ··············•····· · ········•·•···· · · · · · · · · · · · · · · · · · ············•·· ······· ····•·•·•·· · · · · · · · · · · · · · · · ··•·•············ ··· · · ··········· ··•···•·•·•·•···············•·•·•·•·•···· ··•·•·•·•••·•·· ··· ··· ··· ··· ··· ··· ··· ············•···•···•·······•···········•·•·•······ ··· ··········· ··· ····•·•·•·······•······ ··· ····•·•······· ·········•···········•·······•·•·•·· · · · ········•••·· · · · · · · · · · · · · · · · ··· ··················· ······· ··········•···· · · · ········· · · · · · ················· · · · · ··•···· · · · •···•·•·•·•·········•·•·•·•·•·•·•••·•·· ··· ····•••·•·· ··· ··· ··· ··· ··· ··· ··· ······•·•·············•·•···········•···•·•·•···················•······ ··· ··· ····•···•·•·•······ ··· ····•······ ···········•···· ····················•·· · · · · ··•···· · · · · · · · · · · · · · · · · ··• · · ··· ··· ··· ··· · ····· · ········•········ ······· ········· · · · · · ······•······ · · · · · · ····· ······•·•·•···· ······•···•···•·•·•·•·•·· · · · · ····•·· ··· ··· ··· ··· ······· ····••··························•·············•·•···•·•·········•·····•···•···· ··· ··•·•·•·•·· ··· ··· · · · · · · · ·····•·· · ················•·•···· · · · · · · · · · · · · · · · · · · · · · · ······• · · · · ··· ··· ··· · · ··· · · ··························· ······•·· · · · · ········· · · · · · · · · · · · · · ····•·•·•·· ··· ··•·•···•···•••·•·· ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ········•·•······ ··· ··•·•·•·•·· ··· ··· ··· · · · · · · · · · ····· · · · ····· ······•···· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ······· · · · · · · · · · · · ··•······ · · ··········•·•···· · · · · · · · · · · · · · · · ··· · · ··· ········•·•···· ··········· ··············· ··· · · · · · · · · · · · · · · · · · · · · · · · · ··•···· ··· · · · · · · · · · · · · · · · · · · ············· · · · · · · · · · · · · · · · · · ··· ······•···· · · · · · · ··· ··· · · · · · · · · · · · · · · ··· · · · · · · · · ··· ··· · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · ············· · · · · · · · · · · · · · ····················•·•···· ··· ··· ··········· ··· ··· · · ··· ··········· ··················•···· · · · · ··· ··· ··· · · · · · · · · · · · · · ····· · · · · · · · · · · · ··· ····· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ····· ··· · · · · · · · · · · · · · · · · · · · · ········· ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · ····· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ······•·•·· ···••·•·•·····•········ ········•······················ · · · · · · · · · · · · · · · · · · · · ● · · · · · · · · · · · · · · · • · · · · · · · ··· · · · · · · · · · · · · · · · ··· ··········•·•·•••·····••·••·•···•···•···•·······•······························ ··· ··· ··· ······· ······· ··· ··· ··············································· ······· ··· ··· ··· ··· ··· ·· · · · ··· · ······••••·····••·•••·····•·················•············ ··········· · · · · ··· ··· ··· · · · · · · · · · · · · · · ··· ··· ··· ··· · ····· ··· ··· ······· · · · · · ··· · · · · · · · · ··· ············•·•·●•●·····••··●·•···•·•·•·•·•·······•·•••·•·•·•·•·························································································•·········································· · · · · ··· ····•·••●••·····•··•··•···•···•···•·········•·········· ··· ··········· · · · · · · · · · · · · ··· · · · · · · ··· ··· · · · · ··· ··· ··· ··········· ··· ··· ··· · · · · · · · · · · · · · ···•···········•••●●●••··•·••·●·•···•••·•·•·••······•···•···•···•···············•······ ················•···································•·······•······································ ··· ······ · · · ········•·•·••●•●·····●•·••·•···•••·•···•·······•·••··•···•·················· · · · ··· ··· ··· · · ····· · ··· ··········· ······· ······················•············ ··· ··· · · · · · ··· · · ················••••●●●●•···•●●·●••·•·•·•••·•·•••·•·•·•·•·•·•·•···•·········•·•·•·•·······················●·····················•·············•·······•·•···•·•·•·•·····•······························· · · · · ··· ······••●●●·····••··●·•···•••·•·•·•·······•··••·······• ··············· · · · · · · ··· ··· · ····· · · ··· ··········· ··· ······•·······•···············•········ ··· ··· · · · · · · · · · ········•·····•·••●•●●•·•·••●·•●•••·•·•••·•·••●·•·•·•·•·••··•···•···•···•···•·•·················································•···········•·······•·•·•···•···•·····•·•·•··························· · · · ······· ··· ··•●•••·•·•●•·●·•···•••·•••·•••·······•·•·•·····•·········•·····•·· · · ··· ··········· ······· ··· ························•·······•·····•·•·········•················ ··· ··· · · · ······················••●••·•·●••●●••···••●·•••·●·•·•·•·•••••·•·•·•·•·•·•···•·•·•···•·······································•···•·•·······•·•·•·•·····•·•···•·•·•·•·•·•·•••·•·······•··················· · · ·•· · · · · • · · ··•·•·•●●·●●•···•·●••·•••••·•···•·•·●···•···•···········•···• · · ··· ··· ··· ··· · · ··· · · ··························•·······•·•·····•···•·····•·············· ····· · · · · · · ··· ··· ··· ··· ········••••●●••●••·•·•●●•••●·●•••··•·•••••·•·•·•·•·····•···•••·•·············································•·•···•···•···•·•·····•·•••·•·•••·•••·•·•••·•··························· · · · · · · · · · · · · ··•••●●·•●•••·••●•••●•••●·•·•··••·●••·····•·······•···•·•···· ··········· ······· ······· ··············•·············•·•······••···•·•·•·•·····•·•·•················ ··· · · · ····························••●●••●•●••·●●●●●●●•●●•·••••••••●·•·•·•••···•·•·•·•·•·•·•·······································•···•·•·····•·•·····•···•·•·•••·•·•·•·•••·•·•••·••··•···•·······•··········· · · · · · · · · · · · · · ··••●••●●••···•●●•●•●•●••·•·•·•••●··•···•···········•·•······ ··· ··· ··· ······· ····· · ··· ··················· ··•·•·····•·•···•·•••·•·····•·•············ ······· ··· ··· · ··· ··· ··· ··· ············•●●•●●●••·••●●●•●●•●●•●•••••●•●·•••·•••···•·•·•·•·•·•·•·························•···················•·····•·······•·····•···•·•···•·•·•·•·•·•·•·•···•····················· · · · · · · · · · · · · · · ··●●•●●•●•••●●●●●●●•●●••••••●••●•·•·•·•·•·······•·•••········ ······· ··· ··· ······· ··········· ··············· ··················•·······•·•·•············ ······· · · · ·······························•●•●●●●●••●●●●●●●●•●•●•●••●●•●●•••••·•••·•·•·•·•·●••·•···············•···•·····•·············•···•·•·····•···•···•·········•·•···••··•···•·•·•·•·····••··•··············· · · · · · · · · · · · · · · · ·•••●●●••·●●●●••●••●●·••••●●•●●·•·•·•·•·····•·•·•·•·•·•·· ··· ········· ····· ··· · · ··· ··································•·····•·········· ··· ··· ··· · · · • · · · · · ●·· ····························•●●●●•••●●●••···•··•●•●•●•●●•••••·•••·•·•·•·••••••••··················•·························•·········•·····•···•···•·•·•··••·····•·•···•························· · · · · · · · · · · · · · · · ····●●●•••●•●·· ··· ····••●●●●●••••·••••··•·•·•·•·•·•·•···· ··· ······· ······· ······· ····································•·•···•···•················ ··· ··· · · · · · ························••··········•·•••···········•···••●●●●●•●••·••●·•••·••••••••••······•···•···•···•·······•···········•·•·•·•·•···•···•···•·•···•·•·•••·•·•••·•••·•·•···•························· · · · · · · · · · · · ··• · · · · · ··· · · · · · · · · ·●●•●●•••••••••·•·•·•·•·●·•·•·· ··························· ··············•·················•·····•·•·•··••·•···•·····• ··· · · · · · · · · · · ······················●•••●·······························•●●●●•●•●•••●•·••••••·●••••·•·············•···•·•·····•·•···········•···•·•·•···•·•·····•···•·•··•••••··●•··•···••······•·····•··············· · · · · · · · · · · ·•••••• · ··· ··· ··· ··· ··· ··· ··· ·•●●•●••••●••·••••••••••••••··················•···· ······· ······•·····•·•·······•·········•·•·•••·•··••·•••·•·•·· •······ ··· ··· · · · · · ············•·········●•●•••····●···························•●●•●●●••●●●••●•••●•●•●•●•●·•···•···•···•·•·•••·····•·•·····•···•·•·•·•·•·•·•·•·••····•·•·•·•••·●••••·●●•·●••••••···•······················· · · · · · · · · · · ●•●••·••· · · ··· · · · · · · · · · · · ·●●•●•●•●•●·•••••●•••●••••··················•·········· ··········•···•·•·····•·•·· ··•···•·•··•●•••·•●···•···•···•···· ··· ··· · · · · · · ·····················●●●●·••●··································•●•●●•●●●•·●•●•●•••●•●••·•·········•···•···•·····•·•·······•·•·•••·•·•·•·•·•···•···•·•·•••••·●●●•●·•••·•••·•••···•······················· · · · · · · · · · ·●●•●●··••● ··· ··· ··· ··· ··· ··· ··· ··· ··●•••●●●•••●•●•●•●●●●•·•·········•·······•·•·· ··•·•·····•···•·•·•·•••·····•·•·····•·•·•••··•●•●••·•·· ····•····•····· ··· ··· ··· · · · ···················•●•●●●•••●●····································••●•••●•●•●•●●●●●●●●•●•·······•·•·•·•···•·•···•••·•···•·•·•••••·•·•••·•·•••·•·•·•·•·••●•●·•●●●••··········•·•·•······················· · · · · · · · · ··•·••●•••••●●· · · · · · · · · · · · · · · · • ······••••●•••●•●●●●●•●···············•··••·····•·•·····•·····•·•·•·•••·•·•··••···•·•·•••••·●●•···· · · · ·●··········· ··· · · · · · · ·····●●···········•·•·••●•●•●●●·············································••●●•●●●●●●●•·•···•·•·•···••··•••·•··••·•·····•·•·•••••·••●••·•••·●•··•••·••●•●••●●•···········●●•··•···•··················· · ·•●•• · · · ··●••·•·••••●●●•●●· ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ····••●•●●●•●·•·········•·•·•··••·•···•·······•·•·•·•••·••●••·•·•••••···•••·•●●●●•••··· ··· ···•••••··•········ ··· ··· ··· · ····••●•●·······●•●••••·••●•●●●●●•················································●•●●●•●••·•·•·•·•·•·•••·•••·•·•••·•···•·••••••●•••●●●•••••●·•••·••●•••●●●●●············●●•●•••···············•········ ··•·••●•● · · •·•••••·•·••●•●●●•• · · · · · · · · · ··· ··· ··· ··· · · · ····· ··•●●●•●•·········•·•·•···•·······•······••·•·••●•••●●●•••••••●···••••••●•●···· ··· ···•●•••••●•··· · · · · · · · · · · ·••••·●●●•·····•••●•●•••••●•●•●•••●··············•●·································•●●•●·•·•·•···•••·•••·•••·•···•••·•···••••••●●●••●●●••●•●••●•·••●●●•●●●•···········•●•●•••●•●······················· ••••·••●•●••···•·••••●•••••••●•••●●●·· ··· ··· ··••●●· ··· ··· ··· ··· ··· ··· •·· ···•●●•·•···•·•·•••·•••·●••·•··••·•···•·••••●●●●••●●•••·••●·●••·••●•••●···· ··· ···•••••••●•••• ··· ··· ··· ··· ··· · •••••·●•●•●•●·•·••••●•●•●•••••••●●●●············•·●●●●●································•●••·•·•••·••●·••●••●●••••·●•••··•·••●•●•●●●•●•●●•·•·•●••●••·●●●••············•••●•••●•●••••·············●●●•···· ·•••·••••••●•··•·•·•·•••••·••••••●•●●··· ··· ·••··●●•●●● ··· ··· ··· ··· ··· ··· ··· ····•••·•·•···•••••••·●••·•··••·•·•···●•••●●●●●••·········••••••●••···· ··· ··· •·•·•·•••••·•·• ··· ··· ·•●•●••···· •·•••·●•••●•●·•·•·••••••●·••●•●●●•●●●•·······•●••·●●●●●•················•·················•••·•••·••●•●•●•••●••••·•••••·•·••●•●●●●●●•·············•·•·•·············●••••••·●••••·•·•·········●•●••••··· ·•·••••••●•●••···•·•·•·•••·•●●•●•●•●•••··· ·•••••••●•●•••········· ··· ··· ··· ··· ··· ······•·•••·•••·••●·•●●••·•·●••···•·●●●•●●●●·······························●●••••·•·•••·•·•···· ··· ··●••••·•·•·· •·••●•••●•●•●·•·•·•·••••••●●●•••●●●•●•●····•••••●•●●●•●•●•······································•·••●●••●•••●●●••·•●●••·••••●●●●●•································●●●●●••••·•••••·•·••······●●●••••••·•· ···•·•·••••●•······•···•·••••••●•••••••● ·••···•·••●•••••●·· ··· ··· ··· ··· ··· ··· ··· ··· ············••••●•••··●••••·•·●●●•●···················· ··· ······· ●•●•●••·•·•••·•···•·•·· ·•●•●••·•••···• •·••••••●•●●●·•·•·•·•·•·••••●●●●●•●•●•●●●●●••·•·••●•●•••●●●···············································•·•●●•●·•●●•●•••••●●●•······················●•●•··· ····●●●●●●•••·•••·•·•·•·••·•●●●●●●•·•···•· ·•·•••·••●•●••···•···•·•·••●●●•●•••●•●•●●●●●••···••●••·•●●●··················································•·•••·•●●••·••●•●···········•···········●•••●•····· ··••●•●••·•••·•·•·•·•·••●•●●●•●••······ •·•·••••●•●•●·•·•·•·•·•·••●•●•●•●•●•●●●●●●●●●••·••●••·•●●●●●················································•···••••●●●•••••●···•···········•······•●•●•●•●••·· · ··•●●●●•••●••·••••••••●•●•●●●●●·•····· ·•·•·•·•·••●•······•···•·●•••••••●•●•●●●•●●●••••·•••·•●●•●●●•··········••··· ······· ······························•●•••·•••······················•●•●•●••••·· · · •·●•●••••••·•·•·•·•·••●•●•●••·····• •·•••·••••●•●·•·•·•·•·•·••●•••●•●•●●●●●●●●●●●•●••·•·•●●●●●●●●●●·······••••········································•·•••••·•·····················●•●•●•●•●•●•••••· · · ••●●●•●••••·•••·••••●•●•●●●●····•• ·•·•·•·••••●••·•·•···•···••••●•••●•●●●•●●●·●●●•●••··•●●●●●•●•●●●·····•·••●●····································································●•●•●•●•••●•••••••· · ●·••●●●••••••·•·•·•·••••●•●●●···•·• •·••••••••●•●••·•·•·•·•·••••●•●•●●●●●●●●●●••●●●●●••·●●●●●●●●●●●●•···•••·●•●●•···············•···•···•···•···•···•···•••·•···•···•···•···••··•●●●●●●•●•●•●•●•●•••••• · •••●●●●•••••••••••••••●•●•●●•·•••• ···•·•·•·••●••••···•···•·••●•●•●•●•●•●●●•●·••●●●•●·●•●●●•●•●•●●●●·••·•·•·••●●●·····················•·············•·•·•·•·•················ · · · · · · · · · · · · · ●·••●••••·•·•·•·•••·••••●•●·•·••• •·•·••••••●●●·•••·•·•·•·••●●●•●●●●●●●●●●●•··•●●●●●•●●●●●●•●●●●●●●••••·•·••●●●●●●··················•·•·•···•···•·•·•••·•••·•···•···•···•·······•••••••·•·•·•·•·•···· ·●·●•·•●●•●•••••••••●•••••●•●●••••●· ·•···•·••●•●••·•••·•·•·•·●•●•●•●●●·●●●●●•●···●●●●●•●•●•●•●•●●●●●••·•·•···•••●●●●●··············•·•·•·•·•·······•·•·•·•·•·•·•·•·······•···· ···•••●•●•• ··•·••●•●·· · · ·••·••●·•••·••••••●••·••••●·•·●·· •·•·••••●•●●●·•·•••••••·•●·●●●●●●●·●●●●●●•··••●·●●●●●●●●●●●●●·●••••·•·•·••••●●●•●●··•·•·•···•·•·•·•·•·•·••··•••·•••·•••·····•••·•·•·•·•·•·····•••●●●●•··•·•·●●●●•·· ··· ●···●•·•••••••••••●•••••••··●•·· ······•••●•●•·····••••·· · ●·●•●•· ●•●•●••······•●•••●·●•●●●· ••······ •·••●•●•·•●●●···•···•·•·•·· · ··•·•·•·•·•·•·•·· · · · •·•·•·•···• · · ·•••●•●•• ··•·••●•●·· · · ··· •·· ··•••••••·•••·•·•·· ••··· •·• •·•·●•●•●·•·• •••••····●·●●●●··●●•●••••···· ●••••··●●·●●· ●••·●·•···••●●●••·●●●●●●•·•·•·•·•·•·······•·•·•·•·•·•···········•••·•·•···· ··· ••••●●●···•·•·●•●●······· · · •·· •••··•●••••••·•·• ·••··· ·•· ··•·•● ●•··• ··•·•·· · ●·●·●●· ●•·•• •·• · ·•●•••· ●··●●···•··••·• •••●●·••·●●•••●●●••·•·•···· ··· ··· ··· ··· ··· ··· ····•·•···· · · · ·•••••••• ··•·•·•···· · · · · ··· ···•· ••••• •·•···· •···· ··· ··· ●··••·•·· ··········· · ●··•· ●•·•··· · ••··•··●· ●●· •···•····•●·●●· · ·●· ●●••●••·•·············································· ··••••••••··•·•·•·•·•·• ··· · · ··· · • ·•·••··•· · •·· ···· · · · ··· · · · · · · ··· · ·· · · · · ··· • ·• ·· · · · · ·· · · ··• ····· · · · · · · · · · · · · · · · · ··· · · · · · ····•·•·•·•·•·•·•·•·•·•·• · · · · · · · · ··· · · · · · · · · · · · ··· ··· · · · · · · · · ··· · · · · · · · · ··· ··· ··· · · · · · · · · · · · · ······································· · · · •·•·•·•·•·•·•·•••·•·•·•·•·•·•·•·•·•·· · ··· · · · ··· · · · · · ·· ··· ············•·•·············•·•·•·•·•·•·•···············•·• ··•·•·•·•·········•·•·•·•·•·•·•·•·•···········•·······•·•·•···········•·•••·•••●●••·•·•·••●●•·•·•·•·•·•·•·•···•········ ··· ··· ····· ··· ··· •·············· ········•·····•···· ··········•···•···············•·····•···•···•·············································· ······•·••●●•···•···••●········ ··· ··· ··· ············· ····· ··· · ··•······ · · ··· · · ····· •···• ··· · ········• ·•· ··· ··· ··•·••· · ··•···•·•········ · · · · · · ··· · · · · · · ······· · · · · ··· ··●·· · · ··· · · · · · · · · · ··· ··•······ ··· · · · ·········••·•·······•·•·· ·•··•••···•••••·•·······•••···•··•• ····•·····•·•••·•·•••·•••·•············ ··················· ········•······ · · ····●●•·· ····•●●·· · · · · · ··· ··•···•·•·•·•·•········· ···· · ··•·•··············•·••••··••••·•·•···· ·••·•···•••••···•···········•••·•·•••·•············ · · ··············· · · ··········· · · · ····••●·· ··· ····· · · · · · ··· · ······•·•············ · •···•·•·•••••···•·•·•·•·•·•••••••·••●••••···••·•●•••••••●••·•••·•···•···•·•••••••·•·········•···•·····•·•···•·•·•·•·•·······•·•·•···•·•···· ······•·· ······•••·· · ··· •···•·· ··•·•·•·•·•·•·•·•···•··· ·······•·•••···············••••••••·••••••·····•·•••••••••••••••···········•••·•···· ··· ··· ··············· ··········· ······· ······· · · ····••• · · · ··••· · · ··• ··•···················•········ ······•·•·•••·•···•···•···•••••••••••••••••···•••••••••••••••••••••·•·····•·•••••·····················•···········•···•·················· ··········· · · ····•·· · ····•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•· ···········•·•·············•·•·•·•·•••••••···•••••··••••••·•••••••·········•••·•·· ··· ··· ··· ··· ······· ··· ··············· ··· ··· ··· ··· · ··•·· · · ··•·· · · ····•·•••·•·•·······•···•·•·•·•···• ········•·•·•••·•···········•·•·•••••••••••·••••••··•••••••••••••···•···•·•••·•·········································•·················· ······•••·······•······ ····•••••·•·•·•·•·•·•·•·•••••···•••· ··········•·············•·•·•·•·•••·•••·•••·•·•···•••••·•·•·•·· · ······•·· · · · · · · · · · · · · · · · · · · · ····· · · · · · · · · · ······•···········•·· · ····•·•••·•·•···········•·•••·······• ······•·•·•···············•·•·•·•·•••••••••••••••·•·•·•••••••·•·· · ··•·•·· · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · •·•·•••·•···•·•···· · ··•·•·•••·•·•·•·•·•·•·•·•·•••·····•· ···········•·•·············•·•·•·•·•·•·•••·•••·•·······•••••••···· · · ····· · · · · · · · · · · · · · · · · · ··· ········· · · · · · · · · · ··············· ··· · · ··•·•·•·•·············•·•·•···· · •···•·•·•••••···········•••••••·•••••••••••••••·•···•···•••••································ · · · · · · · · · · · · · · · · · · · · · · · · · ········•·•·•······ ··•·•••·•·•·•···•·•·•·•·•••••••····· ·······•·•·············•·•·•·•·•·•·•·•·•·•·•·····•·····•·•·· · · · · · · · · · · · · · · · · · · · · · · · · ········•·•········ · · · · · · · · ········· · · ··•·•·•···············•·•·•·•·•···· · · ··•·•·•·•·•···········•·•·•••·•·•·•••·•••·•···•·•·•···••• ··· ··· ··· ··· ··· ··· ··· ··· ··· ··· ············•···•·•·····•·········· ······· ··· ········· · ··•·•••••···•·······•···•·•·•••·•········· ·········•·•·· ··········•·•·•·•·•·•·•···········•········ · · · · · · · · · · · · · · · · · · · · ··········•·····•·•·····•·•···· · · · · · · · · ··· · · · ··•·•·················· ··•·•······ ··· · ······•·•·•·•···········•·•·•·•·•·•·•·•·········•·•·•···•·· ················································•·•·•·····•·•·····•••·•···························· ····•••·•···•···············•·•·•······· ··············· ··· ··············•····· · ········•·•···· · · · · · · · · · · · · · · · · · ············•·· ······· ····•·•·•·· · · · · · · · · · · · · · · · ··•·•············ ··· · · ··········· ··•···•·•·•·•···············•·•·•·•·•···· ··•·•·•·•••·•·· ··· ··· ··· ··· ··· ··· ··· ············•···•···•·······•···········•·•·•······ ··· ··········· ··· ····•·•·•·······•······ ··· ····•·•······· ·········•···········•·······•·•·•·· · · · ········•••·· · · · · · · · · · · · · · · · ··· ··················· ······· ··········•···· · · · ········· · · · · · ················· · · · · ··•···· · · · •···•·•·•·•·········•·•·•·•·•·•·•••·•·· ··· ····•••·•·· ··· ··· ··· ··· ··· ··· ··· ······•·•·············•·•···········•···•·•·•···················•······ ··· ··· ····•···•·•·•······ ··· ····•······ ···········•···· ····················•·· · · · · ··•···· · · · · · · · · · · · · · · · · ··• · · ··· ··· ··· ··· · ····· · ········•········ ······· ········· · · · · · ······•······ · · · · · · ····· ······•·•·•···· ······•···•···•·•·•·•·•·· · · · · ····•·· ··· ··· ··· ··· ······· ····••··························•·············•·•···•·•·········•·····•···•···· ··· ··•·•·•·•·· ··· ··· · · · · · · · ·····•·· · ················•·•···· · · · · · · · · · · · · · · · · · · · · · · ······• · · · · ··· ··· ··· · · ··· · · ··························· ······•·· · · · · ········· · · · · · · · · · · · · · ····•·•·•·· ··· ··•·•···•···•••·•·· ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ········•·•······ ··· ··•·•·•·•·· ··· ··· ··· · · · · · · · · · ····· · · · ····· ······•···· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ······· · · · · · · · · · · · ··•······ · · ··········•·•···· · · · · · · · · · · · · · · · ··· · · ··· ········•·•···· ··········· ··············· ··· · · · · · · · · · · · · · · · · · · · · · · · · ··•···· ··· · · · · · · · · · · · · · · · · · · ············· · · · · · · · · · · · · · · · · · ··· ······•···· · · · · · · ··· ··· · · · · · · · · · · · · · · ··· · · · · · · · · ··· ··· · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · ············· · · · · · · · · · · · · · ····················•·•···· ··· ··· ··········· ··· ··· · · ··· ··········· ··················•···· · · · · ··· ··· ··· · · · · · · · · · · · · · ····· · · · · · · · · · · · ··· ····· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ····· ··· · · · · · · · · · · · · · · · · · · · · ········· ··········· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ··· · · · · · · · · · · · · · · · · · · · ····· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
use it
html
<script type="module" src="https://ascii.rest/ascii.js"></script> <ascii-art piece="aurora-fjord"></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 { auroraFjord } from "ascii.rest/pieces";
<Ascii piece={auroraFjord} /> A client component, so it works in the Next.js app router as it is. Pass the name instead, piece="aurora-fjord", to fetch the piece only when it mounts.
astro
--- // npm install github:bas3line/ascii import Ascii from "ascii.rest/astro"; --- <Ascii piece="aurora-fjord" />
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 { auroraFjord } from "ascii.rest/pieces";
const el = document.querySelector<HTMLCanvasElement>("canvas")!;
const stop = mount(el, auroraFjord); 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.
/*
* aurora fjord: curtains of aurora ripple over a fjord between snowy
* mountains. The still water holds a broken shimmer of them, and a red cabin
* on the far shore keeps its lamps lit.
*
* Shaded in colour per cell on a square grid, then drawn as a halftone: dot
* size is brightness, ordered-dithered, in the palette colour nearest its hue.
* The land is built once; each frame shades the sky, then mirrors it into the
* water.
*/
import type { Frame, Meta } from "../types.ts";
export const meta = {
name: "aurora fjord",
category: "scenes",
note: "aurora curtains rippling over a still fjord, a cabin lit on the shore",
cols: 200,
rows: 100,
cell: 1,
fps: 15,
ground: "#05080f",
palette: [
"#0b1322", "#101b30", "#16243f", "#1e3050", "#2a3f63",
"#0e3a33", "#11573f", "#167a4c", "#22a05c", "#3ccb73", "#7cf0a0", "#c8ffdc",
"#0f5f5c", "#16877f", "#2cb5a6", "#7fe6d6",
"#2a1f52", "#432b78", "#6a3c9f", "#9558c6", "#c48ae4", "#363a72", "#4f5596", "#1b4f63",
"#1a2236", "#283350", "#3b4a6e", "#566a92", "#7d91b8", "#a9bad9", "#d6e0f2", "#9fc9cf",
"#0f1a1c", "#173128", "#24493a",
"#4a1517", "#7c2420", "#b23a2a", "#d65aa8",
"#ffd27c", "#ffb04a", "#fff2c4",
"#eef3ff",
],
} satisfies Meta;
const W = 200, H = 100;
const WL = 62; // the waterline
const DOTS = " ·•●";
const COVER = [0, 0.3, 0.6, 1];
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, NEAR = 1, FAR = 2, SHORE = 3, WALL = 4, ROOF = 5, PANE = 6, TREE = 7, DOOR = 8;
const CAB = [142, 161]; // the cabin's walls, x from and to
const PANES = [[145, 148], [156, 159]];
const DOOR_X = [150, 152];
const LAMPS = [[147, 1], [158, 0.8]]; // pane centres and their strength
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): 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);
const a = hash(xi, yi), b = hash(xi + 1, yi), c = hash(xi, yi + 1), d = hash(xi + 1, yi + 1);
return a + (b - a) * u + (c - a) * v + (a - b - c + d) * u * v;
}
function fbm(x: number, y: number, octaves: 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);
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);
// Ranges as tent peaks [x, height, slope], roughened.
const LEFT: [number, number, number][] = [[25, 38, 1.3], [6, 29, 0.9], [50, 25, 1.0], [72, 13, 0.6]];
const RIGHT: [number, number, number][] = [[172, 30, 1.15], [194, 24, 0.85], [151, 16, 1.0], [212, 22, 0.6]];
const DISTANT: [number, number, number][] = [[100, 10, 0.5], [119, 12, 0.55], [86, 7, 0.45], [134, 8, 0.5]];
function range(x: number, peaks: [number, number, number][], seed: number, rough: number): [number, number] {
let m = -99, px = 0;
for (const [cx, h, s] of peaks) {
const v = h - Math.abs(x - cx) * s;
if (v > m) (m = v), (px = cx);
}
const j = rough * (fbm(x * 0.09, seed, 3) - 0.5) + rough * 0.45 * (noise(x * 0.45, seed + 5) - 0.5);
return [m + j * Math.min(1, Math.max(0, m) / 6), px];
}
export default function auroraFjord(): Frame {
const P = meta.palette.map(hex);
const N = W * H;
const out: string[] = new Array(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 < 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 land, built once ------------------------------------------------
const mat = new Uint8Array(N);
const sr = new Float32Array(N), sg = new Float32Array(N), sb = new Float32Array(N);
const rec = new Float32Array(N); // how much aurora light a cell picks up
const rim = new Float32Array(N); // aurora light caught on ridgelines and treetops
const nearTop = new Float32Array(W), farTop = new Float32Array(W), peakX = new Float32Array(W);
for (let x = 0; x < W; x++) {
const [hl, pl] = range(x + 0.5, LEFT, 3.1, 4);
const [hr, pr] = range(x + 0.5, RIGHT, 7.7, 4);
const [hd] = range(x + 0.5, DISTANT, 11.3, 2.2);
nearTop[x] = WL - Math.max(hl, hr, 0);
peakX[x] = hl > hr ? pl : pr;
farTop[x] = WL - Math.max(hd, 0);
}
const shoreTop = (x: number) => WL - 2.2 * smooth(134, 140, x) * smooth(178, 168, x) - 0.6 * noise(x * 0.3, 2);
const cabBase = WL - 2.2;
for (let r = 0; r < WL; r++) {
for (let x = 0; x < W; x++) {
const k = r * W + x;
const y = r + 0.5;
if (y >= nearTop[x]) {
mat[k] = NEAR;
const px = peakX[x];
const side = x + 0.5 - px;
const depth = y - nearTop[x];
const height = WL - nearTop[x];
// Faces turned toward the fjord catch the aurora; the ridge between
// the faces wanders as it comes down from the peak.
const ridge = px + (depth + 1) * 0.6 * (noise(y * 0.1, px) - 0.5);
const inward = px < 100 ? 1 : -1;
const face = smooth(-4, 4, (x + 0.5 - ridge) * inward);
// ribs and couloirs running down the fall line, each with a lit side
const u = x + depth * 0.45 * Math.sign(side || 1);
const rib = (v: number) => fbm(v * 0.13, px * 0.37, 3);
const grad = (rib(u + 1) - rib(u - 1)) * 7 * inward;
// the snow reaches further down the ribs than the couloirs, in fingers
const reach = 3 + height * (0.62 + 0.42 * rib(u + 40));
const streak = smooth(0.56, 0.64, fbm(u * 0.32, y * 0.035 + px, 3)) * smooth(1, 5, depth);
// a stand of spruce climbing the slope behind the cabin, jagged on top
const cx = x + 0.5 - 152;
const wood = WL - 18.5 + 9 * (cx / 19) ** 2 + 1.5 * (noise(x * 0.7, 9) - 0.5) - 2.6 * hash(x, 77) * ((x & 1) ? 1 : 0.3);
const snow = smooth(reach + 1.6, reach - 1.6, depth) * (1 - smooth(WL - 3, WL - 0.5, y)) * (1 - 0.5 * streak);
const lit = clamp(0.35 + 0.55 * face + grad * 0.5);
// blue-grey rock below the snow, a little lighter on the lit faces
const rv = 0.75 + 0.5 * fbm(x * 0.4, y * 0.4, 2);
const rr = (0.05 + 0.03 * lit) * rv, rg = (0.065 + 0.035 * lit) * rv, rb = (0.11 + 0.05 * lit) * rv;
const s = 0.34 + 0.66 * Math.pow(lit, 1.5);
sr[k] = mix(rr, 0.62 * s + 0.04, snow);
sg[k] = mix(rg, 0.7 * s + 0.05, snow);
sb[k] = mix(rb, 0.86 * s + 0.09, snow);
rec[k] = snow * (0.25 + 0.75 * lit) + 0.06;
rim[k] = smooth(2.2, 0.3, depth) * 0.5;
if (y > wood && cx > -14 - 2 * hash(r, 3) && cx < 13 + 2 * hash(r, 4)) {
mat[k] = TREE;
const h = hash(x * 13 + r, 5);
sr[k] = 0.02 + 0.03 * h, sg[k] = 0.045 + 0.045 * h, sb[k] = 0.06 + 0.04 * h;
rec[k] = 0.05;
rim[k] = smooth(wood + 1.6, wood + 0.2, y) * (0.7 + 0.3 * h);
}
} else if (y >= farTop[x]) {
mat[k] = FAR;
const depth = y - farTop[x];
const snow = smooth(0.5, 0.62, fbm(x * 0.18, y * 0.25, 3) * 0.6 + (1 - depth / 7) * 0.55);
const lit = 0.5 + 0.3 * (noise(x * 0.25, y * 0.1) - 0.5);
sr[k] = mix(0.075, 0.22 * lit + 0.12, snow);
sg[k] = mix(0.1, 0.27 * lit + 0.15, snow);
sb[k] = mix(0.17, 0.36 * lit + 0.24, snow);
rec[k] = 0.2 + 0.3 * snow;
}
// the shelf the cabin stands on, snowed over
if (x > 132 && x < 180 && y >= shoreTop(x)) {
mat[k] = SHORE;
const f = 0.6 + 0.3 * fbm(x * 0.3, y * 0.5, 2);
sr[k] = 0.26 * f, sg[k] = 0.3 * f, sb[k] = 0.42 * f;
rec[k] = 0.4;
rim[k] = 0;
}
}
}
// a spruce treeline along the foot of both ranges, open where the fjord runs in
const spruce = (tx: number, th: number, tw: number, tb: number, guard: ((k: number) => boolean) | null) => {
for (let r = Math.max(0, Math.floor(tb - th)); r < WL; r++) {
const y = r + 0.5, dy = y - (tb - th);
if (dy < 0 || y >= tb + 0.5) continue;
const tier = (dy + th * 0.3) / 1.8;
const w = (dy / th) * tw * (0.7 + 0.45 * (tier - Math.floor(tier))) + 0.35;
for (let x = Math.max(0, Math.floor(tx - tw - 1)); x <= Math.min(W - 1, tx + tw + 1); x++) {
const k = r * W + x;
const ex = x + 0.5 - tx;
if (Math.abs(ex) > w || (guard && guard(k))) continue;
mat[k] = TREE;
const h = hash(x * 13 + r, 5);
const s = ex < 0 ? 0.7 : 0.3; // the aurora is up and left
sr[k] = 0.02 + 0.03 * s * h, sg[k] = 0.04 + 0.05 * s, sb[k] = 0.055 + 0.045 * s;
rec[k] = 0.05;
rim[k] = Math.max(smooth(1.6, 0.2, dy), ex < 0 && ex < -w + 1 ? 0.45 * smooth(th, 0, dy) : 0);
}
}
};
const solid = (k: number) => mat[k] === WALL || mat[k] === ROOF || mat[k] === PANE || mat[k] === DOOR || mat[k] === SHORE;
for (let x = -1; x < W + 2; ) {
const h = hash(Math.floor(x * 7), 21);
const open = smooth(96, 80, x) + smooth(122, 136, x);
const onShelf = x > 132 && x < 180;
if (open > 0.05 && !(x > 136 && x < 166)) {
const th = (3.2 + hash(Math.floor(x * 3), 5) * 3 + (hash(Math.floor(x * 5), 8) > 0.7 ? 2.4 : 0)) * Math.min(1, open) * (onShelf ? 0.7 : 1);
if (th > 1.5) spruce(x + hash(Math.floor(x), 2), th, 1 + hash(Math.floor(x), 4) * 0.6, onShelf ? shoreTop(x) - 0.4 : WL + 0.3, onShelf ? solid : null);
}
x += 2 + 2.2 * h;
}
// The cabin: red boards, a snowed roof, two warm panes, a door, a chimney.
const eave = cabBase - 7;
const roofTop = eave - 8;
const CHIM = CAB[1] - 5, CHIM_TOP = eave - 8.5;
for (let r = 0; r < WL; r++) {
for (let x = CAB[0] - 3; x <= CAB[1] + 3; x++) {
const k = r * W + x;
const y = r + 0.5;
const cx = (CAB[0] + CAB[1] + 1) / 2;
if (x >= CAB[0] && x <= CAB[1] && y >= eave && y < cabBase + 0.5) {
mat[k] = WALL;
const boards = r & 1 ? 0.82 : 1;
const s = (0.5 + 0.5 * ((CAB[1] - x) / (CAB[1] - CAB[0]))) * boards;
sr[k] = 0.7 * s, sg[k] = 0.14 * s, sb[k] = 0.11 * s;
rim[k] = 0;
for (const [a, b] of PANES) if (x >= a && x <= b && y >= eave + 1.5 && y < cabBase - 2) mat[k] = PANE;
if (x >= DOOR_X[0] && x <= DOOR_X[1] && y >= eave + 1.5) {
mat[k] = DOOR;
sr[k] = 0.16, sg[k] = 0.06, sb[k] = 0.05;
}
}
const half = 12.5 - (eave - y) * 1.45;
if (y >= roofTop && y < eave && Math.abs(x + 0.5 - cx) <= half) {
mat[k] = ROOF;
const snowy = y < eave - 1;
const s = 0.78 + 0.22 * ((cx - x - 0.5) / 12);
if (snowy) (sr[k] = 0.78 * s), (sg[k] = 0.84 * s), (sb[k] = 0.96 * s);
else (sr[k] = 0.12), (sg[k] = 0.05), (sb[k] = 0.06);
rec[k] = snowy ? 0.5 : 0;
rim[k] = 0;
}
if (x >= CHIM && x <= CHIM + 1 && y >= CHIM_TOP && y < eave - 4) {
mat[k] = WALL;
const s = x === CHIM ? 1 : 0.55;
sr[k] = 0.2 * s, sg[k] = 0.21 * s, sb[k] = 0.27 * s;
rim[k] = 0;
}
}
}
// a few spruce on the shelf, beside the cabin
for (const [tx, th] of [[134, 7], [137.8, 10], [166.5, 9], [170, 6], [174.5, 8]]) {
spruce(tx, th, 2.2, shoreTop(tx) + 0.5, (k) => mat[k] === WALL || mat[k] === ROOF || mat[k] === PANE || mat[k] === DOOR);
}
// the warm light the panes throw on the snow and the air around them
const lampLand = new Float32Array(WL * W);
for (let r = 0; r < WL; r++) {
for (let x = 0; x < W; x++) {
const k = r * W + x, m = mat[k];
if (m === PANE || m === WALL || m === ROOF || m === DOOR) continue;
let g = 0;
for (const [lx, s] of LAMPS) {
const wx = x + 0.5 - lx, wy = r + 0.5 - (cabBase - 2.5);
const d = Math.sqrt(wx * wx * 0.6 + wy * wy * 2.2);
g += s * Math.exp(-d / 5.5) * 0.6;
}
lampLand[k] = g * (m === AIR ? 0.3 : m === TREE ? 0.4 : 0.75 + 0.5 * hash(x, r + 31));
}
}
// the sky's unevenness and its stars
const haze = new Float32Array(WL * W);
for (let k = 0; k < WL * W; k++) haze[k] = fbm((k % W) * 0.04, Math.floor(k / W) * 0.07, 3);
const star = new Float32Array(WL * W);
for (let k = 0; k < WL * W; k++) {
const h = hash(k % W, Math.floor(k / W) + 101);
if (h > 0.986) star[k] = 0.35 + (h - 0.986) * 45;
}
// rows of the water that break the reflection into strips
const gap = new Uint8Array(H);
for (let r = WL; r < H; r++) gap[r] = hash(r, 404) < 0.3 ? 1 : 0;
// per-column aurora state, filled each frame
const baseA = new Float32Array(W), tallA = new Float32Array(W), envA = new Float32Array(W);
const baseB = new Float32Array(W), envB = new Float32Array(W);
const RAYS = 4 * W;
const raysA = new Float32Array(RAYS + 2), raysB = new Float32Array(RAYS + 2);
const R = new Float32Array(WL * W), G = new Float32Array(WL * W), B = new Float32Array(WL * W);
const lightX = new Float32Array(W); // the aurora's light falling on the land below
const ray = (arr: Float32Array, u: number) => {
const s = u * 4;
let i = Math.floor(s);
const f = s - i;
i = ((i % RAYS) + RAYS) % RAYS;
return arr[i] + (arr[i + 1] - arr[i]) * f;
};
return (t, { color } = {}) => {
// --- the curtains -------------------------------------------------------
for (let x = 0; x < W; x++) {
const u = x / W;
// the main curtain sweeps down from the upper left, low over the fjord,
// and lifts again to the right; ripples travel along it and fold it
baseA[x] = 5 + 40 * Math.pow(Math.sin(Math.min(1, u / 0.6) * Math.PI / 2), 1.5) - 13 * smooth(0.6, 0.95, u)
+ 2.6 * Math.sin(x * 0.07 - t * 0.55) + 1.4 * Math.sin(x * 0.17 + t * 0.9 + 1.3) + 2.2 * Math.sin(x * 0.22 + t * 1.2)
+ 4 * (fbm(x * 0.015 + t * 0.03, 4.2, 2) - 0.5);
tallA[x] = 11 + 8 * fbm(x * 0.03 - t * 0.05, 1.7, 2);
envA[x] = smooth(0.0, 0.2, u) * smooth(0.98, 0.72, u) * (0.4 + 0.8 * fbm(x * 0.022 - t * 0.07, 8.8, 3));
// a fainter curtain behind, higher up, on the right
baseB[x] = 14 + 4 * Math.sin(x * 0.035 + t * 0.3 + 2) + 1.6 * Math.sin(x * 0.11 - t * 0.7);
envB[x] = smooth(0.45, 0.7, u) * smooth(1.05, 0.85, u) * (0.25 + 0.5 * fbm(x * 0.03 + t * 0.05, 3.3, 2));
}
for (let i = 0; i <= RAYS + 1; i++) {
const u = i / 4;
raysA[i] = 0.14 + Math.pow(fbm(u * 0.6 + t * 0.35, t * 0.12, 3), 2.4) * 2.5;
raysB[i] = 0.1 + Math.pow(fbm(u * 0.45 - t * 0.2, 5 + t * 0.1, 3), 2.2) * 2.0;
}
for (let x = 0; x < W; x++) {
let s = 0;
for (let d = -24; d <= 24; d += 6) {
const xx = Math.min(W - 1, Math.max(0, x + d));
s += envA[xx] + 0.4 * envB[xx];
}
lightX[x] = s / 9;
}
const flick = 0.92 + 0.05 * Math.sin(t * 2.3) + 0.03 * Math.sin(t * 7.1);
// --- sky and land ---------------------------------------------------------
for (let r = 0; r < WL; r++) {
const y = r + 0.5;
const v = y / WL;
for (let x = 0; x < W; x++) {
const k = r * W + x;
const m = mat[k];
let cr: number, cg: number, cb: number;
if (m === AIR) {
const hz = 0.85 + 0.3 * haze[k];
cr = (0.025 + 0.03 * v * v) * hz;
cg = (0.04 + 0.07 * v * v) * hz;
cb = (0.1 + 0.11 * v * v) * hz;
// curtain A: a sharp lower hem, rays rising and fading to violet
let a = 0;
const d = baseA[x] - y;
if (d > -4 && d < 46) {
const bend = Math.abs(baseA[Math.min(W - 1, x + 1)] - baseA[Math.max(0, x - 1)]);
const hc = tallA[x];
const lean = ray(raysA, x + d * 0.22);
const prof = d < 0 ? Math.exp(-d * d * 0.9) : (1 - Math.exp(-(d + 0.4) * 1.1)) * Math.exp(-d / hc);
// the rays, over a continuous bright band along the hem
const band = d < 0 ? Math.exp(-d * d) : Math.exp(-d / 3);
a = (prof * lean + 0.3 * band * (0.55 + 0.45 * Math.min(1.4, lean))) * envA[x] * (1.15 + 0.35 * bend);
const up = clamp(d / (hc * 1.6));
const gk = 1 - smooth(0, 0.5, up), vk = smooth(0.4, 0.9, up);
const tk = 1 - gk - vk;
cr += a * (0.18 * gk + 0.06 * tk + 0.42 * vk);
cg += a * (1.0 * gk + 0.78 * tk + 0.16 * vk);
cb += a * (0.48 * gk + 0.7 * tk + 0.75 * vk);
// pink at the very hem where it is brightest
const hem = Math.exp(-((d + 0.6) ** 2) * 1.2) * smooth(0.3, 0.8, a) * 0.8 * (0.45 + 0.55 * Math.min(1, lean));
cr += hem * 0.95, cg *= 1 - 0.55 * Math.min(1, hem * 1.6), cb += hem * 0.4;
}
// curtain B, further away, thinning out toward the top of the frame
const db = baseB[x] - y;
if (db > -3 && db < 30) {
const prof = db < 0 ? Math.exp(-db * db) : (1 - Math.exp(-(db + 0.4))) * Math.exp(-db / 9);
const b = prof * ray(raysB, x + db * 0.18) * envB[x] * 0.85 * smooth(0, 8, y);
const up = clamp(db / 12);
cr += b * (0.1 + 0.4 * up);
cg += b * (0.75 - 0.5 * up);
cb += b * (0.7 + 0.2 * up);
a += b;
}
// a little glow round the curtain, kept tight under the hem so the
// hem reads as an edge over dark sky
const below = y - baseA[x];
const gl = envA[x] * (below > 0 ? Math.exp(-below / 6) * 0.1 : Math.exp(below / 8) * 0.18);
cr += gl * 0.12, cg += gl * 0.62, cb += gl * 0.52;
// airglow on the horizon
const ag = Math.exp(-(WL - y) / 10) * (0.1 + 0.16 * lightX[x]);
cg += ag * 0.7, cb += ag * 0.75, cr += ag * 0.2;
const st = star[k];
if (st > 0) {
const tw = 0.7 + 0.3 * Math.sin(t * (1.3 + 3 * hash(x, r)) + 6.28 * hash(r, x));
const s = st * tw * clamp(1 - a * 1.6) * smooth(WL - 2, 30, y);
cr = Math.max(cr, s * 0.9), cg = Math.max(cg, s * 0.94), cb = Math.max(cb, s);
}
} else {
cr = sr[k], cg = sg[k], cb = sb[k];
const L = lightX[x] * rec[k];
cr += L * 0.03, cg += L * 0.14, cb += L * 0.1;
const e = rim[k];
if (e > 0) {
const q = e * (m === TREE ? 0.2 + 0.45 * lightX[x] : 0.05 + 0.22 * lightX[x]);
cr += q * 0.25, cg += q * 0.95, cb += q * 0.7;
}
if (m === PANE) {
const f = flick + 0.04 * Math.sin(t * 5.3 + x);
cr = f, cg = 0.76 * f, cb = 0.38 * f;
} else if (m === DOOR) {
// light through the crack of the door
if (x === DOOR_X[1] && r > eave + 1) (cr = 0.55 * flick), (cg = 0.36 * flick), (cb = 0.14 * flick);
}
}
const lg = lampLand[k] * flick;
if (lg > 0) cr += lg, cg += lg * 0.62, cb += lg * 0.26;
R[k] = cr, G[k] = cg, B[k] = cb;
}
}
for (let r = 0; r < H; r++) {
const y = r + 0.5;
let floor = 0.1, fade = 1;
const dw = y - WL;
const deep = r >= WL ? mix(1, 0.45, dw / (H - WL)) : 1;
const ry = WL - 1 - (r - WL) - Math.round(0.4 * Math.sin(r * 0.9 + t * 0.6));
const r0 = Math.max(0, ry) * W, r1 = Math.max(0, ry - 1) * W, r2 = Math.max(0, ry - 2) * W;
for (let x = 0; x < W; x++) {
const k = r * W + x;
let cr: number, cg: number, cb: number;
if (r < WL) {
cr = R[k], cg = G[k], cb = B[k];
const m = mat[k];
floor = m === AIR ? 0.1 : m === NEAR ? 0.05 : m === TREE ? 0.04 : 0.06;
} else {
// still water: the mirror image, stretched and broken by slow ripples
const wave = noise(x * 0.04 + t * 0.05, r * 0.55 - t * 0.35);
const sx = x + (0.5 + dw * 0.12) * Math.sin(r * 1.3 + t * 1.6 + wave * 4);
let ix = Math.floor(sx);
const fx = sx - ix;
ix = Math.max(0, Math.min(W - 2, ix));
const a0 = r0 + ix, a1 = r1 + ix, a2 = r2 + ix;
const sky = mat[a0] === AIR;
let kr = (sky ? 0.55 : 0.64) * (0.82 + 0.3 * wave) * deep;
if (sky && gap[r] && wave < 0.45) kr *= 0.12;
// the cabin's own image is soft; the lamplight road below carries it
const ms = mat[a0];
if (ms === PANE) kr *= 0.4;
else if (ms === WALL || ms === ROOF || ms === DOOR) kr *= 0.7;
const gx = 1 - fx;
cr = ((R[a0] * gx + R[a0 + 1] * fx) * 0.5 + (R[a1] * gx + R[a1 + 1] * fx) * 0.3 + (R[a2] * gx + R[a2 + 1] * fx) * 0.2) * kr;
cg = ((G[a0] * gx + G[a0 + 1] * fx) * 0.5 + (G[a1] * gx + G[a1 + 1] * fx) * 0.3 + (G[a2] * gx + G[a2 + 1] * fx) * 0.2) * kr;
cb = ((B[a0] * gx + B[a0 + 1] * fx) * 0.5 + (B[a1] * gx + B[a1 + 1] * fx) * 0.3 + (B[a2] * gx + B[a2 + 1] * fx) * 0.2) * kr;
if (ms !== WALL && ms !== DOOR) cr += 0.02, cg += 0.035, cb += 0.065;
// a pale line where the water meets the shore
if (r === WL) {
const e = 0.3 * (0.3 + 0.7 * smooth(0.25, 0.75, noise(x * 0.3, t * 0.4)));
cr += e * 0.6, cg += e * 0.85, cb += e;
}
// the lamplight laid on the water as a broken golden road
if (dw < 14 && x > 138 && x < 166) {
const rip = noise(x * 0.5 - t * 0.2, r * 1.4 - t * 1.5);
for (const [lx, s] of LAMPS) {
const lw = 1 + dw * 0.1;
const q = (x + 0.5 - lx) / lw;
const g = Math.exp(-q * q) * Math.exp(-dw / 8) * smooth(0.3, 0.65, rip) * s * 1.6 * flick;
cr += g, cg += g * 0.68, cb += g * 0.28;
}
}
floor = sky ? 0.07 * deep : 0.03;
fade = smooth(H + 3, H - 12, y);
}
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));
}
}
}
const lines: string[] = [];
for (let r = 0; r < H; r++) lines.push(out.slice(r * W, (r + 1) * W).join(""));
return lines.join("\n");
};
}