Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Card game where players write their own cards that get parsed into code (wordbots.io)
114 points by alnis 11 months ago | hide | past | favorite | 26 comments
Wordbots is a long-running side project I've been working on on-and-off for the past ~7 years that I finally feel comfortable enough with to share with the HN community.

It's an online tactical card game (inspired by games like Hearthstone and Magic: the Gathering), where players write their own cards in natural language, that gets parsed down to JavaScript. The English-to-JavaScript translation is handled by a semantic parser operating on a hand-crafted CCG grammar – kind of an “old-school” approach in this age of LLMs but one that performs quite well on the very constrained language of Wordbots cards.

The resulting game gets pretty wacky as players can create all sorts of cards, though there are some game formats that try to produce more balanced gameplay as well (e.g. one format in which both players shuffle their decks together, and various draft formats).

If you're curious about how it all works, I made a write-up about it here: https://app.wordbots.io/how-it-works

And if you want to chat about Wordbots beyond this thread, please don't hesitate to join our discord at https://discord.wordbots.io/ . I'd love to hear any and all feedback.


I don't like competing so my first thought was to make a card which says, "You win the game." Is that possible, ostensibly with great cost, or is there some restriction on the effects? I believe MTG card effects often directly translate to a certain "mana" cost so it can be determined (in most cases) if a card is "overpowered" for its cost. Does this have some mechanism which ties effect to cost?

(I also appreciate the "old-school" approach in this case; I suspect it actually makes it easier to determine that the intended card is invalid.)

Edit: I tried, and I guess it is able to understand that. Nothing which seems to tie that to a cost, though. That makes sense as you'd effectively have to define a game system while this is crowdsourcing that to the community. I imagine the intention for play (if there really is one) is to have players agree on a set of cards to use.

You can definitely make an Action card with the text "You win the game" :-)

Wordbots doesn't have a built-in mechanism to enforce cards being at a "fair" power level. We initially had a few ideas for how to do it: some kind of machine-learning approach to determine how much "energy" a card should cost to play based on its text and stats, or having a server constantly simulating games between AI players with various cards to see how effective cards are in practice, or even a market-based mechanic where cards could be traded for in-game currency and how valuable a given card was would determine it's a "fair" card or not.

All of these approaches were ultimately abandoned as too complicated. Instead, we opted to just prioritize game formats where both players are equally likely to have access to any given card in-game:

  - In the Mash-up format, both players build a deck made up of any cards they want, but the two decks are shuffled together into one big deck that both players draw from.
  - In the Set format, players build their own separate decks but have to choose cards from a given "set" of cards curated by a player (and ostensibly the cards within a set should be roughly balanced).
  - In the draft formats (Set Draft and Everything Draft), both players are drafting from the same pool of crads.
This way, overpowered (and underpowered) cards can still be created by players, but at least in these game formats, both players would be equally likely to draw said overpowered cards.

That's clever and elegant, well done. I'm really interested, especially since it turns out to be more than just a ChatGPT front-end.

I started making a game like this 7 years ago too. Congrats on your release :)

What I figured was to make there be a cost for using any card, pinned to the number of targets affected, amount of "force" applied, and one or more resources (life, energy, time, space).

Or an equivalent-exchange/extreme-couponing system of some kind. "To destroy the universe, you must first destroy something of equal or greater value." This can deadlock the game though.

After "heat death of the universe" cost too much to play, the workaround ended up being "wait for all other players to die of natural causes" (hadn't implemented time cost yet).

Could be interesting to see if you can make cards that only one player can use, such as “win the game if this card is played while the seconds of utc time matches the following hmac sum, otherwise lose the game”

Then you’ve got a 1/60th chance of your opponent using it.

Hi, My son has taken a shine to this after I sent him the link (he's up to 100 cards now...). Online, drafting, and the most important bit - user created content (he'd have been as happy with a traditional editor for the cards rules, but has had fun trying to convince the parser to do his bidding).

The Discord link is timing out for me. Hopefully you don't mind a brain dump here.

He had one feature request - the ability to restrict the number of Rare/Uncommon cards to be included in a deck built off of a given set (if that makes any sense).

Also, we hit a few bugs. One time we had a major state desync - on one player one team was entirely wiped out with a given card play, whereas on the other it had no/limited effect. From that point, the games diverged in their entirety - including the log. It was only because we were sat next to each other we even knew.

Some form of hashing of the engine state and comparisons every play could ensure that at least a desync identified (which would hopefully lead to a fix).

Another time, the 'End Turn' button was unresponsive for one player, and we instead had to force a draw.

He had an issue with a card he created that read "when you draw a card, ...", which was triggering when the opponent drew too.

The final thing is more of an irritation, which is the 'Activation' overlay can make it hard to move/attack to the hex immediately to the right.

Otherwise, great game and it's obviously a labour of love. Jist hope for a bit more interest and player activity.

Thank you so much for the feedback! Unfortunately I screwed up the Discord link in the post – it's http://discord.wordbots.io/ , not https:// – but it was too late to modify the HN post after I noticed that.

Glad that you and your son have had fun playing it! He's definitely made the most cards in Wordbots of any user so far, so that's pretty cool :-)

I'll respond to each issue in turn:

Re: decks and card rarity – I hadn't thought of this when implementing card rarities (which right now take effect only in draft mode), but it's a good idea. I'll make an issue for it.

Re: state desync – I've never noticed this issue in testing, but I will admit that the multiplayer code is pretty sloppy (this part isn't exactly my strong suit). In theory the game should be fully deterministic (and the RNG is seeded identically for both players and the server), but it's possible that either a socket message got lost somewhere or there's some nondeterminism in some card behavior that I neglected to notice. If you encounter this again, please let me know what happened right before the desync – it'll help us narrow down the issue. And hashing the state and checking it periodically seems like a good measure to take for now; I'll make an issue for it.

Re: End Turn button unresponsive – This is a bug we've had in the past, and it was caused by an error occurring during combat, resulting in the game state thinking that an attack animation was still happening (so the turn couldn't end yet). I'm pretty sure that it's fixed now, but if you encounter it again, check the game debug log and JS console to see if anything weird happened right before.

Re: card draw trigger – Oops, this looks like an issue with how `afterCardDraw` is being triggered, should be an easy fix on my end. I'll take a look.

Re: Activate popover – Yeah, this is feedback we've gotten in the past, and we're looking into what a better UX for object activation could look like.

That looks neat, thanks for sharing. Speaking of sharing, it seems your repos are missing a license file (and the source files themselves don't have a licensing block that would also serve the same purpose).

I would also recommend linking to https://github.com/wordbots/wordbots-core/blob/v0.20.0-beta/... since the app.wordbots.io version seems to boot up some horrific amount of javascript or something, because the gears just sit there for about 15 seconds before the content finally shows up

Separately, do you know if the vocabulary for wordbots would tolerate the vocabulary for M:TG? IOW, is it possible to "port-over" some of the cards?

Oops, lack of licenses was my bad - good catch! Just added LICENSEs to clarify that both the game (https://github.com/wordbots/wordbots-core) and the parser (https://github.com/wordbots/wordbots-parser) are MIT-licensed.

Regarding M:TG vocabulary, Wordbots's syntax is a little bit different but a lot of the same effects are possible. For example, M:TG's Flametongue Kavu's "When Flametongue Kavu enters the battlefield, it deals 4 damage to target creature." becomes "Startup: Deal 4 damage to a robot" in Wordbots.

Some of the cards that people have been making so far in Wordbots are rough reinterpretations of cards from other games (M:TG, Hearthstone, Faeria, etc). Of course, many cards from these games wouldn't be possible to reimplement in Wordbots, as it doesn't have anywhere near the breadth of mechanics that these more-sophisticated games do. But also, there are some mechanics that are only possible in a game like Wordbots – such as https://app.wordbots.io/card/cnrssvyxfsp: > Replace "1" with "2", "2" with "4", "3" with "6", and "4" with "8" on all cards in your hand.

This would work in Magic: Arena digital-only formats using the perpetual mechanic plus a variation of the text on a card like Magical Hack.

Also, while not related to Wordbots, Alex has a cool JS sandbox-escape-y game https://alexnisnevich.github.io/untrusted/ (https://github.com/AlexNisnevich/untrusted#license CC-BY-NC-SA 3.0) that I thought was fun and you might, too

I like the game itself - it feels well balanced when you are playing single-player mode with built-in cards only.

But creating your own cards is an INCREDIBLY frustrating experience. This is a robot I tried to create (sumbot):

"This robot's attack, speed, and health are the sum of the attacks, speeds, and healths respectively of all other robots in play."

It didn't understand the words: "are", "sum", "speeds", "healths", "respectively".

Very restrictive dictionary and grammar. It pissed me off at a deep level and I probably will step away from this game.

Maybe integrate with an LLM (such as GPT4) to accept card descriptions?

It seems I can set an arbitrary cost for my cards? How do you balance the game when it involves custom cards?

One strategy would be to give each player a deck consisting of their cards and the opponents cards. So if someone made a really imbalanced card, they would have a 50-50 chance of having it used on them.

Re: balance – see a comment I made below on that: https://news.ycombinator.com/item?id=35879796

Re: frustration of writing cards – yeah, I definitely feel you on that. The grammar is fairly restrictive and there's generally just one way to make a given card action parse (you could say it's more like Python than Perl). One affordance that we've put in to at least make writing cards a little easier is the Dictionary/Thesaurus feature in the Workshop, that lets you see all the words and phrases recognized by the parser and examples of how each of them has been used in practice.

Re: sumbot – You can do something like "Startup: Set this robot's attack to the total attack of all robots, and set this robot's speed to the total speed of all robots, and set this robot's health to the total health of all robots."

On the point of card creation, I also found it to be frustrating. Not as much as you did, but for example I couldn't get a card to say "Destroy this robot unless it moved this turn" even though "moved this turn" is in the dictionary. I guess I can only say "Destroy each robot that moved this turn" - no negation, and not specific. I still enjoyed messing with it, but it was a pretty challenging experience to start coming up with cards that were both interesting and legal.

> It seems I can set an arbitrary cost for my cards? How do you balance the game when it involves custom cards?

> One strategy would be to give each player a deck consisting of their cards and the opponents cards. So if someone made a really imbalanced card, they would have a 50-50 chance of having it used on them.

The author actually addressed this by doing exactly that

Yeah, the poor parsing around "moved this turn" is a known issue that I'm going to look into fixing this week. (Someone actually mentioned it yesterday on our discord – they were attempting to make a card with the text "At the end of your turn, if this robot didn't move this turn, restore 2 health to this robot": https://discord.com/channels/301800217055985665/301800217055... )

"At the end of your turn, destroy this robot unless it moved this turn" or "At the end of your turn, destroy this robot if it didn't move this turn" are definitely phrases that ought to parse correctly, and there's already in-game support for these mechanics (it's purely a parser issue).

Glad to hear it's not only within the ruleset, but will be addressed!

I believe this is fixed now, with this parser commit: https://github.com/wordbots/wordbots-parser/commit/f713e5a68...

Maybe integrate with an LLM (such as GPT4) to accept card descriptions?

Use the LLM to turn English into the subset understood by sumbot and it slowly teaches the player the formal language!

Incredibly cool! It's not normally my type of game but I am going to try this out for sure.

I love the idea, and I'm going to try it out!

Weird bug I noticed (and I might have missed a better place to report it): The parser got stuck on the word "praction" in the phrase "When this robot deals damage to another robot, prevent all damage that would be dealt to this robot."

"Praction" comes after the comma in that phrase, apparently?

Hah, this is the keyword substituter incorrectly substituting "event" -> "action" (Action cards were called Event cards in an earlier version of the game). I'll fix that, but in any case, there's not any notion of preventing future damage currently.

P.S. Discord (https://discord.wordbots.io/) or GitHub (https://github.com/wordbots/) would be the best place to report issues like this at the moment.

This is really cool, and actually I think LLMs would be a great fit: they can generate your constrained language from more freeform language input by the user. Might make it easier to get into, and you've done the hard work already by specifying a language for the card rules

Neat idea. Unfortunately it knows nothing about infinite squirrels.

The first card I made was "Startup: Create a copy of this robot in empty adjacent space", which immediately filled the board. Not quite infinite, but similar!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact