]> git.cworth.org Git - lmno.games/log
lmno.games
5 days agoAllow queueing up a claim while another claim is in progress
Carl Worth [Mon, 9 Mar 2026 15:36:20 +0000 (08:36 -0700)]
Allow queueing up a claim while another claim is in progress

Prior to this commit, when another player is claiming, the "Claim a
word" button would be deactivated. Now, instead, we allow this button
to be active, and it puts the player's claim request onto a queue so
that they will get their turn eventually.

6 days agoUse "spacer" tiles to get correct inter-word spacing for claimed words
Carl Worth [Mon, 9 Mar 2026 05:24:07 +0000 (22:24 -0700)]
Use "spacer" tiles to get correct inter-word spacing for claimed words

Previously, we had the code computing an expected gap between tiles,
(and setting it as the "column-gap" CSS attribute). But this proved
fragile. In practice, it's hard to predict exactly what a browser will
do, (particular with things like sub-pixel rendering, etc.), so it's
easy for a calculation like this to be off.

And we saw that in practice. Tiles in one row would be a pixel or two
off (hrozintonally) from tiles in the next row. Being so close, but
not quite exactly the same was distracting (especially for someone who
looks closely and pays attention to details like this).

What we do instead, in this commit, is place an invisible "spacer"
tile between each word. This way, the browser is doing the exact same
computation for the "spacer" tiles and the "real" tiles, so they will
match.

That much is simple. The real trick comes when one word ends precisely
at the right edge of the view and then the "spacer" tile wraps on to
the next row. This results in the first word in that row being offset
to the right by the spacer tile, but we don't want that.

To account for this, we use a resizeObserver to notice when any
resizing happens, and in that case we walk through the tiles and
notice whenever the "offsetTop" of a spacer tile is larger than the
"offsetTop" of the previous tile. This indicates that that spacer tile
got wrapped. And in this case we style that spacer to have zero width.

Phew! That's a lot of text to explain a fair amount of code, all just
to correct a rendering error where tiles were just off by about a
single pixel.

6 days agoanagram: Add a guard against the same letter getting taken twice
Carl Worth [Mon, 9 Mar 2026 03:10:05 +0000 (23:10 -0400)]
anagram: Add a guard against the same letter getting taken twice

This is effectively debouncing taps (or keypresses) of letters being
taken from the center of the play field and put into the rack. If the
same letter tile is taken multiple times then a player can end up with
"ghost" tile in the rack that never goes away but also can't be
interacted with.

6 days agoanagrams: Add a "Noe, I'm done" button to the "Still playing?" dialog
Carl Worth [Mon, 9 Mar 2026 03:08:17 +0000 (23:08 -0400)]
anagrams: Add a "Noe, I'm done" button to the "Still playing?" dialog

This just dismisses the dialog.

I think it's important to add this because when theh dialog pops up it
triggers a natural reaction to want to click something to make it go
away. But when it hhas only one button, and that button isn't what you
want, it's mildly unnerving to just sit there and watch the countdown.

Much better to let the player answer the question the game is asking.

6 days agoanagrams: Add letters to the rack optimistically
Carl Worth [Mon, 9 Mar 2026 02:09:05 +0000 (22:09 -0400)]
anagrams: Add letters to the rack optimistically

Rather than waiting for a server response before displaying the letters
in the rack.

We _do_ still wait for the server response, and if it fails, then we
will revert and move the letter from the rack back to the center of
the board.

This optimistic addition guarantees that letters are added to the rack
in the order that the user typed them, (even if the responses to each
request come back in some other order). Reliable typing---what a concept!

6 days agoMove ReconnectingEventSource from client to base.html in the server
Carl Worth [Mon, 9 Mar 2026 01:54:30 +0000 (21:54 -0400)]
Move ReconnectingEventSource from client to base.html in the server

Since some pages use that without referencing lmno.js but all pages
need to have the ReconnectingEventSource defined.

6 days agoAdd a new ReconnectingEventSource, and use it in all cames
Carl Worth [Mon, 9 Mar 2026 01:43:34 +0000 (21:43 -0400)]
Add a new ReconnectingEventSource, and use it in all cames

This wrapper for EventSource will attempt to reconnect after a lost
connection (up to 5 times with a 2-second delay between each attempt).

With this in place, a quick server restart (< 10 seconds) should be
unnoticed by clients.

6 days agoanagrams: Again, follow the rule that server events are the source of truth
Carl Worth [Mon, 9 Mar 2026 01:20:20 +0000 (21:20 -0400)]
anagrams: Again, follow the rule that server events are the source of truth

Prior code here was returning letters from the rack (claim area) to
the center of the board, but then server events would also return the
letters, resulting in duplicate letters appearing in the center as
ghosts.

Meanwhile, there was an opposite problem in response to the user
pressing backspace in quick succession. Because the client was waiting
for the server to remove the tile from the rack, addiitional presses
of backspace would all apply to the same last tile, ad would fail.

So, now, as of this commit, we remove tiles from the rack with
backspace, (allowing subsequent presses to target subsequent letters)
but wait for the server to tell us the tile has been returned to the
center area. This should keep state in sync and keep things humming
along.

6 days agoanaagrams: Implement a game-ending modal
Carl Worth [Sun, 8 Mar 2026 22:34:49 +0000 (18:34 -0400)]
anaagrams: Implement a game-ending modal

Once the bag is empty and all players have gone idle, (nobody has even
attempted to claim a word in some time), the server will report that
the game is ready to end. The client then displays a modal with a
countdown giving the user the chance to say whether they are still
looking for words. If anyone is still looking, the server should start
its idle counter over. If not, then the server should declare the game
over.

6 days agoAn attempt at catching some state drift bugs (and adding logging as well)
Carl Worth [Sun, 8 Mar 2026 22:13:07 +0000 (18:13 -0400)]
An attempt at catching some state drift bugs (and adding logging as well)

I recently noticed a letter get "stuck" in the center area, (it appeared
to be there, but did not allow any interaction).

This commit is by claude which it described as follows, (note: in the
below, rAF is requestAnimationFrame):

* Fixed the likely culprit — rAF loop using stale state:

  The old code checked this.state.revealing[tile.id] synchronously
  after an async setState to decide whether to keep animating. Now it
  uses a local running flag, and the loop termination is decided
  inside the setState callback where it has access to the actual
  current state.

* Defensive cleanup in receive_center:

  When the server sends an authoritative center update, any revealing
  entries for tiles no longer in center are now cleaned up. This
  prevents ghost revealing state from accumulating.

* Periodic consistency check (every 5s):

  - Detects stale revealing entries for tiles not in center, logs a
    warning, and auto-cleans them

  - Detects inconsistent claim state

The combination of the rAF fix and the defensive cleanup in
receive_center should prevent the stuck-tile scenario. And if
something else causes drift in the future, the console warnings will
help diagnose it.

6 days agoAdd comment about authoritative server state for central tiles
Carl Worth [Sun, 8 Mar 2026 18:15:55 +0000 (14:15 -0400)]
Add comment about authoritative server state for central tiles

As a reminder to ensure we follow this principle.

6 days agoAllow for rearranging the rack while claiming a work
Carl Worth [Sun, 8 Mar 2026 16:42:01 +0000 (12:42 -0400)]
Allow for rearranging the rack while claiming a work

This is implemented with both of DND and touch drag, (so should work
either a mouse or a touchscreen).

6 days agoanagrams: Fix claim interface to work for stealing a word
Carl Worth [Sun, 8 Mar 2026 16:18:08 +0000 (12:18 -0400)]
anagrams: Fix claim interface to work for stealing a word

Typing letters in the claim area now draws from stolen words first,
(if possible), and from the center area otherwise. Each letter used
from a stolen word is marked in accent-color-muted to show it has
been used. The backspace key or a little "X" badge can be used to
return letters from the rack back to where they came from.

6 days agoanagrams: Display words and letters being claimed by another player
Carl Worth [Sun, 8 Mar 2026 16:03:10 +0000 (12:03 -0400)]
anagrams: Display words and letters being claimed by another player

This allows other players to be a part of the action, (and even try
to predict what the final word will be while a claim is happening).

6 days agoanagrams: Make the "return word" a badge at the upper right of the word
Carl Worth [Sun, 8 Mar 2026 15:48:39 +0000 (11:48 -0400)]
anagrams: Make the "return word" a badge at the upper right of the word

This makes it much more clear what this icon is, (it was confusing
when it was inline next to the existing '+').

6 days agoanagrams: Allow clicking on a word to steal it
Carl Worth [Sun, 8 Mar 2026 15:44:45 +0000 (11:44 -0400)]
anagrams: Allow clicking on a word to steal it

In addition to dragging the word, which was already supported.

6 days agoanagrams: Allow pressing Enter to start a claim
Carl Worth [Sun, 8 Mar 2026 15:42:23 +0000 (11:42 -0400)]
anagrams: Allow pressing Enter to start a claim

If claiming letters from the center, the user can just start typing.

But for a steal, they need another keybinding to initiate the claim
phase and Enter seems like a reasonable option for this.

6 days agoDisplay 3, 2, 1 when revealing a tile (even if server uses < 3 seconds)
Carl Worth [Sun, 8 Mar 2026 15:38:45 +0000 (11:38 -0400)]
Display 3, 2, 1 when revealing a tile (even if server uses < 3 seconds)

We recently change the server to make the tile reveal time be only 1.5
seconds. But we still want to display a "3, 2, 1" countdown.

So evenly space out those 3 numbers in whatever time the server gives us.

6 days agoletterrip, anagrams: Make game reload smoother
Carl Worth [Sun, 8 Mar 2026 15:11:10 +0000 (11:11 -0400)]
letterrip, anagrams: Make game reload smoother

Previously we were requiring each player to do a separate join_game
(even after they were already part of the game). Notably, if the user
ever reloaded their browser, they had to click "Join game" yet again.

Instead, in this commit we add a game.started state. And we only need
one player to start the game, triggering the send of the started game
state to all players.

Now, if a player reloads their browser, they will just see the game
state, and not a "join game" button.

6 days agoArrange tiles neatly when reloading the game
Carl Worth [Sun, 8 Mar 2026 14:16:51 +0000 (10:16 -0400)]
Arrange tiles neatly when reloading the game

The random positioning (which we use for one-at-a-time dealing of
tiles) was failing here, because each tile's random position was being
chosen against an empty playfield, (the tiles are being added in bulk
and the state isn't being updated between tiles). So the letters ended
up piling on top of each other.

We have a nice way to arrange non-overlapping tiles with the
shuff_tiles() function, so just call that once when doing a bulk
receive of tiles.

6 days agoUse a full tile's worth of space between words in the score display.
Carl Worth [Sun, 8 Mar 2026 13:54:31 +0000 (09:54 -0400)]
Use a full tile's worth of space between words in the score display.

Previously, the inter-word display was a tiny gap and things all ran
together.

Both the tile size and the gap between tiles are variables for
consistent computation.

6 days agoanagrams: Compute correct constraints when dragging tiles
Carl Worth [Sun, 8 Mar 2026 13:50:44 +0000 (09:50 -0400)]
anagrams: Compute correct constraints when dragging tiles

Keeping tiles precisely in the bounds of play.

6 days agoAdd a shuffle button for arranging all tiles in the play area
Carl Worth [Sun, 8 Mar 2026 13:47:43 +0000 (09:47 -0400)]
Add a shuffle button for arranging all tiles in the play area

If the user wants to move them around, they can. But for cleaning up,
(or changing the order randomly), the player can click this shuffle
button.

6 days agoanagrams: Bring claim area into our color scheme
Carl Worth [Sun, 8 Mar 2026 13:32:04 +0000 (09:32 -0400)]
anagrams: Bring claim area into our color scheme

By preferring --accent-color and existing button styling wherever
possible, and add a new --accent-color-muted. Avoid bright red for
actions like cancelling the claim or returning a word, using subtle
gray instead.

6 days agoanagrams: Try a little to avoid placing a tile on top of others
Carl Worth [Sun, 8 Mar 2026 13:23:38 +0000 (09:23 -0400)]
anagrams: Try a little to avoid placing a tile on top of others

This just tries 10 different random positions and picks the one that
is the furthest from existing tiles.

6 days agoAdd support for dragging tiles while claiming
Carl Worth [Sun, 8 Mar 2026 13:20:25 +0000 (09:20 -0400)]
Add support for dragging tiles while claiming

This can be either to drag tiles to the rack (to claim them) or to
just rearrange the tiles (as can already be done outside of
claiming). A 5-pixel threshold of movement will trigger a drag
operation. Movement less than that will be considered a click and will
claim the letter.

6 days agoanagrams: Add a bunch of keybindings to make things keyboard friendly
Carl Worth [Sun, 8 Mar 2026 13:13:38 +0000 (09:13 -0400)]
anagrams: Add a bunch of keybindings to make things keyboard friendly

The most significant is that just typing a word starts a claim
implicitly. But we also add "space" for drawing a new letter from the
bag, and Y/N for voting.

6 days agoUse an SVG for the tile bag (rather than an emoji that looks like a purse)
Carl Worth [Sun, 8 Mar 2026 13:06:23 +0000 (09:06 -0400)]
Use an SVG for the tile bag (rather than an emoji that looks like a purse)

This SVG is creative commmons (public domain dedication) made available
through the Open Clipart Library. We originally found it here:

https://commons.wikimedia.org/wiki/File:Mcol_money_bag.svg

And edited it to remove the dollar sign.

6 days agoanagrams: Change score to use existing accent color
Carl Worth [Sun, 8 Mar 2026 12:47:01 +0000 (08:47 -0400)]
anagrams: Change score to use existing accent color

Rather than inventing a new color (which looked pretty bad).

6 days agoanagrams: Use gloabl styling for the "Claim a Word" button
Carl Worth [Sun, 8 Mar 2026 12:43:40 +0000 (08:43 -0400)]
anagrams: Use gloabl styling for the "Claim a Word" button

Trying to have some consistent styling across the games here.

6 days agoRemove custom "join-btn" classes from letterrip and anagrams
Carl Worth [Sun, 8 Mar 2026 12:39:30 +0000 (08:39 -0400)]
Remove custom "join-btn" classes from letterrip and anagrams

We already have button styling at the top levl. Use it for consistency.

6 days agoMake the "Host a new game" buttons primary on each page
Carl Worth [Sun, 8 Mar 2026 12:31:38 +0000 (08:31 -0400)]
Make the "Host a new game" buttons primary on each page

Displaying it first, (before the form for joining an existing game).

Also drop the submit button from the join form, (relying on the user
simply entering a game ID instead).

This makes the primary flow smoother: Choose a game, then click "Host"
without the user being confronted with a form and having to decide
which of two buttons to click.

6 days agoSimplify tile dealing from the bag
Carl Worth [Sun, 8 Mar 2026 12:21:49 +0000 (08:21 -0400)]
Simplify tile dealing from the bag

No longer require multiple people to request a letter. Instead, any person
can draw a new letter from the bag as long as no letter reveal is currently
in progress.

6 days agoFix tile dealing animation
Carl Worth [Sun, 8 Mar 2026 12:04:14 +0000 (08:04 -0400)]
Fix tile dealing animation

It was previously showing only a "3" instead of "3", "2", "1", and it
was fading the whole tile instead of just the number. Both issues are
fixed in this commit.

6 days agoFix Anagrams: draggable center tiles, keyboard input, countdown animation, claim...
Carl Worth [Sun, 8 Mar 2026 05:22:37 +0000 (00:22 -0500)]
Fix Anagrams: draggable center tiles, keyboard input, countdown animation, claim bugs

1. Center tiles can be dragged to rearrange (client-side only,
   mouse and touch) to help visualize possible words.
2. Keyboard input during claiming: type letters to grab from
   center, Backspace to return last, Enter to submit, Escape
   to cancel.
3. Countdown shows 3, 2, 1 on the tile with opacity fade
   animation each second.
4. Fix cancelled claims not returning tiles to center (let
   server SSE events handle state cleanup).
5. Fix UI staying in claim mode after successful word submission
   (server-side fix: broadcast claim-end after acceptance).
Also remove game_steal references (deferred for later).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6 days agoAdd Anagrams client-side UI
Carl Worth [Sun, 8 Mar 2026 03:40:25 +0000 (22:40 -0500)]
Add Anagrams client-side UI

React game component with center letter pool (random tile
positions), claim mode with rack for arranging words, player
word areas with steal support, voting modal for non-dictionary
words, and game-over scoreboard. Also adds lobby page and
listing on main index.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 days agoExtract shared tile CSS into tiles.css
Carl Worth [Sun, 8 Mar 2026 00:04:12 +0000 (19:04 -0500)]
Extract shared tile CSS into tiles.css

Base .tile and .tile.blank styles are now in a shared stylesheet
so they can be reused by multiple letter-based games.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7 days agoletterrip: Fix blank-letter to work even if letter selection is cancelled
Carl Worth [Sat, 7 Mar 2026 23:05:55 +0000 (18:05 -0500)]
letterrip: Fix blank-letter to work even if letter selection is cancelled

If a user is moving a blank tile off of their rack onto the board,
then they are required to choose a letter for the blank. In this
situation, cancelling letter selection cause the blank tile to be
returned to the rack.

In contrast, when moving a blank tile from one space on the board to
the other, the blank will already have a selected letter, and it's
reasonable for that selection to be unchanged. So in this case,
cancelling the letter selection should let the movement work, and
should not send the letter back to the rack.

This commit fixes that scenario by performing the movement prior to
bringing up the selection modal. That way, if the selection modal is
cancelled, there's nothing else to do and the user gets the desired
behavior (the tile moved, unchanged).

7 days agoAdd a form to join an existing game (by 4-letter code) from each game page
Carl Worth [Sat, 7 Mar 2026 16:40:11 +0000 (11:40 -0500)]
Add a form to join an existing game (by 4-letter code) from each game page

We already had the ability to host a new game at these pages, but a
user may land here on want to join an existing game. So give them that
form to be able to do that. (Saves them having to know that they could
go to / to do that, and saves them the work of doing that.)

7 days agoletterrip: Allow the grid to grow beyond the default page width
Carl Worth [Sat, 7 Mar 2026 14:36:10 +0000 (09:36 -0500)]
letterrip: Allow the grid to grow beyond the default page width

It's silly to make the user scroll back and forth when the grid gets
wider than the default page. So set the board's container to use a
maximum width that is based on the viewport, rather than just being a
percentage of the parent. For this to work, we also have to drop the
parent-relative 100% maximum width from .board-and-rack.

7 days agoletterrip: Don't bring up modal for selecting blank tile when first clicking it
Carl Worth [Sat, 7 Mar 2026 13:53:12 +0000 (08:53 -0500)]
letterrip: Don't bring up modal for selecting blank tile when first clicking it

Instead, just select the tile on first click, and then bring up the
selection modoal on the second click, (either when selecting the
destination cell for movement or deselecting it).

This is consistent behavior with what the user will have first seen
when moving the blank from the rack to the board, and now means that
the user can use click-to-select/click-to-move to move a blank tile
from one board square to another, (which was impossible prior to this
commit).

7 days agoletterrip: Remove all word validation from the client
Carl Worth [Sat, 7 Mar 2026 13:10:22 +0000 (08:10 -0500)]
letterrip: Remove all word validation from the client

Now that the server has a dictionary, it performs all validation of
valid tile placements. This allows for a smaller client, (no need
to download a word list anymore), and ensures that word validation
is performed consistently in a single place on the server side.

7 days agoletterrip: Display scores at the end of the game
Carl Worth [Sat, 7 Mar 2026 04:08:17 +0000 (23:08 -0500)]
letterrip: Display scores at the end of the game

The server now computes a score for each player and sends them out,
so display the scores and the board for each player.

7 days agoRework touch drag operation to render dragging tile as a React component
Carl Worth [Fri, 6 Mar 2026 22:06:06 +0000 (17:06 -0500)]
Rework touch drag operation to render dragging tile as a React component

We encountered a bug where a touch drag operation was interrupted, by
some operation, leaving a ghost tile left around half-way through the
drag operation. One option to fix this would be to implement a
tounchCancel handler to clean things up.

But an alternate approach, in this commit, is to render the tile being
dragged as a React component. This way, everything is rendered
uniformly as React components, and we have less dependence on precise
browser semantics with respect to touchCanel, etc.

7 days agoSeveral fixes for styling of the "blank modal" selector
Carl Worth [Fri, 6 Mar 2026 21:44:58 +0000 (16:44 -0500)]
Several fixes for styling of the "blank modal" selector

This is the modal dialog that pops up when the user clicks on a
blank tile to select what letter it represents. The changes in
this commit are:

1. Use the same appearance (referencing the same CSS class) for
   the tiles in this modal as for tiles in other contexts, (this
   replaces the previous custom styling which was white text on
   a light background and hard to read).

2. Restructure the modal so that it is centered over the grid
   rather than centered over the viewport (also constrain the
   rack to not be wider than the grid).

3. Fix a bug that resulted from the user cancelling a selection of a
   blank tile, (it was "returned" to the rack before being properly
   removed from the rack, resulting in two occurences of the same tile
   on the rack). See the reassign_true logic in this commit for the
   relevant fix.

8 days agoUpdated babelrc from babel 6 to babel 7 format
Carl Worth [Fri, 6 Mar 2026 16:19:52 +0000 (11:19 -0500)]
Updated babelrc from babel 6 to babel 7 format

And update this dependency in the README file.

8 days agoindex.html: Add "Letter Rip" to the list of available games.
Carl Worth [Fri, 6 Mar 2026 16:06:54 +0000 (11:06 -0500)]
index.html: Add "Letter Rip" to the list of available games.

Which is the latest addition to LMNO games.

8 days agoUse new /place endpoint to tell server aboud tile placements
Carl Worth [Fri, 6 Mar 2026 14:37:27 +0000 (09:37 -0500)]
Use new /place endpoint to tell server aboud tile placements

And accept the board contents when the server provides it.

This is all so that a browser refresh doesn't destroy board state.

8 days agoDon't grow the grid if not needed, (shift tiles instead)
Carl Worth [Fri, 6 Mar 2026 14:30:06 +0000 (09:30 -0500)]
Don't grow the grid if not needed, (shift tiles instead)

At least, shifting of the tiles is what the user experiences. Within
the code, the concept is simpler: We don't have a grid size at all
anymore, but simply compute the grid bounds that we want whenever
things change. The bounds are made to just fit the tiles (plus one
extra row/column on each side) and never smaller than the original
size chosen to fill the screen.

8 days agoMake the rack sticky
Carl Worth [Fri, 6 Mar 2026 14:22:15 +0000 (09:22 -0500)]
Make the rack sticky

If the user needs to start panning the grid around, we want their rack
to always stay visible.

8 days agoOnly apply hover effects on devices with a true pointer
Carl Worth [Fri, 6 Mar 2026 14:16:41 +0000 (09:16 -0500)]
Only apply hover effects on devices with a true pointer

Prior to this change, the "stuck" button was staying stuck (ha!) with
styling as if hovered even after the user was done pressing it.

8 days agoCompute initial grid size to be no larger than fits on the screen
Carl Worth [Fri, 6 Mar 2026 14:09:32 +0000 (09:09 -0500)]
Compute initial grid size to be no larger than fits on the screen

Nobody wants a UI that starts off with a horizontal scrollbar!

But the 10x10 initial grid wasn't fitting on my mobile device. So
dynamically compute a smaller grid size that will fit.

Also, rather than hard-coding the cell size in the computation of the
grid size, use a --cell-size custom property.

8 days agoAdd a "touch drag" interface to the game
Carl Worth [Fri, 6 Mar 2026 14:00:37 +0000 (09:00 -0500)]
Add a "touch drag" interface to the game

This sits alongside the existing HTML5 DND interface.

The new touch interface is _much_ more friendly on a phone than the
previous HTMl DND interface, (which required long pressing before
it would do anything).

8 days agoChange height of the "Letter Rip" button to match the height of tiles
Carl Worth [Fri, 6 Mar 2026 13:36:14 +0000 (08:36 -0500)]
Change height of the "Letter Rip" button to match the height of tiles

Prior to this change, the appearance of this button was causing the
rack to grow vertically, which was distracting.

8 days agoLeave the "Some words are not valid" text up whenever it is relevant
Carl Worth [Fri, 6 Mar 2026 13:34:51 +0000 (08:34 -0500)]
Leave the "Some words are not valid" text up whenever it is relevant

Prior to this commit, this message was disappearing when the last tile
was removed from the rack, but there's no reason for that. The message
depends only on the state of the board, not whether there are tiles
on the rack or not.

8 days agoAdd a tap-to-select/tap-to-place interface
Carl Worth [Fri, 6 Mar 2026 13:30:46 +0000 (08:30 -0500)]
Add a tap-to-select/tap-to-place interface

This sits alongside the existing drag-and-drop interace, so either
can be used.

8 days agoFix race condition in handling of stuck button
Carl Worth [Fri, 6 Mar 2026 13:14:16 +0000 (08:14 -0500)]
Fix race condition in handling of stuck button

Which was causing the button to stay stuck (ha!). The new logic
lets the SEE event be the single source of truth.

While fixing this, fix the styling of the button to be more clear,
specifically making it appear as a button saying "I'm stuck" where
it was previously blank which made its use non-obvious.

8 days agoCalm down the dynamic grid resizing
Carl Worth [Fri, 6 Mar 2026 12:58:57 +0000 (07:58 -0500)]
Calm down the dynamic grid resizing

There was some annoying jitter as rows were being constantly
added/removed so that there were always 3 empty rows/columns around
placed tiles. Instead, in this commit, the grid starts initially at a
size of 10x10 and then only grows (by one tile) when a tile is placed
at an extreme edge.

8 days agoAdd logging for any non-alphabetic tile that might show up
Carl Worth [Fri, 6 Mar 2026 12:50:02 +0000 (07:50 -0500)]
Add logging for any non-alphabetic tile that might show up

I saw a bug where a tile was diplayed with a value of '1' which was
unexpected. If this happens again, this logging should help us
determine what happened.

8 days agoTrack receival of bag_remaining count when joining
Carl Worth [Fri, 6 Mar 2026 12:30:36 +0000 (07:30 -0500)]
Track receival of bag_remaining count when joining

This was recently added to what the server sends on join

8 days agoInitial implementation of Letter Rip
Carl Worth [Fri, 6 Mar 2026 11:59:32 +0000 (03:59 -0800)]
Initial implementation of Letter Rip

This is the game we originally learned as "Speed Scrabble", (but
similar to what others may have learned later as Bananagrams).

This implementation was created with the assistance of claude opus
4.6.

5 years agoAdd some autofocus attributes
Carl Worth [Sat, 19 Sep 2020 21:41:09 +0000 (14:41 -0700)]
Add some autofocus attributes

Just trying to make the games a little more keyboard friendly.

5 years agoscribe: Add explicit width/height of 100% to elements of the "board" class
Carl Worth [Thu, 9 Jul 2020 02:35:26 +0000 (19:35 -0700)]
scribe: Add explicit width/height of 100% to elements of the "board" class

This fixes a bug with Safari where every mini-grid was appearing with
a height of 0.

5 years agoReformat some h2 tags
Carl Worth [Tue, 7 Jul 2020 12:22:17 +0000 (05:22 -0700)]
Reformat some h2 tags

The extra whitespace here was causing emacs to do something funny,
(underlining that space), so things look better with it dead.

5 years agoRemove extraneous closing p tag.
Carl Worth [Tue, 7 Jul 2020 12:21:54 +0000 (05:21 -0700)]
Remove extraneous closing p tag.

Missed this in a recent edit.

5 years agoLink scribe in at the top level
Carl Worth [Tue, 7 Jul 2020 06:29:19 +0000 (23:29 -0700)]
Link scribe in at the top level

Now that glyphs are scored, I feel a bit better about putting the game
out there.

5 years agoScore each mini glyph and render the winner for each
Carl Worth [Tue, 7 Jul 2020 06:26:43 +0000 (23:26 -0700)]
Score each mini glyph and render the winner for each

At this point the game is almost totally complete. All that is missing
is the final-score indication of the majority winner and the
super-glyph winner.

5 years agoPrep for stashing final scores against each mini grid
Carl Worth [Tue, 7 Jul 2020 06:10:53 +0000 (23:10 -0700)]
Prep for stashing final scores against each mini grid

By turning each mini grid into an object rather than just an array of
squares. This new object now has a place to lodge scores and a final
winner for each mini grid, (though we aren't populating those yet).

This commit is intended to have no visible change on the game.

5 years agoAdd support for detecting glyph shapes
Carl Worth [Tue, 7 Jul 2020 05:58:12 +0000 (22:58 -0700)]
Add support for detecting glyph shapes

And color the background of each cell that is part fo a glyph in a
player-specific color.

Note: I'm not at all convinced that this is a good way to style
things, but the actual functionality is here now, and I'll be happy to
improve the specific styling in the future.

5 years agoScribe: Prep game state for detection of glyphs
Carl Worth [Tue, 7 Jul 2020 02:08:32 +0000 (19:08 -0700)]
Scribe: Prep game state for detection of glyphs

There's not any detection of glyphs here yet, there's simply a new
slot in each of the squares: Where we used to just have a textual
ymbol for each occupied square, we now have an object:

{
          symbol: '+' or 'o',
          glyph: true or false
        }

And the glyph Boolean is used to add a class to the HTML square
element as well.

5 years agoStop ignoring .gitattributes
Carl Worth [Sun, 5 Jul 2020 18:31:54 +0000 (11:31 -0700)]
Stop ignoring .gitattributes

We're implementing a cleaner approach for this where the nogit script will provide its own .gitattributes data as needed, (and the lmno-todo repository won't need to).

5 years agoRemove typo in URL
Carl Worth [Sun, 5 Jul 2020 06:59:52 +0000 (23:59 -0700)]
Remove typo in URL

Way to many Ts there, of course.

5 years agoIgnore the TODO file, its .nogit directory, and its .gitattributes file
Carl Worth [Sat, 4 Jul 2020 14:59:20 +0000 (07:59 -0700)]
Ignore the TODO file, its .nogit directory, and its .gitattributes file

I'm going to experiment with a TODO file that is present in this
directory but tracked via a separate git repository.

If we ever end up wanting to add a TODO file here, (or a
.gitattributes file), then we can reconsider this implementation
approach at that point.

5 years agoempathy: Don't force active:true when adding state for a new player
Carl Worth [Sat, 4 Jul 2020 14:53:32 +0000 (07:53 -0700)]
empathy: Don't force active:true when adding state for a new player

This fixes the bug where reloading the interface would cause inactive,
grayed-out player names to appear solid instead of grayed out.

What I had been thinking when writing this code is that this function
would be called only when a new player joins the game, (and by
definition, a newly joined player must be active). But this function
can also be called when a player reloads their interface, and at that
point player-join events are received for all players whether active
or not.

Meanwhile, the server is now explicitly providing the active bit for
players, so we get the right information without doing anything.

5 years agoDisplay (grayed out) inactive players with non-zero scores
Carl Worth [Tue, 30 Jun 2020 00:09:31 +0000 (17:09 -0700)]
Display (grayed out) inactive players with non-zero scores

This issue came up with playtesting last night: We had a player who
finished in the top three overall, but dropped out for the last couple
of rounds. But we still wanted to see their score in the final
results. So, here we keep track of active and inactive players and
display the inactive ones (if they have non-zero score) with 50%
opacity.

5 years agoOnly consider active players when counting players needed for prompt voting
Carl Worth [Tue, 30 Jun 2020 00:05:17 +0000 (17:05 -0700)]
Only consider active players when counting players needed for prompt voting

Now that the server is sending us inactive players, we don't want to
consider them when computing how many votes we need to go forward with
a category.

5 years agoFix "KUDOS SLAM" achievement to only consider players that answered
Carl Worth [Mon, 29 Jun 2020 23:34:22 +0000 (16:34 -0700)]
Fix "KUDOS SLAM" achievement to only consider players that answered

The potentially larger number of registered players is totally
irrelevant here.

5 years agoAllow a user to un-select a star
Carl Worth [Mon, 29 Jun 2020 22:26:50 +0000 (15:26 -0700)]
Allow a user to un-select a star

By doing the intuitive thing and clicking it again.

5 years agoAdd instructions for giving kudos
Carl Worth [Mon, 29 Jun 2020 22:24:45 +0000 (15:24 -0700)]
Add instructions for giving kudos

Otherwise, this feature could be hard to discover.

5 years agoAdd the KUDOS SLAM and GREAT MINDS achievements
Carl Worth [Mon, 29 Jun 2020 22:19:07 +0000 (15:19 -0700)]
Add the KUDOS SLAM and GREAT MINDS achievements

At this point, I've implemented all of the achievements we originally
thought of, (except for TWINNER which is going to take a bit more code
to find cases where it applies).

5 years agoAdd some explanatory text when there aren't enough categories/votes
Carl Worth [Mon, 29 Jun 2020 22:07:26 +0000 (15:07 -0700)]
Add some explanatory text when there aren't enough categories/votes

Encouraging the players to make more of either, so that the game will
make some progress.

5 years agoFix category voting to select among only those with the most votes
Carl Worth [Mon, 29 Jun 2020 21:56:16 +0000 (14:56 -0700)]
Fix category voting to select among only those with the most votes

Previously, the code was selecting randomly among all categories with
at least a quorum of votes. With this commit, the code now does what
was intended, by selecting randomly only among the categories that are
tied for the most votes.

5 years agoChange category voting to require fewer votes when there are more categories
Carl Worth [Mon, 29 Jun 2020 21:54:31 +0000 (14:54 -0700)]
Change category voting to require fewer votes when there are more categories

Now, at the beginning, it's no longer enough for there to be a
majority of votes on a single prompt. Instead, the number of votes
required is the number of players minus the number of available
prompts.

5 years agoPut the "Start Game" button above the category-vote prompts
Carl Worth [Mon, 29 Jun 2020 21:49:52 +0000 (14:49 -0700)]
Put the "Start Game" button above the category-vote prompts

So that it's not required to scroll down a tone before being able to
start the game.

5 years agoDisplay kudos (as stars) in the per-round scores
Carl Worth [Mon, 29 Jun 2020 21:28:35 +0000 (14:28 -0700)]
Display kudos (as stars) in the per-round scores

Now that the server gives us this information, let's display it,
(otherwise, the players could be very confused about why some ties
were apparently broken in the sorting).

5 years agoSend kudos as a Boolean alongside each word group
Carl Worth [Mon, 29 Jun 2020 21:27:36 +0000 (14:27 -0700)]
Send kudos as a Boolean alongside each word group

This is how the server is now expecting these to come in, (now that
it's actually scoring them).

5 years agoAdd a QUIRKSTER achievement
Carl Worth [Mon, 29 Jun 2020 17:49:22 +0000 (10:49 -0700)]
Add a QUIRKSTER achievement

This one recognizes the dubious achievement of submitting an entire
docket of answers with no matches with anyone else at all. Thanks to
Andrew for naming it.

5 years agoRename "label" to "achievement"
Carl Worth [Mon, 29 Jun 2020 15:55:29 +0000 (08:55 -0700)]
Rename "label" to "achievement"

The word "label" was far too generic to capture the stlying needs for
this class. Thanks to Andrew for pointing out that this feature is
really what games today call an "achievement".

5 years agoDon't allow text to overflow an ambiguity button in the Y direction
Carl Worth [Mon, 29 Jun 2020 15:43:48 +0000 (08:43 -0700)]
Don't allow text to overflow an ambiguity button in the Y direction

Thanks to one of my nephews for submitting something like:

b̵̩͚̽̀͂͂͑̿͘̕͝u̸̮̅͌g̷̡̢̻̬͎̙͉̳̬͈̑̐̋̃̅ẻ̶̤̜̾̐x̷̦͔͚͙̤̀̀̀̂̕ṣ̷͙̦̘̰̔̾͊̊̍̒͛̄̉̚p̵̡̤̫̹̥̀́́͆ǫ̷̮͚̳̭̘̭̏s̷͔̈́̈͋̿̌̑͛̚̚͘i̸͔͔̾̄͐̓͗͐̌͘ṉ̷̨̭̻͇̥͌̓̕g̴̢̧̖̬͈͇̻͉̯͈̅̔͛̀

in our game last night, which ended up scribbling over the rows above
and below in the judging view. This fix chops things off vertically,
(which doesn't solve the case if someone is _legitimately_ trying to
get such text to appear—we can address that case when it appears).

5 years agoAllow a really long word inside an ambiguity button to break onto multiple lines
Carl Worth [Mon, 29 Jun 2020 15:40:08 +0000 (08:40 -0700)]
Allow a really long word inside an ambiguity button to break onto multiple lines

Thanks to playtesting with "4 made-up words" and entries of
"supercalifragilisticexpialidocious" for exposing this bug.

5 years agoReword the Move On button when we're not waiting for anyone specific
Carl Worth [Mon, 29 Jun 2020 15:32:51 +0000 (08:32 -0700)]
Reword the Move On button when we're not waiting for anyone specific

This case arises when there are additional players still connected to
the game, but that haven't even started typing any answers.

In this case, the view looks like this:

Submission received

The following players have submitted their answers: <list>

In this case, wording of "Move On Without Their Answers" suggests the
exact opposite, (as if "their" is referring to the submitted players
rather than those not listed on this page). The new wording in this
case, "Move On Without Anyone Else" makes it more clear what the
behavior is.

5 years agoDefine the move_on button after the still_waiting component
Carl Worth [Mon, 29 Jun 2020 15:29:51 +0000 (08:29 -0700)]
Define the move_on button after the still_waiting component

This is just code movement here with no intended logical change. The
motivation here is so that the "Move On" button can be worded
differently depending on who we're waiting for.

5 years agoReject a category with a number of items of 0
Carl Worth [Mon, 29 Jun 2020 15:27:07 +0000 (08:27 -0700)]
Reject a category with a number of items of 0

Thanks to my nephews for poking holes at the implementation by feeding
some stressful input to the game.

5 years agoAdd some clarifying text to the "Move On" buttons
Carl Worth [Mon, 29 Jun 2020 15:14:59 +0000 (08:14 -0700)]
Add some clarifying text to the "Move On" buttons

Making it more plain to participants that advancing like this will
leave some players out of the specific phase.

5 years agoSet kudos to null if no answer is starred
Carl Worth [Mon, 29 Jun 2020 15:06:54 +0000 (08:06 -0700)]
Set kudos to null if no answer is starred

This fixes the bug we saw last night where nobody could submit judging
results until they had starred at least one item.

5 years agoEliminate some debugging calls to console.log
Carl Worth [Mon, 29 Jun 2020 15:06:23 +0000 (08:06 -0700)]
Eliminate some debugging calls to console.log

These were not meant to stick around.

5 years agoAdd key to list of PromptOption components
Carl Worth [Mon, 29 Jun 2020 15:05:23 +0000 (08:05 -0700)]
Add key to list of PromptOption components

This is the classic thing to overlook in React programming. It's easy
to forget the key until React warns that it's missing.

5 years agoempathy: Add the ability to star one favorite item
Carl Worth [Sun, 28 Jun 2020 23:25:29 +0000 (16:25 -0700)]
empathy: Add the ability to star one favorite item

The client isn't currently saving information about which words the
player themself submitted, so it isn't yet preventing the user from
sending kudos to an item they submitted themself.

5 years agoempathy: Pre-group words according to common patterns
Carl Worth [Sun, 28 Jun 2020 22:55:46 +0000 (15:55 -0700)]
empathy: Pre-group words according to common patterns

Specifically, the following will be considered identical and
pre-grouped:

<word> = <word>s
        <word> = a <word>
        <word> = an <word>
        <word> = the <word>

Unlike the server-side canonicalization of case differences, which are
not visible, the above matching words are all still made available to
the player and simply pre-grouped. So, the player can decide whether
to leave them grouped or to separate them back out.

5 years agoAdd a "PERFECT" label for a player with a perfect score
Carl Worth [Sun, 28 Jun 2020 22:28:34 +0000 (15:28 -0700)]
Add a "PERFECT" label for a player with a perfect score

It's nice to know when a player (or group of players) did as well as
could be done.