GOTA: a fresh take on Game of the Amazons
▲ 13 r/digitaltabletop+1 crossposts

GOTA: a fresh take on Game of the Amazons

Hi everyone,

I've been working on a browser version of Game of the Amazons in my spare time, and I think it's finally ready for other people to try: gota.gg

The Game of the Amazons is an abstract board game from 1988 that surprisingly few people know about. I discovered it years ago through a Numberphile video, A final game with Elwyn Berlekamp, and I've loved it ever since. The rules take about 30 seconds to learn:

  • Each turn you move one of your amazons like a chess queen
  • Then that same amazon shoots an arrow (also like a queen move), and the square it lands on is blocked for good
  • The board slowly fills up, and the last player who can still move wins

That's the whole thing, but the games turn into a tense fight over territory, a bit like Go.

What's in it right now:

  • An interactive tutorial, if you'd rather learn by doing
  • Custom games on square or rectangular boards from 6x6 to 16x16, with up to 8 players
  • Bots from "random" up to "hard" (the hard one is a neural net I trained, and it beats me more often than I'd like)
  • Online auto-match with three modes: Classic 10x10, an "Hourly" mode where everyone gets the same random board for that hour, and "Chaos", with random boards and random starting positions
  • Local games on one device, plus replays

You don't need an account to play, auto-match games included.

I'd really appreciate any feedback: bugs, anything confusing, or whether the tutorial actually makes sense to someone new. Give it a try!

gota.gg
u/imicnic — 11 days ago

CVA Alternative: slot-variants

Hey, I started using tailwindcss about 3 years ago. At the beginning I had mixed feelings about how to use it and struggled to style complex component states. Then I discovered cva and its declarative variants API — it was eye-opening, a real way to bind styles to state. It was great, but soon I needed to style more than one element inside the same component, and that's when I found tailwind-variants (tv for short), which extended cva's idea with slots. Suddenly I could do so much more.

tv became the center of styling for our design system components. It did the job well, but two things kept bothering me:

1. Every slot is a function. You call it with optional variants that, in practice, we almost never passed:

const { base, icon } = component({ size: 'sm' });
base({ class: 'rounded' }); // a function...

And when no slots are defined, tv returns a string instead, like cva. So the return type depends on the config, and it was never quite obvious at the call site which one you were holding.1. Every slot is a function. You call it with optional variants that, in practice, we almost never passed:const { base, icon } = component({ size: 'sm' });
base({ class: 'extra' }); // a function...
And when no slots are defined, tv returns a string instead, like cva. So the return type depends on the config, and it was never quite obvious at the call site which one you were holding.

2. No requiredVariants. The workaround is to patch the prop type by hand:

type ButtonProps = Omit<VariantProps<typeof button>, 'intent'>
  & Required<Pick<VariantProps<typeof button>, 'intent'>>;

I opened a PR to add requiredVariants to tv. After some late feedback it went quiet for about three months, and I started asking myself: could I just build the thing that has everything I want?2. No requiredVariants. The workaround is to patch the prop type by hand:type ButtonProps = Omit<VariantProps<typeof button>, 'intent'>
& Required<Pick<VariantProps<typeof button>, 'intent'>>;
I opened a PR to add requiredVariants to tv. After some late feedback it went quiet for about three months, and I started asking myself: could I just build the thing that has everything I want?

So I built slot-variants (sv for short)

What it gives you:

  • Easy migration from cva/tv — sv accepts both config styles, so in most cases it's just a rename.
  • Required variants — enforced by the types and at runtime, no Omit/Required gymnastics.
  • Presets — named combinations of variant values, usable as a matcher inside compound variants.
  • Slot groups — name a set of slots once, then target the group anywhere a slot name goes, including compound slots.
  • A built-in result cache — repeated calls with the same props (so, every re-render) skip variant resolution entirely.
  • An ESLint/oxlint plugin — catches duplicate and conflicting Tailwind classes across your variants, and other common issues with sv.
  • A SKILL\.md shipped in the package, so LLMs get the API right instead of inventing cva or tv syntax.

Repo link: https://github.com/micnic/slot-variants

Curious whether the things that bugged me about tv bug anyone else, or if I'm alone on this.

u/imicnic — 2 months ago