0x92cb…dc61

All memos sent from and to 0x92cb…dc61.

PILLARSstyle.immutables.artbody { background-color: #0d0d0d; color: #ffffff; } .bg-light { background-color: #0d0d0d!important; } h1, h2, h3 { color: #ffffff; } .text-white { color: #ffffff!important; } .btn-success { background-color: #ffffff; border-color: #ffffff; color: #0d0d0d; } .btn-success:hover { background-color: #ececec; border-color: #ececec; color: #0d0d0d; } .btn-success:focus { background-color: #ffffff; border-color: #ffffff; box-shadow: none; } .btn-secondary { background-color: #1a1a1a; border-color: #333333; color: #ffffff; } .btn-secondary:hover { background-color: #1a1a1a; border-color: #8d8d8d; color: #ffffff; } .btn-secondary:focus { background-color: #1a1a1a; border-color: #333333; box-shadow: none; } .btn-outline-secondary { border-color: transparent; color: #666666; } .btn-outline-secondary:hover { color: #ffffff; background-color: transparent; border-color: #8d8d8d; } .btn-outline-secondary:not(:disabled):not(.disabled):active { color: #ffffff; background-color: transparent; border-color: #ffffff; } .btn-outline-secondary:focus { box-shadow: none; } .btn:focus { box-shadow: none; } .btn-info { color: #666666; background-color: transparent; border-color: transparent; } .btn-info:hover { color: #8d8d8d; background-color: transparent; border-color: #8d8d8d; } .btn-warning { color: #666666; background-color: transparent; border-color: transparent; } .btn-warning:hover { color: #a4a4a4; background-color: transparent; border-color: #a4a4a4; } .btn-outline-warning { color: #a4a4a4; border-color: #a4a4a4; } .btn-outline-warning:hover { color: #ffffff; background-color: #1a1a1a; border-color: #ffffff; } .modal-content { background-color: #0d0d0df7; color: #ffffff; } .modal-header { border-bottom: 1px solid #333333; } .modal-footer { border-top: 1px solid #333333; align-items: center; justify-content: center; } .close { color: #666666; } .close:hover { color: #ffffff; } .table { color: #ececec; } .table td { border-top: 1px solid #333333; } .table-bordered td, .table-bordered th { border: 1px solid #333333; } .form-control { color: #ffffff; background-color: transparent; border: 1px solid #333333; } .form-control:focus { color: #ffffff; background-color: transparent; border-color: #8d8d8d; box-shadow: none; } .input-group-text { color: #666666; background-color: transparent; border: 0; } .nav-tabs { border-bottom: 1px solid #333333; } .nav-tabs .nav-link.active { color: #ffffff; background-color: transparent; border-color: #ffffff #ffffff #0d0d0d; } a { color: #666666; } a:hover { color: #ffffff; } .card { border: none; background-color: #1a1a1a; } .card-img, .card-img-bottom { background-color: #0d0d0d; border: 1px solid #333333; border-bottom: 0; cursor: zoom-in; } .overlay-dark { background-color: rgba(13,13,13,.9); border: 1px solid #333333; border-top: 0; } .navbar-toggler { background-color: #1a1a1a; } .wmde-markdown { color: #b0b0b0; } .wmde-markdown a { color: #ffffff; } .btn-primary { background-color: #8d8d8d; border-color: #8d8d8d; color: #0d0d0d; } .btn-primary:hover { background-color: #a4a4a4; border-color: #a4a4a4; color: #0d0d0d; } .btn-primary:focus { background-color: #8d8d8d; border-color: #8d8d8d; box-shadow: none; } .btn-outline-primary { color: #8d8d8d; border-color: #8d8d8d; } .btn-outline-primary:hover { color: #0d0d0d; background-color: #8d8d8d; border-color: #8d8d8d; } .btn-danger { background-color: #b6b6b6; border-color: #b6b6b6; color: #0d0d0d; } .btn-danger:hover { background-color: #cecece; border-color: #cecece; color: #0d0d0d; } .btn-outline-danger { color: #b6b6b6; border-color: #b6b6b6; } .btn-outline-danger:hover { color: #0d0d0d; background-color: #b6b6b6; border-color: #b6b6b6; } .btn-outline-success { color: #ececec; border-color: #ececec; } .btn-outline-success:hover { color: #0d0d0d; background-color: #ececec; border-color: #ececec; } .btn-outline-info { color: #9b9b9b; border-color: #9b9b9b; } .btn-outline-info:hover { color: #0d0d0d; background-color: #9b9b9b; border-color: #9b9b9b; } .form-check { color: #666666; } .d-flex { color: #ececec; }
PILLARSinfo.immutables.art# PILLARS A guidepost on the road through time. A “herm” was a stone post with a head carved into it, set at a boundary or where one road met another. They were named for Hermes — messenger, god of roads and thresholds, the one who carried word between worlds and walked travelers over the edges of things. A herm was not decoration. It was placed where a person would need it: at the fork, at the border, at the point where the way stopped being obvious. It told you where you were, and it spoke on behalf of someone not present. These are herms for a road nobody can step off. We are all traveling through time at the same speed, in one direction, without a map, and the crossings that matter are not marked on the ground. A PILLAR is a temporal guidepost set along your path. It keeps the hour, marks the season, and at the turnings it has something to say. ## It Speaks A PILLAR speaks on the new moon and on the full moon — roughly twice a month, twenty-four or twenty-five times a year. Herms stood at physical boundaries; this one speaks at temporal ones. The words are its own. **The oracle is carried inside the stone:** its learned weights, its vocabulary and the code that gives it speech are written into the work itself, and there is no puppeteer controlling it from afar. It composes each sentence in front of you from the transaction it was cast from and from the date. Ask on the same day from anywhere and you are told the same thing. What it says is not advice and is not an answer. It tells you something. What you do with it is yours. --- ## Consulting the PILLAR A PILLAR needs nothing. Neglect it for a year and it will have said twenty-five things you did not hear, and be none the worse for it. Nothing you do sustains it and nothing you neglect can harm it, which is an unusual arrangement with something you are asked to keep. You are not its caretaker. It is the one doing the tending. It keeps the months for you and hands you a sentence to carry through the fortnight. It tells you where the year has got to, what the sky is doing, when the season turns and when it will turn back. It weathers at your side for as long as you last, and then for a long time after. It does not know when you will need what it says, and does not wait to find out. It speaks on the turn of the month and leaves the sentence standing, which is why one so often seems to have been waiting for you: it spoke early and the moment caught up. ### Watch the Moon The practice is the rhythm, not the reading. Go to it at the dark moon and at the full moon — the two hinges of the month — and it will have something for you. Nothing is required of you in between. The dark moon is the closed hand: the month has not happened yet. What it says then is best taken as something to set out with. The full moon is the open one: the month is at its height and everything in it is visible, including what you would rather not look at. The same sentence lands differently on the two days, and after a year you will know which of the two your PILLAR is better at. ### Carry the Sentence Between one utterance and the next, the PILLAR holds what it last said. It does not refresh, and there is nothing else to get from it that fortnight. This is deliberate. You are meant to carry the sentence, not consume it. Read it on the day, then leave it alone and let it work on the ordinary hours — the argument you were already having, the decision you have been circling, the thing you have not said. An oracle that could be asked again immediately would only ever be a way of avoiding the first answer. Come back to it near the end of the fortnight. It will have collected whatever happened to you, which is the whole trick. ### Learn Your PILLAR Its manner is set for life and will not adjust itself to suit you. What that manner is you already know from its hexagram; what you cannot know in advance is how it wears. So watch for the preoccupation. Doors. Water. The ledger. Stone. Across several utterances you will find the thing your stone is always, in the end, talking about — which is worth more than any single sentence, because it tells you the angle everything is being said from. Do not read one utterance and decide what your PILLAR is. Read a year of them. ### Read the Six Lines On the day it changes its mind, the shaft resolves into six carved lines before it speaks. That is its hexagram, fixed at the moment it was set down and never altered. The lines are not a second prophecy. They are the announcement that what follows is new — the stone clearing its throat. If you arrive and see them, you have come on a speaking day and the words are fresh. If you arrive and see only the stone, what it tells you is what it has been telling everyone since the last turning. The figure is also the PILLAR's nature — its voice, its temperature, the words it keeps returning to — which is set out under **The Hexagram**, below. Seeing your own carved into the shaft is worth more once you know what it decides. The same figure is cut small and permanently above the brow: six strokes read left to right from the first line up, parted in the middle where a line is broken. One of the six is marked, and **only the mark moves**. The figure is cut once and never recut. What advances, on each of the four turns of the year, is which line carries the mark — so it comes back round every eighteen months, and in that time the stone has been every version of itself and none of them has been a different stone. In the old reading a changing line is what lets one figure be read through another, and it does that here. Read the marked line the other way and you have the PILLAR's relating figure: not a new hexagram for the stone, but a second one held beside its own for the season. What it lends is a subject. Your stone is still the stone of doors and gates; this season it is also thinking about water. ### Notice the Season The same stone does not say the same kind of thing as the seasons turn. The term it stands in picks which of its four manners it uses, so it moves through its own voices as the year advances and comes back round. The pattern is fixed and it is yours: another stone warns in a different month, and there is no season that is grim for all of them. The season moves one thing more, and this is the part worth watching for. At each turn the changing line advances, and the relating figure it opens onto lends the stone a second subject for the whole of that season — a preoccupation that is not its own, held beside the one that is. Four times a year the borrowed subject changes; every eighteen months the cycle returns. It is a leaning and not a takeover. Counted over many utterances a stone reaches for its own words about eighteen times in a hundred and for the borrowed ones about thirteen, against four for a figure it has nothing to do with — three times the background, and still short of its own. About one utterance in ten comes out differently for it. You will not notice it in a single reading. Over a season you will start to see what else the stone has been circling, and over eighteen months you will have watched it circle six different things and come back to the first. Its manner and its temperature are untouched by any of this. A PILLAR borrows a subject for a season; it never borrows a voice. Which means the utterances arrange into a shape you can only see across a year, and only for your own PILLAR. When a reading feels unusually hard or unusually generous, look at the term before you take it personally. You may simply have come in the cold. ### Mark the Rare Nights Sometimes the sky is doing something while it speaks, and the two are not equally rare. A PILLAR catches every eclipse of its life — all of them, without exception — and that is not luck. An eclipse can only happen at a new or full moon, and those are the only days it opens its mouth. So roughly one utterance in seven arrives during an eclipse somewhere on earth, about four a year. Frequent enough to be a rhythm rather than an omen. Meteor showers are the rare ones, because they answer to the sun rather than the moon and have no reason to fall on a speaking day. A PILLAR meets one about every eighteen months, and can go six years without. Neither makes for a better prophecy. They are marked utterances, not favored ones — and the shower nights are the ones worth writing down. ### Ask, if You Must Press **C** and it will take a question. It cannot answer, it will not try, and it knows nothing about you. It replies in its own manner, colored a little by the words you used, and it will give the same reply to the same question for ever. So asking is useful for exactly one thing, and it is not information. The reply comes back oblique, and what you notice is your own reaction to it — the reading you reach for first, the meaning you supply, the part you resist. That was the answer, and it was yours before you asked. ### The Chronicle Press **T** and the chronicle opens: the years it has spoken in, then the months of a year, then what it said in that month. Click a row to open it and the heading to come back, or use the keys — arrows move, enter goes in, escape comes back out. Nothing was recorded. There is no archive to download and no log to fetch. Knowing which years and months it spoke in costs nothing, because that follows from the moon alone — but open a month and the stone has to think, and you will feel it think. It is working that utterance out again from the transaction and the date, which is all it ever needed. The pause is not a loading bar. It is the PILLAR being asked, again, what that day was. Which has a strange consequence worth sitting with. Whoever holds a PILLAR in the distant future can recover what it said in a historic winter, and the person who owned it then need never have looked at it once. The history belongs to the stone for the benefit of those who consult it. Close it and what it worked out is gone. Nothing is lost, because none of it was ever kept. ### Keep the Record Press **S** to save the whole turn — stone, lines, words — as it moved. Press **P** for the moment you are looking at. Press **A** and the frame closes on the head: the capital, the face, the top of the shaft. It is the same stone, drawn the same way, standing nearer. Left uncropped in a small circle — a timeline, a chat list — the image gives you more sky and plain than carving, and the sky is the one thing here that is not yours. Press **P** to save the avatar. Press **A** again to step back. One thing does change in that frame, and only there. An omen normally keeps its own hour: an eclipse manifests between nine and three and an aurora after dark. A profile picture is looked at whenever somebody looks at it, so in the crop the omen is always present, whatever the clock says. It is the rarest thing a PILLAR carries and the least worth hiding. In the full frame it still waits for its hour. Keep them. Twenty-five a year is a small enough number to hold, and a year of them read together says something no single one does. The stone is aging while you do it, on the same road, so a record kept long enough becomes a record of you both. --- ## The Stone Weathers Nothing is stored to achieve any of this: the hour is read from the clock, the weathering from elapsed time, the sky from the arithmetic of the sky, and everything else from the transaction that minted the edition. A PILLAR can be recomputed exactly as it stood on any date, past or future, by anyone holding the code. There is no table of dates inside to go stale. A PILLAR asked about a time that will outlast its keeper answers from the same arithmetic as one asked about tomorrow. Every PILLAR bears the mark, `][`, struck into the lower right. ## How Many Six hundred and forty are set down — sixty-four tens, which is the arithmetic behind the number rather than a promise about how they land. Ten to a figure is what it would take for every voice the oracle has to be carried by a handful of stones rather than by one. They do not come out in even portions. The figure is read from the transaction rather than dealt, so some voices end up with six pillars and some with eighteen — an unevenness nobody arranged, and a rarity nobody wrote down. What six hundred and forty buys is the near certainty that none of the sixty-four goes unspoken — about one chance in three hundred that any voice is missing. At half the number it is closer to one chance in three, and a piece with a voice it built and never used is worse than a smaller piece. ## The Meridian Each PILLAR stands at a meridian and keeps that meridian's time. Its sun climbs and sets on the local clock, the moon takes its turn, and the shadow swings and lengthens to match — short and underfoot at that meridian's noon, reaching across the plain at its dusk. No two are lit alike at the same moment, and a wall of them shows the world's daylight spread across it. Your PILLAR is not on your clock. It stands where it stands. If it keeps a meridian half a world from yours, its day turns while you sleep, and you will come to it after the fact — which is the ordinary condition of anyone consulting an oracle. ## The Hexagram A hexagram is six lines, each broken or whole — and it has been since about 1000 BC. There are sixty-four, named in King Wen order, which is a traditional sequence with no generating rule. It cannot be derived; it can only be known. Yours might be **2. Field**, or **48. Welling**, or **1. Force**. Three things follow from it, and together they are what makes one PILLAR sound unlike another. **Its idiom.** There are sixteen ways the oracle can open its mouth — *you shall*, *beware the*, *seek not*, *who shall*, *let not*, and so on. Your PILLAR is allowed **four of the sixteen**, and which four is decided by its hexagram. All sixty-four hexagrams get a different set. This is why one stone warns where another foretells and a third only ever asks: it is not a mood, it is the whole range it has. **Its temperature.** How far the model is allowed to wander when it chooses each next word, between **0.62 and 0.80**. A cool PILLAR speaks plainly and a hot one is strange, sometimes barely coherent — and it stays that way for fifty years. There are nineteen possible temperatures. A difficult PILLAR is not a broken one, and the strange ones repay a patience the plain ones do not need. **Its preoccupation.** Sixteen small sets of words, one to a PILLAR: doors and gates, or water and tide, or stone and boundary, or light and lamp and fire, or dust and ash and bone. When the oracle has a choice between two sentences it will reach for the one containing its own words. Measured over hundreds of utterances it lands on them about 19% of the time, against 4% for another PILLAR's — so it is a leaning rather than a drumbeat, and it takes several utterances to notice. That is the point. An oracle with a subject is not the same thing as an oracle that can talk about nothing else. **What the hexagram does not do is choose the words.** Two PILLARS carrying the same figure share an idiom, a temperature and a preoccupation, and still say entirely different things — the sentence itself is seeded from the transaction. Not that the oracle has infinite things to say: measured over fifty thousand utterances, about one in seventy repeats a sentence some other PILLAR has already given, and it is almost always a short one. A PILLAR repeats itself far more rarely, perhaps once in eight years. Sharing a hexagram is sharing an accent, not a script. And the six lines on the shaft are the number itself in binary, which is the same thing written twice: once as a figure a diviner would recognize, once as the bits a machine reads. --- ## Metadata Eight traits are settled by the minting transaction and never change. These are the ones rarity is counted from. | Attribute | Possible Values | |------------|-----------| | Order | Plain, Fluted, Banded, Tapered, Stepped, Broken | | Stone | Granite, Sandstone, Basalt, Marble, Serpentine, Porphyry, Obsidian, Alabaster | | Eyes | Bracket, Carved, Hollow, Single, Blind, Lit | | Mouth | Seam, Grille, Set, Vent, Sealed | | Capital | None, Abacus, Cornice, Torch, Wreath, Halo, Obelisk, Crown | | Ground | Survey, Cracked, Dune, Saltflat, Void | | Weather | None, Chipped, Fissure, Moss | | Omen | None, Aurora, Eclipse | Three more are fixed at mint and score nothing. A place is not a prize, and a figure is not a prize either. Meridian is reported as the place; Offset is the same fact in hours, because a name is only useful if you know what it means. | Attribute | Possible Values | |------------|-----------| | Meridian | One of twenty-seven named places, one for each whole-hour offset | | Offset | The hours from GMT that the name stands for, GMT−12 to GMT+14 | | Hexagram | One of the sixty-four, in King Wen order, with its six lines | Five are read from the date rather than the transaction, and will read differently tomorrow. They are reported because they are what the PILLAR is working from, not because they are rare — a distribution compiled from them disagrees with one compiled next week. | Attribute | Possible Values | |------------|-----------| | Condition | Pristine, Weathered, Worn, Ancient — read from elapsed time | | Term | One of the twenty-four solar terms, from the sun's place on the ecliptic | | Sky | Clear, one of eight meteor showers, or a solar or lunar eclipse | | Changing | Which of the six lines is turning, advancing once a season | | Relating | The figure read through the marked line this season. The PILLAR's own Hexagram is unchanged | `Sky` reports the day's celestial event. The changing sky the PILLAR visibly stands under is deliberately left out of metadata: it turns over four times a day, and an attribute that changes between one compile and the next is worse than no attribute. Meridian is what decides it, and Meridian is reported. An Omen only shows at the hour that suits it: an aurora needs darkness, an eclipse needs a sun to cover. A PILLAR carrying one reveals it on its own schedule rather than the viewer's — except under **A**, where it always shows, because a rarity nobody can wear is not much of a rarity. Rarity is summed improbability across the eight fixed traits, so one very rare trait outranks several merely uncommon ones. It is settled at mint and untouched by weather or hour: a PILLAR's rarity was decided when it was set down, not by how long it has stood. Its rarity, and nothing beyond that — what a stone comes to be worth to whoever keeps it is a different question, settled over years rather than in a single transaction, and this table has no opinion on it. The tiers are Common, Marker, Landmark, Monument — which is what a stone by a road is called, as it becomes worth the walk. ## Technical Notes For anyone who wants to open the stone. None of this is needed to use one. **The oracle.** A decoder-only transformer of 332,640 parameters: five layers, four heads, width 56, a 32-token context and a vocabulary of 2,501 words. Weights are quantized to int8 with float32 scales; the norms and biases stay in float32. It was written by hand in numpy with manual backpropagation, checked against finite differences, and trained on 49,201 lines cut from public-domain philosophy, the prophetic books of the King James Bible, and the Nostradamus quatrains in translation, together with 986 lines written for the piece. **Where it lives, and where it runs.** The weights, the vocabulary, the inference code and the almanac are all part of the artwork's own bytes, stored in the calldata of an Ethereum transaction and referenced by the immutables.art contract. Nothing is fetched at view time and no model is called. But the arithmetic is done in your browser, not by the EVM: Ethereum holds the stone, the stone holds the oracle, and a browser animates it. That is a different claim from on-chain *inference*, and the weaker one — it is also, at 16.3 million gas for the whole work, the only one that is affordable. Running this network in the EVM would cost billions. **Fitting it in one transaction.** Since Fusaka activated in December 2025, EIP-7825 has capped a single Ethereum transaction at 2^24 gas, regardless of how much room remains in the block. For a data-heavy transaction like this one, the EIP-7623 floor makes nonzero calldata effectively cost forty gas a byte. A pure-data transaction can therefore carry at most 418,905 nonzero calldata bytes; a larger one is not merely expensive but invalid. The work as written is 573,676 bytes. So the model is Huffman-coded and packed five characters to four bytes, turning 454,048 base64 characters into 327,295 bytes of text, and the commentary comes out, because that prose is this document and is posted once already. What is left is 406,693 bytes and 16.3 million gas, with about twelve thousand to spare. A canonical Huffman code was chosen over gzip on purpose: the quantized weights are close to random past their distribution of values, so gzip beats plain entropy coding by under four per cent, and the decoder is forty lines rather than three thousand. What is posted can never be corrected, and forty lines can be read by eye. **What a sentence depends on.** The transaction hash and the date, and nothing else. The hash gives the hexagram, which fixes the four openings, the temperature and the favored words; the hash and the day together seed the sampler. The day also fixes which line of the figure is changing, and the figure that line points at lends a second set of favored words for the season. The search asks the model up to forty times and keeps the first reply that passes the acceptance rule, which rejects doubled words, dangling clauses, article disagreement, and relative clauses that never become sentences. **Whether it will say the same thing in fifty years.** `Math.sqrt` is required to be correctly rounded and is safe on any engine. `Math.exp` and `Math.tanh` are not, and the network calls both — so a last-bit difference could in principle pick a different token and everything after it would diverge. Perturbing both and comparing 480 utterances: no change at one ULP, none at 1e-9, none at 1e-6, four at 1e-5. The tolerance is therefore at least several billion times the difference two honest implementations produce, with the true boundary somewhere above 1e-6 and varying by generation. The int8 quantization is why — coarse weights make wide gaps between tokens, so a sampling threshold almost never lands near a boundary. The compression that made it fit is what made it reproducible. `check_determinism.js` is kept with the work: in twenty years it is the test of whether a new engine can still speak for a PILLAR. **The sky.** Solar position from Meeus chapter 25, lunar phase from chapter 49, eclipses from chapter 54 computing gamma and the shadow's size, and Terrestrial Time converted to civil time by the Espenak–Meeus polynomials. Checked against independent references: 224 solar eclipses in the twenty-first century, matching NASA's count; every named eclipse from 1999 to 2045 with the right type; season lengths within half an hour of the known unequal values. **The chronicle.** Which days a PILLAR has spoken on is `speaksOn`, pure arithmetic over the moon, so the year and month menus are free — no model runs to build them. Opening a month calls `readingFor(PILLAR, day)` for the one or two utterances that month holds, about seven tenths of a second each, with the thread handed back between them. Nothing is cached and nothing is written: closing it discards the lot, and every line of it can be worked out again. Verified by reconstructing a PILLAR’s readings cold and out of order and comparing them against the same PILLAR’s life lived day by day — 27 of 27 identical, and unchanged by whatever the stone had been doing in between. **One dependency.** The artwork is a p5.js sketch, and p5 must be supplied by whatever is showing it. The surface it uses is small — the drawing is `fill` and `rect` and nothing else — but it is honest to say the stone needs that much of a hand to stand up. --- ## Colophon **Artist:** Gutenblock **Code License:** [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) **Edition License:** [NIFTY](https://www.nftlicense.org/) PILLARS is posted by the operator of immutables.art, on immutables.art. Said here rather than left to be discovered.
BigBangH0xc7baaa5cab68007340396847497c487dc1311fc51ac186f0c170b7aaaf73af53``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Seed the p5js random seed using the first 32 bits of the hash. if(props.editionId && ((props.editionId >= 586 && props.editionId <= 635) || (props.editionId >= 938 && props.editionId <= 962) ) ) { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "True"; const burn = 150 * (props.editionId % 50); for (let i = 0; i < burn; i++) { p.random(); } } else { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "False"; } // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(+borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
BigBang``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Seed the p5js random seed using the first 32 bits of the hash. if(props.editionId && ((props.editionId >= 587 && props.editionId <= 635) || (props.editionId >= 939 && props.editionId <= 962) ) ) { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "True"; const burn = 150 * (props.editionId % 50); for (let i = 0; i < burn; i++) { p.random(); } } else { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "False"; } // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(+borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
BigBang``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); // Seed the p5js random seed using the first 32 bits of the hash. p.randomSeed(+props.transactionHash.substr(0, 10)); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
BigBang # BigBang [Immutables.art](http://immutables.art) started with BigBang. Immutables.art is a decentralized and on-chain generative art platform. Each Immutables.art Project Edition is generated from the minting transaction hash and the project code obtained from the Ethereum blockchain. **Artist:** Gutenblock.eth & [Mark Egli](https://markegli.com/) **Code License:** [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) **Edition License:** [NIFTY](https://www.nftlicense.org/) ## Metadata | Attribute | Possible Values | |------------|-----------| | Styles |Monochrome, Spectrum, Spotlight, Random | Borders | Yes, No | | Edges | Wrap, Bounce | | Speeds | Quantized, Varied | | Trails | Yes, No | | Background | Color based on transaction hash | Dwell Before Bang | Time delay based on transaction hash | | Margin | Random size based on transaction hash | | Number of Balls | Number based on transaction hash | | For Each Ball | Numbers based on the transaction hash for: | |- Initial X Speed | | - Initial Y Speed | | - Ball Color | | - Ball Size