Something went wrong. Try again.
a tiny pet with a GPT-2 brain, living in your browser
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153// Pixel art: an 8x8 icon set and small primitives shared by the LCD scene// and the DOM (buttons, diary stickers, gift shelf).
export const C = { lcd: "#cfdcc9", lcdDark: "#2b3833", lcdNight: "#26302d", lcdShade: "#b9cbb5", ink: "#1f2a27", mid: "#7f9a91", white: "#f6f2e9", pink: "#ec9fae", red: "#d9636f", green: "#79ad74", dgreen: "#4f8352", yellow: "#efc75e", orange: "#e8894d", brown: "#a3744f", blue: "#7ea8cf", lav: "#b7a3d9",};
const KEY: Record<string, string> = { "#": C.ink, o: C.mid, "+": C.white, p: C.pink, r: C.red, g: C.green, G: C.dgreen, y: C.yellow, O: C.orange, b: C.brown, u: C.blue, l: C.lav,};
const S = (rows: string) => rows.trim().split(/\s+/);
export const SPRITES: Record<string, string[]> = { strawberry: S(`...gg... ..gGgg.. .rrrrrr. rr+rrrrr rrrrr+rr .rr+rrr. ..rrrr.. ...rr...`), cookie: S(`..bbbb.. .bbbbbb. bb#bbbbb bbbbb#bb bb#bbbbb bbbb#bbb .bbbbbb. ..bbbb..`), "rice ball": S(`...oo... ..o++o.. .o++++o. .o++++o. o++++++o o+####+o o+####+o .o####o.`), carrot: S(`......g. ....g.g. ....OOg. ...OOO.. ..OOO... .OOO.... OOO..... O.......`), pudding: S(`...bb... ..bbbb.. ..yyyy.. .yyyyyy. .yyyyyy. yyyyyyyy oooooooo .oooooo.`), apple: S(`....b... ...bg... .rr.rr.. rrrrrrr. rr+rrrr. rrrrrrr. .rrrrr.. ..r.r...`), flower: S(`.pp..pp. pppppppp .ppyypp. pppyyppp .pppppp. pp.gg.pp ...gg... ..gggg..`), pebble: S(`........ ........ ...ooo.. ..oo+oo. .ooooooo .oooooo# ..####.. ........`), star: S(`...yy... ...yy... yyyyyyyy .yyyyyy. ..yyyy.. .yyyyyy. .yy..yy. y......y`), leaf: S(`......gg ....gggg ...ggggg ..ggg+gg .gg+ggg. .g+ggg.. .+gg.... +.......`), shell: S(`...pp... ..p+pp.. .pp+p+p. .p+pp+p. p+pp+pp+ pppppppp .pp..pp. ........`), heart: S(`........ .pp..pp. pppppppp pppppppp .pppppp. ..pppp.. ...pp... ........`), drawing: S(`+++++++. +uu++++# +u+u+p+# ++++ppp# +g+++p+# +gg++++# +++++++# .#######`), feather: S(`......u. .....uu. ....uuu. ...uu+.. ..uu+... .uu+.... .u+..... +.......`), cloud: S(`........ ...oo... ..o++o.. .o+++oo. o++++++o o++++++o .oooooo. ........`), moon: S(`...yyy.. ..yy.... .yy..... .yy..... .yy..... ..yy.... ...yyy.. ........`), sun: S(`y..y..y. .y.y.y.. ..yyy... yyyyyyy. ..yyy... .y.y.y.. y..y..y. ........`), frog: S(`.gg..gg. g+#gg+#g gggggggg gpggggpg gg####gg .gggggg. gg....gg ........`), rain: S(`...oo... ..o++o.. .o++++o. .oooooo. .u..u... ..u..u.. .u..u... ........`), music: S(`...###.. ...#.##. ...#..#. ...#.... .###.... ####.... .##..... ........`), cat: S(`o.....o. oo...oo. ooooooo. o#ooo#o. ooopooo. .ooooo.. ........ ........`), ghost: S(`..oooo.. .o++++o. o+#++#+o o++++++o o++pp++o o++++++o o+o++o+o .o.oo.o.`), sparkle: S(`...y.... ...y.... ..yyy... yyy+yyy. ..yyy... ...y.... ...y.... ........`), ball: S(`..####.. .#++++#. #+pp+++# #+pp+++# #++++uu# #+++uuu# .#++uu#. ..####..`), bubbles: S(`.oo..... o++o.oo. o++oo++o .oo.o++o .....oo. ..oo.... .o++o... ..oo....`), bulb: S(`..####.. .#yyyy#. #yy++yy# #yy+yyy# .#yyyy#. ..#oo#.. ..#oo#.. ...##...`), pill: S(`........ ...##... ..#pp#.. ..#pp#.. ..#++#.. ..#++#.. ...##... ........`), book: S(`.######. #ppppp+# #ppppp+# #pp#pp+# #ppppp+# #ppppp+# .######. ........`), poop: S(`....b... ...bb... ..bbbb.. ..b#b#.. .bbbbbb. bbbbbbbb ........ ........`), note: S(`..###... ..#.#... ..#..... ..#..... ###..... ###..... ........ ........`), zz: S(`####.... ..#..... .#...... ####.... ........ ........ ........ ........`), bang: S(`.##..... .##..... .##..... .##..... ........ .##..... ........ ........`), tear: S(`u. uu .u`), smallheart: S(`p.p ppp .p.`), crumb: S(`b. .b`),};
export const SPRITE_W = (name: string) => SPRITES[name][0].length;
export function drawSprite( ctx: CanvasRenderingContext2D, name: string, x: number, y: number, { color = null, flip = false }: { color?: string | null; flip?: boolean } = {},) { const rows = SPRITES[name]; if (!rows) return; for (let j = 0; j < rows.length; j++) { const row = rows[j]; for (let i = 0; i < row.length; i++) { const ch = row[flip ? row.length - 1 - i : i]; if (ch === ".") continue; ctx.fillStyle = color || KEY[ch] || C.ink; ctx.fillRect(Math.round(x) + i, Math.round(y) + j, 1, 1); } }}
const urlCache = new Map<string, string>();export function spriteURL(name: string, scale = 4) { const key = `${name}@${scale}`; if (urlCache.has(key)) return urlCache.get(key)!; const rows = SPRITES[name]; const c = document.createElement("canvas"); c.width = rows[0].length * scale; c.height = rows.length * scale; const ctx = c.getContext("2d")!; ctx.scale(scale, scale); drawSprite(ctx, name, 0, 0); const url = c.toDataURL(); urlCache.set(key, url); return url;}
// Tiny 3x5 pixel font for the LCD clock and score.const FONT: Record<string, string> = { 0: "###,#.#,#.#,#.#,###", 1: ".#.,##.,.#.,.#.,###", 2: "###,..#,###,#..,###", 3: "###,..#,.##,..#,###", 4: "#.#,#.#,###,..#,..#", 5: "###,#..,###,..#,###", 6: "###,#..,###,#.#,###", 7: "###,..#,.#.,.#.,.#.", 8: "###,#.#,###,#.#,###", 9: "###,#.#,###,..#,###", ":": "...,.#.,...,.#.,...", x: "...,#.#,.#.,#.#,...", "?": "###,..#,.##,...,.#.", "!": ".#.,.#.,.#.,...,.#.", " ": "...,...,...,...,...",};export function drawText( ctx: CanvasRenderingContext2D, text: string | number, x: number, y: number, color = C.ink,) { ctx.fillStyle = color; for (const ch of String(text)) { const g = FONT[ch]; if (g) g.split(",").forEach((row, j) => [...row].forEach((p, i) => { if (p === "#") ctx.fillRect(x + i, y + j, 1, 1); }), ); x += 4; }}