t.p.n parity

This commit is contained in:
mehbark 2026-01-24 20:55:36 -05:00
parent 112961960d
commit a411ef4665
Signed by: mbk
GPG key ID: E333EC1335FFCCDB
28 changed files with 899 additions and 6 deletions

View file

@ -24,6 +24,7 @@ export default function (eleventyConfig) {
eleventyConfig.addPassthroughCopy("site-src/res"); eleventyConfig.addPassthroughCopy("site-src/res");
eleventyConfig.addPassthroughCopy("site-src/*.png"); eleventyConfig.addPassthroughCopy("site-src/*.png");
eleventyConfig.addPassthroughCopy("site-src/**/*.html");
eleventyConfig.setLayoutsDirectory("layout"); eleventyConfig.setLayoutsDirectory("layout");

View file

@ -0,0 +1,10 @@
---
title: Fun web stuff
description: Stuff that mehbark made that you can play with on your browser
---
- [Spout](/spout): Fun, oft-interactive HTML/JS pieces
- [gol](https://pyrope.net/gol): [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life) with checkboxes, made in elm
- [TIMEDOG](https://pyrope.net/TIMEDOG): a clock that measures time in Patricia Taxxon's [TECHDOG](https://patriciataxxon.bandcamp.com/album/techdog-1-7)
- [davehash](https://pyrope.net/davehash/): you know what a hash modus is, right?
- [old site](https://web.archive.org/web/20260124004542/https://terezi.pyrope.net/): the site before this one. [aka onepn](/twopn)

View file

@ -12,13 +12,29 @@ export function PostLink({post}) {
{" "} {" "}
({tags.join(", ")}) ({tags.join(", ")})
{" "} {" "}
(<time datetime={post.date.toISOString()}>{post.date.toDateString()}</time>) (<time dateTime={post.date.toISOString()}>{post.date.toDateString()}</time>)
</> </>
} }
## Posts ## About me
- [I go by mehbark](/awesomebark) on the internet!
- I did get this domain just for the pun, but alas, I can't claim to be <span title="I think that's maybe Vriska?">the number one Terezi fan</span>.
- I put code on [my Forgejo instance](https://g.pyrope.net) and [my GitHub](https://github.com/mehbark).
- I had fun making posts on [cohost](https://cohost.org) before it died;
I enjoyed making [CSS crimes](https://cohost.org/mehbark/tagged/css%20crimes) the most, of course.
- I occasionally enjoy making bad video games and putting them on [my itch.io](https://mehbark.itch.io)
If you want to do something on your browser AS SOON AS POSSIBLE, check out [my page of fun web stuff](/fun-web-stuff)!
If you want longer-form stuff of even less consistent quality, check out [my blog](https://b.pyrope.net)!
---
## Latest posts
<ul> <ul>
{props.collections.post.toReversed().map(p => {props.collections.post.toReversed().map(p =>
<li key={p.url}><PostLink post={p} /></li> <li key={p.url}><PostLink post={p} /></li>
)} )}
</ul> </ul>
---

View file

@ -0,0 +1,63 @@
<div class="badges">
<a href="https://bambosh.dev/unofficial-homestuck-collection">
<img src="/res/88x31/homestuck.gif" alt="homestuck" title="read it">
</a>
<a rel="me" href="https://critter.cafe/@mehbark">
<img src="/res/88x31/mastodon_button_3.gif" alt="The mastodon mastodon playing with a paper airplane next to text that says Follow me on Mastodon" title="if you want">
</a>
<a href="https://cyber.dabamos.de/88x31/">
<img src="/res/88x31/88x31.gif" alt="88 X 31" title="most of these are from here">
</a>
<img src="/res/88x31/stamp-sadness.gif" alt="i like stamps but they would look out of place sad face" title="i mean the fancy ones that aren't 88x31, they just don't line up">
<a href="https://archlinux.org/">
<img src="/res/88x31/archlinux.gif" alt="arch linux" title="it's just easier tbh">
</a>
<a href="https://www.w3.org/Style/CSS">
<img src="/res/88x31/css2.gif" alt="made with cascading style sheets" title="very few of them, but some">
</a>
<a href="https://www.debian.org/">
<img src="/res/88x31/debian.gif" alt="the debian logo next to text that says powered by debian" title="it really is; that's why it's still working">
</a>
<a href="https://store.steampowered.com/app/1610900/The_Genesis_Project/" target="_blank">
<img src="/res/88x31/e-hs.gif" alt="text that says download SBURB next to the SBURB logo, the SBURB part is all fancy" title="not really but this is dang cool">
</a>
</a>
<img src="/res/88x31/this-user-loves-terezi.png" alt="terezi next to text that says THIS USER LOVES TEREZI in terezi's typing quirk" title="(platonically)">
<!--
hi cefqrn hi hi hi hi hi hi hi hi
-->
<a href="https://www.mozilla.org/firefox/">
<img src="/res/88x31/firefoxget.gif" alt="The firefox logo next to text that cycles between get firefox, rediscover the web, the browser you can trust, etcetera" title="i use it">
</a>
<img src="/res/88x31/ie_exploder.gif" alt="Text that says FREE: Microsoft Internet Exploder next to the internet explorer logo, which turns into the earth and then BLOWS UP" title="real fact, ask your local librarian">
<a href="https://irc.pyrope.net">
<img src="/res/88x31/ircworks.gif" alt="irc works" title="sometimes. uh, not right now">
</a>
<!--
-->
<img src="/res/88x31/2019.gif" alt="Still using buttons in 2019!" title="get it? because it isn't 2019?">
<a href="https://www.vim.org/">
<img src="/res/88x31/madewithvi.gif" alt="made with vi" title="technically the improved version and a bit of the vscode version and a bit of evil">
</a>
<img src="/res/88x31/i-was-on-cohost.gif" alt="eggbug next to text that says I was on cohost" title="i was!">
<!--
-->
<a href="http://web.archive.org/web/20240000000000*/hackles.org">
<img src="/res/88x31/hackles-button.png" alt="the two penguins from hackles looking at teal text that says hackles.org" border=0>
</a>
<img src="https://deep-freezer.neocities.org/images/misc_buttons/HomestuckButton.gif" alt="a pretty pixel art gif by @coldcalzone that shows the broad strokes of the acts of homestuck. very cool">
<a href="http://www.sbcl.org/"><img src="https://www.sbcl.org/sbclbutton.png" alt="(get 'sbcl)"></a>
<a href="https://terezi.pyrope.net"><img alt="terezi's head is seen from behind looking at the sky. on the right, it says terezi.pyrope.net and >:]" src="https://terezi.pyrope.net/88x31.png"></a>
<a href="https://wowperfect.net/"><img title="wow, perfect" src="https://wowperfect.net/img/88x31.png"></a>
<a href="https://coolstation.space"><img title="cool, station" src="https://coolstation.space/cool_assets/88x31/coolstation.gif"></a>
<a href="https://spax.zone"><img title="Spaxolotl's zone" src="https://spax.zone/images/buttons/button.gif"></a>
<a href="https://kokoscript.com"><img title="Koko's NetWeb Site" src="https://kokoscript.com/img/button/kokoscript.gif"></a>
<a href="https://deerz.one"><img title="the (ida) deer zone" src="https://deerz.one/img/88x31/deerzone.gif"></a>
<a href="https://moonbase.lgbt" title="Moonbase Dot LGBT"><img src="https://moonbase.lgbt/88x31/moonbase.gif" alt="Moonbase Dot LGBT" width="88" height="31" /></a>
<a href="https://easrng.net"><img title="em's net" src="https://badges.easrng.net/easrng.gif"></a>
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" title="Lebsite Weague"><img src="/res/88x31/lebsite-weague.png" alt="lebsite weague" /></a>
<a href="https://moonbase.lgbt/blog/nes-pictionary-in-memoriam/" title="NES Pictionary"><img src="https://moonbase.lgbt/88x31/nes-pictionary.png" alt="NES Pictionary" width="88" height="31"></a>
<a href="https://nixos.org" title="fixes this"><img src="/res/88x31/nixos-88x31.png" alt="nixos logo" /></a>
<iframe src="https://incr.easrng.net/badge?key=terezi.pyrope.net" style="background: url(//incr.easrng.net/bg.gif)" title="increment badge" width="88" height="31" frameborder="0"></iframe>
<a href="https://lisanne.gay"><img alt="lisanne.gay 88x31" src="https://lisanne.gay/88x31_pls_DO_hotlink.png"></a>
</div>

View file

@ -28,11 +28,21 @@ title: terezi.pyrope.net
</head> </head>
<body> <body>
<h1 id="site-title"><a href="/">T3R3Z1.PYROP3.N3T</a></h1> <h1 id="site-title"><a href="/">T3R3Z1.PYROP3.N3T</a></h1>
<main>
{% if title != "terezi.pyrope.net" %} {% if title != "terezi.pyrope.net" %}
<h1><a href="{{ url or "" }}">{{ title }}</a></h1> <h1><a href="{{ url or "" }}">{{ title }}</a></h1>
{% endif %} {% endif %}
{{ content | safe }} {{ content | safe }}
</main>
<footer>
{% include "./badges.njk" %}
<div class="webring">
<h3>this web site is part of the m,cai webring</h3>
<a href="https://spax.zone">←</a> <a href="/ring.html">everyone</a> <a href="https://lisanne.gay">→</a>
</div>
<iframe title="splat button" width="110" height="100" src="https://www.myinstants.com/instant/lancer-splat-18107/embed/" frameborder="0" scrolling="no"></iframe>
</footer>
</body> </body>
</html> </html>

BIN
site-src/res/88x31/2019.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

BIN
site-src/res/88x31/css2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
site-src/res/88x31/e-hs.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -23,6 +23,11 @@ body {
/* idk */ /* idk */
/* font-feature-settings: "aalt", "c2sc", "ccmp", "cv13", "cv17", "cv19", "cv20", "cv25", "cv28", "cv37", "cv43", "cv44", "cv46", "cv47", "cv49", "cv55", "cv57", "cv62", "cv68", "cv69", "cv70", "cv71", "cv75", "cv76", "cv77", "cv79", "cv80", "cv81", "cv82", "cv84", "cv90", "cv91", "cv92", "cv98", "frac", "liga", "locl", "smcp", "ss01", "ss04", "ss05", "ss11", "ss12", "subs", "sups", "mark", "mkmk"; /* font-feature-settings: "aalt", "c2sc", "ccmp", "cv13", "cv17", "cv19", "cv20", "cv25", "cv28", "cv37", "cv43", "cv44", "cv46", "cv47", "cv49", "cv55", "cv57", "cv62", "cv68", "cv69", "cv70", "cv71", "cv75", "cv76", "cv77", "cv79", "cv80", "cv81", "cv82", "cv84", "cv90", "cv91", "cv92", "cv98", "frac", "liga", "locl", "smcp", "ss01", "ss04", "ss05", "ss11", "ss12", "subs", "sups", "mark", "mkmk";
*/ */
min-height: 100%;
}
main {
min-height: 60vh;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
@ -256,9 +261,53 @@ video {
Courier, Courier,
monospace; monospace;
background: var(--accent2); background: var(--accent2);
margin: 0;
} }
#site-title > a { #site-title > a {
color: var(--accent); color: var(--accent);
text-decoration: none; text-decoration: none;
} }
footer {
text-align: center;
background-color: var(--accent2);
width: 100%;
margin: 0;
}
/*.badges a, marquee a, header a {
border: none;
background-color: #00000000;
text-decoration: none;
}*/
.badges {
image-rendering: pixelated;
transition: transform 0.1s;
overflow-x: clip;
font-size: 0pt;
padding: 0.5rem;
}
.badges > * {
display: inline-block;
width: 88px;
height: 31px;
vertical-align: middle;
}
/*
.badges > :hover {
transform: scale(2);
}
*/
.badges > a > img,
.badges .ff-container {
width: 88px;
height: 31px;
}
.webring {
margin: 0 auto;
}
.webring > a {
font-size: 2rem;
}

View file

@ -2,6 +2,7 @@
title: On the reverse-chronological ordering of items title: On the reverse-chronological ordering of items
description: I pontificate on the merits and missteps of ordering items by their associated date in a fashion antiparallel to our logical conception of time. description: I pontificate on the merits and missteps of ordering items by their associated date in a fashion antiparallel to our logical conception of time.
tags: post,short tags: post,short
date: 2026-01-24 20:00:00
--- ---
the bit is that this is actually for testing reverse chron but i'm going to turn it into a little piece about reverse chron. the bit is that this is actually for testing reverse chron but i'm going to turn it into a little piece about reverse chron.

96
site-src/ring.html Normal file
View file

@ -0,0 +1,96 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
html {
width: 100%;
height: 100%;
margin: 0;
}
body {
color: #b8b;
padding-left: 1rem;
background-color: #111;
margin: 0;
}
h1 {
}
li {
list-style-type: georgian;
border-left: 1lh outset var(--color);
}
a {
color: #c3c;
text-decoration: none;
}
a:visited {
color: #b2b;
}
canvas {
border-radius: 4113cm;
border: 1px solid #b8b;
image-rendering: pixelated;
width: min(514px, 95vw);
}
</style>
<title>the m,cai webring</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
// yo dawg,
var updates_per_update = 1;
window.onload = () => {
let ch = [...document.querySelector("ul").children];
for (let c of ch) c.appendChild(document.createElement("span"))
for (let i = 0; i < ch.length; i++) {
ch[i].onmouseover = () => {
for (let c of ch) c.querySelector("span").innerText = "";
let l = ch[i==0?ch.length-1:i-1].querySelector("span");
let r = ch[i==ch.length-1?0:i+1].querySelector("span");
l.innerText = "(left)";
r.innerText = "(right)";
};
}
let c = document.querySelector("canvas").getContext("2d");
let [cx, cy] = [256, 256];
let randr = (l, h) => Math.random() * (h-l) + l;
let parts = ch.map(c => ({x: cx, y: cy, color: c.style.getPropertyValue("--color")}));
let dist = (x1, y1, x2, y2) => Math.sqrt((x2-x1)**2 + (y2-y1)**2);
function update() {
// c.clearRect(0, 0, 512, 512);
for (const p of parts) {
c.fillStyle = p.color;
c.fillRect(p.x, p.y, 1, 1);
p.x += Math.round(randr(-1, 1));
p.y += Math.round(randr(-1, 1));
if (dist(cx, cy, p.x, p.y) >= 257) {
if (p.x > cx) p.x--;
if (p.x < cx) p.x++;
if (p.y > cy) p.y--;
if (p.y < cy) p.y++;
}
}
}
setInterval(() => {for (let i=0;i<updates_per_update;i++)update()}, 0);
}
</script>
</head>
<body>
<h1>the m,cai webring</h1>
<ul>
<li style="--color: #008282"><a href="https://terezi.pyrope.net">terezi.pyrope.net</a>
<li style="--color: #a0a08b"><a href="https://lisanne.gay">lisanne.gay</a>
<li style="--color: #14a02e"><a href="https://coolstation.space">coolstation.space</a>
<li style="--color: #306850"><a href="https://spax.zone">spax.zone</a>
</ul>
<canvas width=512 height=512></canvas>
</body>
</html>

646
site-src/spout/index.html Normal file
View file

@ -0,0 +1,646 @@
<!doctype html>
<html><head><title>spout</title>
<meta charset="UTF-8">
<meta content="spout" property="og:title" />
<meta content="i post html" property="og:description" />
<meta content="https://terezi.pyrope.net/spout" property="og:url" />
<meta content="#008282" data-react-helmet="true" name="theme-color" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html {
--fg: #ede;
--bg: #233;
--accent: #76a6e4;
color: var(--fg);
background-color: var(--bg);
}
body {
width: 100%;
height: 100%;
margin: 0;
}
a[href^="#s"], a[href^="#s"]:visited {
text-decoration: none;
font-weight: bold;
}
a, a:visited {
color: var(--accent);
text-decoration: dotted underline;
}
a:hover {
text-decoration: solid underline;
}
article {
padding: 1rem;
border-bottom: 1px solid var(--fg);
margin-inline: 2rem;
margin-bottom: 1rem;
width: min(calc(95vw - 4rem), 15cm);
}
canvas {
image-rendering: pixelated;
}
.emoticon {
font-family: "Courier New", "Courier Std", courier, monospace;
font-weight: bold;
color: #008282;
}
.controls {
display: flex;
}
.controls > button {
flex: 1;
aspect-ratio: 1;
font-size: 2rem;
font-weight: bold;
}
h1 {
font-size: 1.2em;
}
h2 {
font-size: 1.1em;
font-style: italic;
}
</style>
<script>
// pretty neat, right?
let hl_ref = () => {
if (!document.location.hash) return;
document.querySelectorAll("article").forEach(a => a.style.backgroundColor = null);
document.querySelector(document.location.hash).style.backgroundColor = "#344";
};
window.onhashchange = hl_ref;
Number.prototype.map = function(a,b,c,d){return c+(d-c)*((this-a)/(b-a))};
let elems = (s, ids) => ids.split(" ").map(i => document.getElementById(`s${s}-${i}`));
window.onload = () => {
hl_ref();
let [s9lhs, s9rhs] = elems(9, "lhs rhs");
const params = new URLSearchParams(window.location.search);
params.get("s9-lhs") && (s9lhs.value = params.get("s9-lhs"));
params.get("s9-rhs") && (s9rhs.value = params.get("s9-rhs"));
};
</script>
</head>
<body>
<h1 style="margin: 1rem">spout: reverse-chron html pieces by <a href="https://terezi.pyrope.net">mehbark</a></h1>
<article id="s16">
<h1><a href="#s16">#</a> binary search over the integers (todo)</h1>
<h2 id="s16num">0</h2>
<p>low: <span id="s16low">?</span>, high: <span id="s16high">?</span></p>
</article>
<article id="s15">
<h1><a href="#s15">#</a> eva interface stuff style noodling</h1>
<div style="display: grid; background-color: black; filter: blur(0.5px) saturate(1.2); padding: 1rem; justify-items: center; align-items: center; aspect-ratio: 2/1;">
<div style="background: repeating-linear-gradient(-45deg, red, red 0.99cm, transparent 1cm, transparent 2cm, red 2.01cm); filter: blur(2px) drop-shadow(0 0 1px red); grid-area: 1/1; width: 100%; height: 100%"></div>
<div style="background-color: black; grid-area: 1/1; z-index: 1; width: 90%; height: 80%; text-align: center">
<h1 style="color: red; font-weight: 900; filter: drop-shadow(0 0 2px red); font-size: 24pt; margin: 0;">EMERGENCY</h1>
<p style="color: orange;filter: drop-shadow(0 0 2px orange);">bla bla stuff is happening i have finished the show but not eoe</p>
<svg version="1.1"
viewBox="0 0 300 100"
style="display: block; height: 2cm; margin-inline: auto; margin-top: 1.5rem;"
xmlns="http://www.w3.org/2000/svg">
<style>
.ok {
filter: drop-shadow(0 0 3px orange);
fill: orange;
}
.bad {
filter: drop-shadow(0 0 3px #fb1515);
fill: #fb1515;
}
.meh {
filter: drop-shadow(0 0 3px #e35c1a);
fill: #e35c1a;
}
</style>
<defs>
<svg id="box" viewBox="0 0 300 100">
<path d="M 0,0 h 275 l 25,25 v 75 h -275 l -25,-25 Z" />
<text x="0" y="0">yo</text>
</svg>
</defs>
<use href="#box" class="ok" width="90" height="30" x="3" y="3" />
<use href="#box" class="ok" width="90" height="30" x="3" y="36"/>
<use href="#box" class="ok" width="90" height="30" x="3" y="69"/>
<use href="#box" class="meh" width="90" height="30" x="95" y="3" />
<use href="#box" class="meh" width="90" height="30" x="95" y="36"/>
<use href="#box" class="ok" width="90" height="30" x="95" y="69"/>
<use href="#box" class="bad" width="90" height="30" x="188" y="3" />
<use href="#box" class="bad" width="90" height="30" x="188" y="36"/>
<use href="#box" class="meh" width="90" height="30" x="188" y="69"/>
</svg>
</div>
</div>
</article>
<article id="s14">
<h1><a href="#s14">#</a> fake book covers</h1>
<p><a href="https://eggbugstestplace.jcink.net/index.php?showtopic=74">chorum thread</a>, i have an idea</p>
<div id="s14-book-1">
<h1>Suturing Spectra</h1>
<h2>Case Studies in Chromatic Containment</h2>
<div class="strip"></div>
<p>Stanton Parker</p>
<p class=series>Practical Anomalous Physics: Volume One</p>
</div>
<p>The original SCP logo was designed by far2, based on <a href="https://youtube.com/watch?v=AEbUZomoBpk">a free asset</a> from <a href="https://en.wikipedia.org/wiki/Adobe_Illustrator">Adobe Illustrator</a>'s "Mad Science" asset library, which in turn was based on the <a href="https://en.wikipedia.org/wiki/File:ESD-warning-symbol.svg">electrostatic discharge warning symbol</a>. The first high-resolution PNG version of the logo was made by Aelanna, based on the original SCP logo. <a href="https://commons.wikimedia.org/wiki/File:SCP_Foundation_(emblem).svg">SCP Foundation (emblem)</a>, <a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode" rel="license">CC BY-SA 3.0</a>
<style>
#s14-book-1 {
width: 6cm;
height: 7.8cm;
background: url(https://upload.wikimedia.org/wikipedia/commons/e/ec/SCP_Foundation_%28emblem%29.svg) #fffefd;
background-size: 10cm;
background-position: 2cm -0.3cm;
background-repeat: no-repeat;
color: #2c2c2c;
//padding: 0.5cm 1cm;
font-family: "Charter", charter, serif;
outline: 0.2cm solid black;
filter: blur(0.25px);
}
/*
#s14-book-1::before {
backdrop-filter: blur(10px);
content: "";
display: block;
position: relative;
inset: 0;
}
*/
#s14-book-1 > h1 {
font-size: 18pt;
width: 7cm;
margin-left: 0.4cm;
padding-top: 0.4cm;
margin-bottom: 0;
}
#s14-book-1 > h2 {
font-size: 13pt;
font-variant: italic;
margin-left: 0.4cm;
width: 4cm;
margin-top: 0.4cm;
margin-bottom: 0.3cm;
}
#s14-book-1 > .strip {
height: 1cm;
background: linear-gradient(to right in hsl, #f00, #0f0, #000, #0ff, #00f, #f0f);
}
#s14-book-1 > p {
margin-left: 0.4cm;
width: 2.5cm;
font-size: 10pt;
margin-top: 0.3cm;
}
#s14-book-1 > .series {
font-style: italic;
width: 2cm;
}
</style>
</article>
<article id="s13">
<h1><a href="#s13">#</a> can i embed a godot game?</h1>
<details><summary>of course</summary>
<iframe src="https://terezi.pyrope.net/s13" width=300 height=300 title="basic asteroid game"></iframe>
</article>
<article id="s12">
<h1><a href="#s12">#</a> sπgot</h1>
<h2>hey, that's almost a spout!</h2>
<p>here's a π spigot from <a href="https://www.gavalas.dev/blog/spigot-algorithms-for-pi-in-python/">this blog post</a>.
a while ago, i implemented one of the algorithms here in scheme. it was fun to get a megabyte of π, and i want you to be able to have a similar experience <span class=emoticon>:D</span>.
this version is unproven, <a href="https://www.gavalas.dev/blog/spigot-algorithms-for-pi-in-python/#the-open-problem">as discussed in the original article</a>, buuuut <abbr title="i don't really care">idrc</abbr>.
fair warning: especially with larger batch sizes, this is liable to freeze up the tab. tread carefully!
</p>
<pre id=s12-output style="overflow: auto; height: 36ch; width: 100%; word-break: break-all; white-space: pre-wrap;">
3.</pre>
<button onclick='
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
this.innerText = "sπgot!";
return;
}
this.innerText = "sτop!";
function* gen() {
let [q, r, t, i] = [1n, 180n, 60n, 2n];
while (true) {
let u = 3n*(3n*i+1n)*(3n*i+2n);
let y = (q*(27n*i-12n)+5n*r)/(5n*t);
yield y;
[q, r, t, i] = [10n*q*i*(2n*i-1n), 10n*u*(q*(5n*i-2n)+r-y*t), t*u, i+1n];
}
}
let [output, digits, batch, error] = elems(12, "output digits batch error");
let g = gen();
g.next();
this.interval = setInterval(() => {
let n = +batch.value;
let str = "";
let digs = +digits.innerText;
try {
for (let i = 0; i < n; i++) {
str += g.next().value;
digs++;
}
} catch (e) {
clearInterval(this.interval);
this.interval = null;
this.innerText = "error :[";
error.innerText = e.toString();
} finally {
output.innerText += str;
digits.innerText = digs;
}
}, 0);
'>sπgot!</button> <span id=s12-digits style="font-family: monospace">1</span> digits in batches of <input id=s12-batch type=number min=1 max=100000 value=10></input> <p style="color: red" id=s12-error></span>
<p>gotta say, it's really sweet working with native generators. not really necessary here, but elegant.
bigints were the real hero, i almost discarded the idea before i remembered js had them <span class=emoticon>:P</span>
<p>at around 2<sup>15</sup> digits, the bigints become too big to allocate, at least on my machine. lame!
</article>
<article id="s11">
<h1><a href="#s11">#</a> emanresu A π approximation</h1>
<p>this is a geminic sequel to <a href="#s10">s10</a>, which does exist yet!
<p>this technique is taken from <a href="https://codegolf.stackexchange.com/questions/275564/count-squares-in-my-pi-approximation">this code golf question</a>.
i hope i can do it!
<canvas id="s11-canvas" width=300 height=300></canvas><br>
<input type=range id="s11-slider" min=0 max=12 value=0 onchange='
let [canvas, slider, best] = elems(11, "canvas slider best");
let ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, 4113, 4113);
let steps = +slider.value;
let c = (x, y) => x*x + y*y <= 1;
let inside = 0;
// why do all of the steps if we do not save work
// for colors, fool!
for (let i = steps; i >= 1; i--) {
let side_len = 2**-i;
let square_size = side_len**2;
ctx.fillStyle = `hsl(${i.map(8, 1, 0, 360)}deg, 70%, 50%)`
for (let x = 0; x < 1; x += side_len) {
for (let y = 0; y < 1; y += side_len) {
if (c(x + side_len, y)) {
ctx.fillRect(x.map(0, 1, 0, 300), y.map(0, 1, 300, 0), 300/(2**i), 300/(2**i));
if (i == steps) inside += square_size;
}
}
}
}
best.innerText = inside * 4;
'/> best guess: <span id="s11-best">idk</span>
<p>i did it! not super efficiently, but it was fun. the slider goes up to 12, which is <em>really</em> pushing it, so exercise caution
</article>
<article id="s10">
<h1><a href="#s10">#</a> Monte Carlo π approximation</h1>
<p>this is a prequel to <a href="#s11">s11</a>, which does exist yet!
<p>a while ago, i made <a href="https://cohost.org/mehbark/post/5961356-mehbark-s-mini-progr">this cohost post</a> about approximating π,
and i'd like to implement my favorite approach here</p>
<canvas id="s10-canvas" width=314 height=314></canvas><br>
<input id="s10-samples" type="number" min=1 value=1000> in batches of <input id="s10-batch" type="number" min=1 value=10> <button onclick='
let [canvas, samples, inside, total, best, batch] = elems(10, "canvas samples inside total best batch");
let n = +samples.value;
let b = +batch.value;
let [ins, tot] = [+inside.innerText, +total.innerText];
if (!(n > 0)) {
alert(`come on, ${n} samples?`);
return;
}
let ctx = canvas.getContext("2d");
setTimeout(function sample() {
for (let i = 0; i < b; i++) {
let x = Math.random();
let y = Math.random();
let win = x*x + y*y <= 1;
ctx.fillStyle = win ? "#76a6e4" : "#ede";
ctx.fillRect(x.map(0, 1, 0, 300), y.map(0, 1, 300, 0), 1, 1);
if (win) ins++;
tot++;
if (!n--) break;
}
inside.innerText = ins;
total.innerText = tot;
best.innerText = 4 * ins/tot;
if (n > 0) setTimeout(sample, 0);
}, 0);
'>sample!</button><br>
<p>current best guess: <span id="s10-inside">0</span>/<span id="s10-total">0</span> * 4 = <span id="s10-best">idk</span>
<p>this is thoroughly ingrained in my brain, but i hope it's still fairly intuitive for others.
i like how the boundary becomes more clear with more samples, it makes the accuracy more understandable <abbr title="in my opinion">imo</abbr>
</article>
<article id="s9">
<h1><a href="#s9">#</a> apropos of <a href="#s7">s7</a></h1>
<p>i may not be stupid!
<p>the technique as applied in <a href="#s6">s6</a> may be pointless, but, for a general equality, points that can move in two directions could actually be interesting!
that might be here! in ! th efuture</p>
<canvas id="s9-canvas" width=300 height=300></canvas><br>
<input id="s9-lhs" value="x*x + y*y"> = <input id="s9-rhs" value="1"> <button onclick='
if (this.innerText == "stop D:") {
clearInterval(this.interval);
this.innerText = "graph!";
return;
}
this.innerText = "stop D:";
let [lhs, rhs, canvas, samples] = elems(9, "lhs rhs canvas samples");
let ctx = canvas.getContext("2d");
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let f = eval(`(x, y) => {with (Math) {return abs((${lhs.value}) - (${rhs.value}))}}`);
let guys = [];
for (let x = x0; x <= x1; x += (x1 - x0)/samples.value) {
for (let y = y0; y <= y1; y += (y1 - y0)/samples.value) {
guys.push({x, y, last: 100, r: Math.random()/10, t: Math.random()*6.28});
}
}
let step = () => {
for (let guy of guys) {
let diff = f(guy.x, guy.y);
if (guy.r < 0.01) guy.r = 0.01;
if (diff > guy.last) {
guy.r *= 0.5;
guy.t += Math.random()/10;
} else {
guy.last = diff;
guy.x += guy.r*Math.cos(guy.t);
guy.y += guy.r*Math.sin(guy.t);
guy.r *= 1.1;
}
if (diff > 0.1 && Math.random() > 0.1) guy.last = diff;
}
};
let draw = () => {
ctx.fillStyle = "#76a6e4";
ctx.clearRect(0, 0, 1000, 1000);
for (let {x, y, t} of guys) {
ctx.fillStyle = `hsl(${t/6.28}turn 100% 60%)`;
ctx.fillRect(x.map(x0, x1, 0, 300), y.map(y0, y1, 300, 0), 1, 1);
}
};
draw();
// the stop button works now, so why limit steps?
let steps = 1/0;
this.interval = setInterval(function loop() {step(); draw(); if (steps-- <= 0) clearInterval(this.interval)}, 0)
'>graph!</button> <input type=number id=s9-samples value=100></input> samples<sup>2</sup>
<p>okay dang this looks freaking great. hue is based on angle, look at the code! i love this
<p>i have decided that instead of making it more accurate, i will leave it at this place of looking very cool
</article>
<article id="s8">
<h1><a href="#s8">#</a> s(oko)8(an)</h1>
<p>i never got anywhere with width-hacking on cohost, but can i implement a normal game in programming language‽
<p><abbr title="work in progress">WIP</abbr>! functional! really needs undo though!</p>
<p>see <a href="http://www.sokobano.de/wiki/index.php?title=Level_format">here</a> if you want to know the #lingo</p>
<textarea id="s8-input" rows=20 style="width: 100%; padding: 0; resize: vertical">
# #
# # #
# # #
# # #
# # #
# # #
# # #
##########
#........####
# $$$$$$$# #
#.$......# #
# $$$$$$ # #
#......$+# #
#$$$$$$$ # #
# ####
##########
"Steaming Hot" by David Buchweitz</textarea>
<div class="controls"><button id="s8-l"></button><button id="s8-u"></button><button id="s8-d"></button><button id="s8-r"></button></div>
<div>winning? <span id="s8-winning">no.</span> moves? <span id="s8-moves"></span></div>
<script>
let [input, l, u, d, r, winning, moves] = elems(8, "input l u d r winning moves");
let step = (dx, dy, c) => () => {
let puzzle = input.value.split("\n");
let max_width = puzzle.reduce((m, s) => Math.max(m, s.length), 0);
puzzle = puzzle.map(s => s.padEnd(max_width).split(""));
let in_bounds = (x, y) => 0 <= x && x < max_width && 0 <= y && y < puzzle.length;
let at = (x, y) => {
let c = in_bounds(x, y) ? puzzle[y][x] : "#";
let out = {wall: false, player: false, goal: false, box: false, c, x, y};
switch (c) {
case "*":
out.goal = true;
case "$":
out.box = true;
break;
case "+":
out.goal = true;
case "@":
out.player = true;
break;
case "#":
out.wall = true;
break;
case ".":
out.goal = true;
break;
}
return out;
};
let open = sq => !sq.wall && !sq.box;
let set = (x, y, c) => puzzle[y][x] = c;
let px, py;
for (let y = 0; y < puzzle.length; y++) {
for (let x = 0; x < max_width; x++) {
if (!at(x, y).player) continue;
px = x;
py = y;
}
}
if (typeof px == "undefined") {
winning.innerText = "THERE ISN'T A PLAYER DOOFUS";
return;
}
let [p, m] = [at(px, py), at(px + dx, py + dy)];
if (open(m)) {
set(px, py, p.goal ? "." : " ");
set(m.x, m.y, m.goal ? "+" : "@");
moves.innerText += c;
} else if (m.box) {
let m2 = at(px + 2*dx, py + 2*dy);
if (open(m2)) {
moves.innerText += c;
set(px, py, p.goal ? "." : " ");
set(m.x, m.y, m.goal ? "+" : "@");
set(m2.x, m2.y, m2.goal ? "*" : "$");
}
}
input.value = puzzle.map(r => r.join("")).join("\n");
let won = !puzzle.join().includes("$");
winning.innerText = won ? "yes!" : "no.";
};
l.onclick = step(-1, 0, "l");
u.onclick = step( 0, -1, "u");
d.onclick = step( 0, 1, "d");
r.onclick = step( 1, 0, "r");
</script>
</article>
<article id="s7">
<h1><a href="#s7">#</a> i may be stupid</h1>
<p>i realized something when talking about <a href="#s7">s7</a>: i may be stupid.
first of all, it's worth understanding that <a href="#s7">s7</a> is actually my third go at this technique,
the first time was on <code>about:blank</code> in canvas, and the second time was in <a href="https://www.lexaloffle.com/picotron.php">picotron</a>.</p>
<canvas id="s7-canvas" width=300 height=300></canvas><br>
<input id="s7-input" value="sin(x)"> <button id="s7-graph" onclick='
let ctx = document.getElementById("s7-canvas").getContext("2d");
ctx.fillStyle = "#76a6e4";
let f = eval(`x => {with (Math) {return ${document.getElementById("s7-input").value}}}`);
let deriv = f => x => (f(x + 1e-6) - f(x))/1e-6;
let order = +document.getElementById("s7-deriv").innerText;
for (let i = 0; i < order; i++) f = deriv(f);
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
ctx.clearRect(0, 0, 1000, 1000);
for (let x = x0; x <= x1; x += (x1 - x0)/1200) {
ctx.fillRect(x.map(x0, x1, 0, 300), f(x).map(y0, y1, 300, 0), 1, 1);
};
'>graph!</button> <button id="s7-deriv" onclick='
this.innerText++;
let n = +this.innerText;
document.getElementById("s7-th").innerText = n > 10 && n < 20 ? "th" : ["th", "st", "nd", "rd", ...Array(6).fill("th")][n%10];
document.getElementById("s7-graph").click();
'>0</button><span id="s7-th">th</span> derivative
<p>i just have to graph the function! the other method just looks cooler and is less reliable
<p>here's the important part of the code: <code>ctx.fillRect(x.map(x0, x1, 0, 300), f(x).map(y0, y1, 300, 0), 1, 1)</code>
<p>i also added approximated derivatives for fun <span class=emoticon>:D</span>
</article>
<article id="s6">
<h1><a href="#s6">#</a> a very fun approach to graphing</h1>
<p>now, this is hardly “production-grade,” but it is fun. first play, then talk.</p>
<canvas id="s6-canvas" width=300 height=300></canvas><br>
<input id="s6-input" value="sin(x)" onkeyup='
let ctx = document.getElementById("s6-canvas").getContext("2d");
ctx.fillStyle = "#76a6e4";
let f = eval(`(x, y) => {with (Math) {return y - (${this.value})}}`);
let [x0,x1,y0,y1] = [-Math.PI, Math.PI, -Math.PI, Math.PI];
let guys = [];
for (let x = x0; x <= x1; x += (x1 - x0)/600) {
guys.push({x, y: 0, dy: 0.1, lastDiff: 1});
};
let draw = () => {
ctx.clearRect(0, 0, 1000, 1000);
for (let guy of guys) {
ctx.fillRect(guy.x.map(x0, x1, 0, 300), guy.y.map(y0, y1, 0, 300), 1, 1);
}
};
let step = () => {
for (let guy of guys) {
let diff = Math.abs(f(guy.x, guy.y + guy.dy));
if (Math.abs(guy.dy) < 0.005) guy.dy = 0.01 * (Math.random() - 0.5);
if (diff > guy.lastDiff) {
guy.dy = -guy.dy/1.5;
} else {
guy.y += guy.dy;
guy.dy = guy.dy * 2;
guy.lastDiff = diff;
}
}
}
let total_diff = () => guys.reduce((sum, g) => sum + g.lastDiff, 0);
let delay = 100;
draw();
setTimeout(function frame() {
step();
draw();
console.log(total_diff());
if (total_diff() > 1) window.setTimeout(frame, delay);
}, delay);
'>
<p>now this is a very janky demo for many, many reasons, but there's a kernel of an idea here that's very cool: moving a bunch of things independently to do a big thing.
<p>some ideas to make this suck less:
<ul>
<li>fix the horrendous onchange behavior to actually stop the previous attempt
<li>use <a href="https://en.wikipedia.org/wiki/Newton%27s_method">Newton's method</a> with an approximated derivative
<li>tweak parameters
</ul>
<p>now look at the code!
</article>
<article id="s5">
<h1><a href="#s5">#</a> why spout</h1>
<p>i have <a href="https://b.pyrope.net">my blog</a> for when i want to make really legit-looking posts.
it's made with <a href="https://docs.racket-lang.org/pollen/">pollen</a>, which is great, and i can make even the most lame posts (currently all of the posts) look very nice.
however, there's a whole build system, the book is a program after all, a lot of things have to happen to make a post there happen. so i wanted something smaller. micro, if you will.
hence, spout! i just write some html (which, tbh, i kinda prefer to markdown) with no restrictions. ssh, edit file, save file, done. it's great! it <em>really</em> needs an RSS feed, though…
</article>
<article id="s4">
<h1><a href="#s4">#</a> oh i'm totally going to</h1>
<canvas width=20 height=20 style="outline: 1px solid var(--fg)"></canvas>
<button onclick="
let ctx = document.querySelector('#s4 > canvas').getContext('2d');
ctx.fillStyle = `rgb(${Math.random()*256}, ${Math.random()*256}, ${Math.random()*256})`;
ctx.fillRect(Math.floor(Math.random()*20), Math.floor(Math.random()*20), 1, 1);
">pixel it</button>
</article>
<article id="s3">
<h1><a href="#s3">#</a> this is, obviously, just an html page</h1>
<p>i can do <span style="color: transparent; background-clip: text; background: linear-gradient(to right, #008282, #005682); -webkit-background-clip: text;">whatever</span> i want!
heck, i could even put <button onclick="this.innerText++; document.getElementById('s3-s').innerText = 's';">1</button> javascript<span id="s3-s"></span>
</article>
<article id="s2">
<h1><a href="#s2">#</a> hello, again</h1>
<p>this is the second
<p>also easy to write!
<p>note the # links
</article>
<article id="s1">
<h1><a href="#s1">#</a> hello, spout</h1>
<p>this is the first spout post
<p>it is easy to write
<p>that is important!
</article>
<p>Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License.</p>
<p>i hope that's sufficient? you can use my stuff</p>
<!-- woo spooky secret
<article id="s0">
<h1><a href="#s0">#</a> title</h1>
</article>
-->
</body>

View file

@ -2,6 +2,7 @@
title: What is twopn? title: What is twopn?
description: How I made a new website without exploding description: How I made a new website without exploding
tags: post,short,meta tags: post,short,meta
date: 2026-01-24 18:00:00
--- ---
twopn is new website and stuff [lisannne](https://lisanne.gay) and [poly wolf](https://wolfgirl.dev/blog) twopn is new website and stuff [lisannne](https://lisanne.gay) and [poly wolf](https://wolfgirl.dev/blog)