Skip to content

Instantly share code, notes, and snippets.

@meltingice
Last active August 9, 2023 16:07
Show Gist options
  • Save meltingice/1365c9a469a877b05121d81b0cc4d446 to your computer and use it in GitHub Desktop.
Save meltingice/1365c9a469a877b05121d81b0cc4d446 to your computer and use it in GitHub Desktop.
Grail #14
// Utility function for shuffling an array
const shuffle = a => a.sort(() => Math.random() - 0.5)
// The current day of the week (0 = Sunday, 1 = Monday, etc.)
const cId = new Date().getDay()
// The set of symbols used for each day of the week
const cs = [
['๐Ÿ”ณ', '๐ŸŸฆ', '๐Ÿ”ฒ', '๐ŸŸฅ'], // Sunday
['โฌ›๏ธ', '๐Ÿ•น', '๐Ÿ’ฟ', '๐Ÿท'], // Monday
['ใ€ฐ๏ธ', '๐ŸŒ€', 'โญ•๏ธ', '๐Ÿ’ค'], // Tuesday
['๐Ÿ”—', '๐Ÿ•', '๐Ÿœ', '๐ŸŽ'], // Wednesday
['โฌœ๏ธ', '๐Ÿ˜ƒ', '๐Ÿฏ', '๐Ÿ˜ญ'], // Thursday
['๐Ÿ“Ž', '๐Ÿคข', '๐Ÿ“', '๐Ÿคฎ'], // Friday
['๐Ÿซฅ', '๐Ÿ˜', '๐Ÿ˜˜', '๐Ÿฅฐ'], // Saturday
]
// The set of symbols used for today
const c = cs[cId]
// The set of possible x/y movements
const s = [[0, 1], [0, -1], [1, 0], [-1, 0]]
// Grid dimensions and snake length
const w = 54, h = 36, l = 24
// Initial position
let x = w/2, y = h/2
// The set of coordinates that comprise the snake
let p = [[x, y]]
// Array of indices into s
let d = [0, 1, 2, 3]
// Our update function that renders a new iteration of the snake
const update = () => {
// The x/y movement we will perform
let a = [0, 0]
// Shuffle the possible movements randomly (roughly 1/3 of the updates)
if (Math.random() < 0.318) d = shuffle(d)
// For each possible movement
for (let i = 0; i < d.length; i++) {
// The next x/y positions
let tx = x + s[d[i]][0]
let ty = y + s[d[i]][1]
// Flag for whether the next x/y position is already occupied
let u = 0
// For each piece of the snake...
for (let j = 0; j < p.length; j++) {
// If the next x/y position is already occupied, set the flag
if (p[j][0] == tx && p[j][1] == ty) u = 1
}
// If the next x/y position is not already occupied, set the next movement
if (!u) a = s[d[i]]
}
// Perform the movement. If u = 1 then this will be [0, 0] and no movement will occur
x += a[0]
y += a[1]
// Wrap around the grid in all directions
if (x < 0) x = w-1
if (x >= w) x = 0
if (y < 0) y = h-1
if (y >= h) y = 0
// Add the new position to the snake
p.push([x, y])
// If the snake has reached its max length, remove the last position
if (p.length > l) p.shift()
// The output string
let o = ''
// For each y position in the grid...
for (let j = 0; j < h; j++) {
// For each x position in the grid...
for (let i = 0; i < w; i++) {
// If the current x/y position is the snake's head...
if (x == i && y == j) {
// If there is no movement in this update, then output the last emoji
// in the list, otherwise output the 2nd emoji.
o += a[0] == 0 && a[1] == 0 ? c[3] : c[1]
} else {
// Check if the current x/y position is part of the snake (but not the head)
let f = p.find(e => e[0] == i && e[1] == j)
// If it is, then output the 3rd emoji, otherwise output the 1st emoji
o += f ? c[2] : c[0]
}
}
// Add a newline after each row to create the grid
o += '\n'
}
// Output the grid to the console
console.log(o)
// Update the page title with the current order of the 4 emojis for today
document.title = `${c[d[0]]}${c[d[1]]}${c[d[2]]}${c[d[3]]}`
}
// Write today's snake emoji's to the page
document.getElementById('s').innerText = `${c[1]}${c[2]}`
// Create a favicon with today's snake emoji's
var link = document.querySelector("link[rel*='icon']") || document.createElement('link');
link.rel = 'icon'
link.href = `data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>${c[1]}</text></svg>`
document.getElementsByTagName('head')[0].appendChild(link)
// Update the snake every 40ms
setInterval(update, 40)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment