waldo#
Right-click a message -> Apps -> waldo
Waldo is a hide-and-seek game played on pictures. You point it at an image, Eimi hides a tiny camouflaged bee somewhere inside it, and posts the result to the channel with your name on it. Everyone else has to find the bee.
Nothing about it is generated. The bee is a small sprite composited into the real picture, so the image is otherwise untouched -- same resolution, same content, one extra insect.
Starting a round#
- Right-click any message with an image, Apps -> waldo (long-press on mobile).
- Eimi checks your bot access, then checks that the message has an image, then checks your cooldown. All three happen before the menu opens, so you never get handed a menu you cannot act on.
- A private menu appears: ### 🐝 Hide a bee in this image, gold accent. Anyone else clicking it gets "This isn't your waldo menu." It expires after 180 seconds.
- If the message has several images, pick one from the "Pick which image to hide the bee in" dropdown. With exactly one image the dropdown is skipped.
- Click a difficulty. That submits immediately -- there is no confirm step. The whole menu greys out, the button you clicked swaps to a spinner, and the menu deletes itself once the job finishes.
There is also a 🚫 Cancel button, which just closes the menu.
Hiding takes 1 to 3 seconds, longer on a very large image. The result posts as a reply to the message you right-clicked.
Waldo never touches the GPU
The whole pipeline is plain Python image processing -- no model, no API call, nothing queued behind your generations. A waldo will run while the queue is backed up, and it will run while the GPU is off.
Videos and GIFs work
A video or GIF source has its first frame extracted and the bee goes into that. See what counts as an image for everything the picker will find, including stickers, embeds and Eimi's own result cards.
What the bot actually does to the image#
Understanding the pipeline makes the game easier to play, and easier to lose fairly.
- It measures how busy every part of the picture is. A downscaled copy (1024 px on the long edge) is run through an edge filter and blurred, which produces a "visual clutter" score from 0 to 1 for every region. Flat sky scores near 0. Mid texture is around 0.10. Dense foliage or line-art detail is around 0.25. Sharp high-contrast edges are 0.35 and up.
- It masks off the border. The outer 6% of the image on every side is excluded, so nobody wins by checking the four corners first.
- It picks a spot. Each difficulty targets a specific clutter score, with a bell curve of tolerance around it. The bee lands in a region whose busyness is near that target -- not necessarily the busiest part of the picture, the part that matches. Because the pick is weighted rather than fixed, the same image at the same difficulty gives a different spot each time.
- It picks a bee. One sprite at random from the library of bumblebee cutouts on disk (512 of them at the moment), scaled to the size the difficulty asks for.
- It camouflages the bee. Every pixel of the sprite is blended toward the background pixel directly underneath it. This breaks up the silhouette: a bee straddling a yellow flower and a green leaf gets its flower half pulled toward yellow and its leaf half pulled toward green, rather than the whole thing turning one averaged colour. Where the background is near-neutral (grey, white, black) the tint is damped down to about a sixth of its nominal strength, so the bee does not wash out into a pale smudge.
- It makes the bee slightly transparent. Each difficulty drops the sprite's opacity a little. This does most of the camouflage work; the tint is kept conservative on purpose because heavy tinting used to erase bees entirely.
- It softens the edge. A sub-pixel blur (0.3 to 1.2 px, scaling with sprite size) is applied to the sprite's alpha channel only. The body stays solid and recognisable, but the outline fades into the surrounding texture instead of reading as a sticker pasted on top.
- It composites and saves. The sprite goes onto the full-resolution original, centred on the chosen coordinates, and the result is written out as a PNG.
Difficulties#
Four buttons, one row, click to submit.
| Button | Bee size | Size clamp | Tint | Opacity | Clutter target | Tolerance |
|---|---|---|---|---|---|---|
| 🟢 Easy | 3.5% of the shorter edge | 10-160 px | 0.22 | 96% | 0.12 | 0.025 |
| 🔵 Medium | 2.2% | 8-130 px | 0.43 | 91% | 0.18 | 0.030 |
| 🟠 Hard | 1.2% | 4-70 px | 0.59 | 84% | 0.26 | 0.035 |
| 🔴 Nightmare | 0.9% | 3-50 px | 0.69 | 78% | 0.36 | 0.040 |
In plain terms: harder means a smaller bee, tinted more heavily toward the colours around it, more see-through, and dropped into a more visually cluttered part of the picture. All four dials move together.
What each column means:
| Column | What it does to the game |
|---|---|
| Bee size | Sprite size as a percentage of the image's shorter edge, so the bee stays proportional across a phone screenshot and a 4K render |
| Size clamp | Hard floor and ceiling in pixels. The floor stops a percentage vanishing on a small image; the ceiling stops it becoming a billboard on a huge one. A last-resort clamp of 4-240 px catches nonsense values |
| Tint | How far each bee pixel is pulled toward the background pixel under it. 0 is no camouflage, 1 would be full replacement on a saturated background |
| Opacity | How solid the bee is. Lower lets more background bleed through the body |
| Clutter target | Which busyness level the placement aims for, on the 0-1 scale described above |
| Tolerance | How far from that target the pick is allowed to wander. Tighter values keep it honest on pictures with two very different regions, like a lighthouse against flat sky and dense grass |
These are the built-in defaults, and they can be retuned
None of these values are set in the bot's config file, so the built-in defaults above are what is actually running. Whoever runs your instance can override any of them live from the admin panel without a restart, so a server that has been tuned may not match this table.
Edge cases#
- A flat single-colour image. There is nowhere busy to hide, so the bee goes somewhere random and off-centre and the tint is held down to at most 0.10 -- camouflage against a uniform colour is pointless and just makes the bee ugly.
- A pure-noise image. Everything is equally busy, so the bell curve flattens and any position is as good as any other.
- A picture with nothing near the target. Nightmare aims at 0.36, and plenty of soft paintings never get above 0.17. The placement quietly degrades to the closest available spot rather than failing.
Nightmare is genuinely unfair on small images
Sprite size scales with the shorter edge and bottoms out at 3 px at nightmare. On a 400 px picture that is a speck that nobody will ever find, and it stops being a game. Save nightmare for large, detailed pictures with somewhere interesting to hide.
The result card#
🐝 @user hid a bee in this image
difficulty: hard
revealed by @alice, @bob
[the image]
[🔍 Reveal] [📤 or 🗑️]
A frameless card -- no accent border, matching the shape of a normal result card. The header names you as the hider and states the difficulty, so nobody has to guess whether they are looking for a 3 px speck or a comfortable blob. The "revealed by" line only exists once someone has clicked 🔍.
| Button | Who can use it | What it does |
|---|---|---|
| 🔍 Reveal | Anyone with bot access | Sends you a private copy with a glowing box drawn around the bee, and adds your name to the public list |
| 📤 | You, or an admin | Only on private results. Reposts the waldo publicly in the channel |
| 🗑️ | You, an admin, or your server's delegated owner | Only on public results. Deletes the message |
Whether a waldo lands publicly or only for you is decided the same way as every other Eimi output -- see Delivery. If it came out private, 📤 promotes it to a real channel post that other people can play. The public copy starts with an empty "revealed by" list, even if you had already revealed the private one.
Waldos are written into your job history with the prompt "Hide a bee in this image", so they show up in /history alongside your generations.
Revealing#
🔍 Reveal is open to anyone with bot access, not just the person who hid the bee. That is the point -- it is how you claim you found it, and how you check whether you were right.
Clicking it:
- Shows a spinner on the public card while it works, then restores the button so it can be clicked again.
- Downloads the bee'd image back from Discord, draws the overlay, and sends it to you only with the message "🔍 the bee was at (x, y)".
- Edits the public card to append your mention to the "revealed by" line.
The split is deliberate. You see exactly where the bee is. The channel only sees that somebody found it, never where, so everyone else can keep hunting. Repeat clicks by the same person do not add duplicate names. The public line shows the first 25 revealers.
The overlay#
A box drawn around the bee in three layers: an outward-only blurred glow halo, a crisp coloured outline, and a thin white pinstripe just inside it. The glow is explicitly cleared out of the box interior so it never washes out the bee you are trying to look at.
The box is drawn fresh on every click, in a colour picked at random from a seven-colour rainbow palette, so two reveals of the same waldo look different. Its border sits well clear of the bee -- 12 px or 75% of the sprite size, whichever is larger -- so you can see the bee in context rather than crushed against the frame.
Reveals survive restarts#
The card is persistent. Its buttons are wired by ID rather than by anything held in memory, and the bee's coordinates are stored in the database against the message, so 🔍 keeps working after the bot restarts. An old waldo stays playable for as long as the message and its image exist. The "revealed by" list accumulates across restarts too, rather than resetting each session.
Two things can still break an old waldo:
- Discord expires image links eventually. A waldo whose picture no longer loads cannot be revealed -- you get "Couldn't download bee'd image (HTTP 404)."
- Waldos posted before the current version were never given reveal data. Those answer "No reveal data for this message (probably from before the waldo revamp)."
Limits#
| Limit | Value |
|---|---|
| Minimum image size | 128 px on both sides |
| Maximum attachment size | 25 MB |
| Menu timeout | 180 seconds |
| Cooldown between waldos | 5 seconds per person |
| Waldos compositing at once, globally | 10 |
| Waldos compositing at once, per person | 2 |
| Button click cooldown | 0.5 seconds |
Minimum size is a hard rejection, not a warning: an image under 128 px on either axis has nowhere to hide anything. You get "❌ Couldn't hide a bee: image is too small to hide a bee in: {W}x{H} (need at least 128 px on each side)".
The 25 MB check only applies to plain Discord attachments -- an embedded image from another site is not measured before download.
The cooldown is checked twice: once before the menu opens, and once again when you click a difficulty. It is stamped the moment a job is accepted rather than when it finishes, so double-tapping cannot sneak two jobs through. Too soon and you get "🐝 you're posting waldos too fast -- try again in {N}s". Admin and VIP users skip the cooldown entirely; the concurrency caps still apply to them.
The concurrency caps exist because this is one machine in somebody's house. Ten simultaneous composites is already enough to make the CPU noticeable. Hitting a cap does not fail the job, it just waits its turn.
All of these can be changed live by whoever runs your instance, from the admin panel, without restarting the bot.
Nothing about an in-flight waldo is saved. If the bot restarts mid-job, the interaction expires and you re-trigger it -- there is nothing to recover in a job that takes two seconds.
Other messages you might see#
| Message | What happened |
|---|---|
| "❌ No image found in that message." | Nothing usable in the message you right-clicked |
| "❌ Waldo system not available." | The runner did not load at startup. Not something you can fix; tell the maintainer |
| "❌ Failed to download image." | Discord's link for the source image did not resolve |
| "❌ Waldo finished but I couldn't post the result" | The bee was hidden, but posting the message failed |
| "❌ Waldo finished but the result didn't post -- Discord probably choked. Try again." | Same, after retries were exhausted |
| "This isn't your waldo menu." | Someone else's picker |
| "You can only post your own waldos." | 📤 on a waldo you did not hide |
| "Bee'd image reference is missing, can't draw reveal." | The card lost track of its own image |
See also#
- Right-click menus -- the other four
- /history -- waldos appear here too
- tweak -- edit an image instead of hiding things in it