[HN Gopher] Boardgame.io: an engine for creating turn-based game...
       ___________________________________________________________________
        
       Boardgame.io: an engine for creating turn-based games using
       JavaScript
        
       Author : freetonik
       Score  : 223 points
       Date   : 2024-12-18 10:50 UTC (2 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | downThePipe wrote:
       | Then what, print it out to play on the kitchen table?
        
         | tardibear wrote:
         | It supports multiplayer over the network.
        
         | ramon156 wrote:
         | > multiplayer networking Its in the description
        
         | vasco wrote:
         | Put the screen on the kitchen table and sit around it, call it
         | CounterTop Surface, have a little imagination man.
        
           | thaumasiotes wrote:
           | You say this like a joke, but that would bring a lot of
           | usability and convenience improvements compared to a physical
           | board game. Just moving stuff out of and back into the box
           | can take a lot of work.
           | 
           | It's easy to overlook rules that a computerized game
           | automatically handles for you, though. For example, I'm part
           | of a group that plays Heat (
           | https://boardgamearena.com/gamepanel?game=heat ) every week.
           | An important part of that game is moving the game-controlled
           | cars, and since the platform handles that, only one person in
           | the group. This is potentially quite bad for strategy,
           | depending on the rules you don't know. Another issue that
           | comes up in the same game is people losing track of the size
           | of their deck. The game is very generous about the allowable
           | timing of deck-manipulation effects, but if you're not
           | actively paying attention you can draw through your deck and
           | trigger a reshuffle, wiping out your discard pile, when you
           | wanted to do something special before the reshuffle. This
           | isn't a mistake it's possible to make while using a physical
           | game.
        
             | jz67 wrote:
             | Hey sorry if this is not the place for it but I play heat a
             | lot too and I was looking for a group like this on bgm
             | since the random matches have a lot of people rage quiting
             | etc. can I ask to join this group?
        
               | azemetre wrote:
               | Do you play live or turn based games? I never had an
               | issue of people rage quitting, I also tend to set the
               | games to one turn per day which is reasonable for most
               | people.
        
             | thaumasiotes wrote:
             | > and since the platform handles that, only one person in
             | the group.
             | 
             | This should read "only one person in the group knows how it
             | works".
        
           | sethammons wrote:
           | a tad further: a central phone or tablet as a main board that
           | you interact with via touch and where you can then transfer
           | over to your handheld device over the network to manage your
           | hand. I've not seen this yet, and it would be a pretty great
           | experience I think. No clean up
        
             | dalmo3 wrote:
             | This is basically how Jackbox games work.
        
       | brudgers wrote:
       | Looks like it might originally have been from Google based on
       | this discussion
       | 
       | https://news.ycombinator.com/item?id=15946425
        
         | ErrantX wrote:
         | The original author looks to have been at Google till 2020.
         | 
         | https://nicolodavis.com/
        
           | nicolodavis wrote:
           | boardgame.io was created as a personal open-source project
           | while I was employed at Google. It is not an official Google
           | product.
        
       | ferd wrote:
       | Looks very interesting.
       | 
       | Somewhat related: I've recently wrote a code-walkthrough (in
       | Clojure) of modeling chess-like games.
       | 
       | https://neuroning.com/boardgames-exercise/
       | 
       | It's very basic and intended for teaching/learning functional
       | programming, not a real library or engine like the OP.
        
       | nicolodavis wrote:
       | Original creator of boardgame.io here. A pleasant surprise to see
       | this here after many years.
       | 
       | More recently, I've been working on https://boardgamelab.app/,
       | which uses a visual programming language to model game rules
       | while also taking care of the UI layer.
        
         | jfengel wrote:
         | Oh, thank you. I've used your library a few times for personal
         | projects, and it does exactly the thing that I needed. I really
         | appreciate you having created this.
        
         | thih9 wrote:
         | The boardgamelab.app looks like a stealth, proprietary project;
         | at least at the moment its T&C[1] says: "under this license you
         | may not (...) use the materials for any commercial purpose, or
         | for any public display (commercial or non-commercial)".
         | 
         | Do you have any plans for the business model?
         | 
         | [1]: https://boardgamelab.app/terms-and-conditions
        
           | fourside wrote:
           | What do you mean by stealth? I looked at the website and
           | nothing about it makes it look like it would necessarily be
           | free or open source.
        
             | jzig wrote:
             | Still needs clearer language IMO.
        
             | thih9 wrote:
             | > What do you mean by stealth?
             | 
             | I meant stealth as in: "or for any public display
             | (commercial or non-commercial)", see grandparent comment. I
             | edited the grandparent comment now and added a comma
             | between "stealth" and "proprietary", hope this is clearer.
        
         | wordglyph wrote:
         | Omg! I've been noodling about making my word game
         | https://WordGlyph.xyz multi player and been dreading that
         | journey but now here it is!
        
         | doctorpangloss wrote:
         | > More recently, I've been working on
         | https://boardgamelab.app/, which uses a visual programming
         | language to model game rules while also taking care of the UI
         | layer.
         | 
         | Suppose there were a technology that could turn the canvas you
         | authored into finished, consistent art; and a way to turn
         | natural language rules into correct code. Would you use it? Why
         | or why not?
        
           | anonymoushn wrote:
           | It would be great to save time on the implementation of board
           | game rules engines. Unfortunately the fine folks at FFG are
           | really bad at figuring out what the rules actually are and
           | telling people :(
        
           | lukan wrote:
           | "turn the canvas you authored into finished, consistent art"
           | 
           | Like a jpeg? Otherwise I don't understand your question.
           | 
           | " a way to turn natural language rules into correct code"
           | 
           | And this is straight impossible, as natural language is by
           | definition ambigious in meaning and code is not. Try your
           | luck with LLM's, they come closest.
           | 
           | (a subset of natural language might work, but this is kind of
           | a complex research topic)
        
         | mankyd wrote:
         | I feel like saying that is supports AI players, but not having
         | a simple, already hosted example is a disservice. Even tic tac
         | toe, or go fish would be a nice hook to help people understand
         | what it actually delivers.
        
         | beretguy wrote:
         | There was this iOS game which died which I wanted to recreate:
         | 
         | https://web.archive.org/web/20161020010853/http://www.82apps...
         | 
         | But I have 0 knowledge of game development. Maybe this could
         | make my job easier? Or maybe somebody else who know how to
         | write game can do it? Please?
        
           | LosEstupidos wrote:
           | The HN niggaz voted you down instead to point you onto
           | something, very thoughtful indeed.
        
       | fleabitdev wrote:
       | This engine uses a Redux-like architecture. You have a State type
       | (containing data like "the position of the black kingside rook")
       | and a stream of in-game actions (like "knight to F3"). Each
       | action is handled by a pure function which converts the current
       | State to a new State. You can either transmit State deltas from
       | the server to the client, or just transmit the actions themselves
       | (https://longwelwind.net/blog/networking-turn-based-game/).
       | 
       | This design makes it easy to implement optimistic updates,
       | rollback, replays, automated testing, and recovery after a
       | disconnection. It's a surprisingly good fit for UI, too; you can
       | render simple games as a React component which takes the current
       | State as one of its props.
       | 
       | However, a stream of context-free actions can be a really
       | inconvenient representation for some games. The rules of a board
       | game are often like the control flow of a computer program:
       | you'll see branching, iteration, local variables, function calls,
       | structured concurrency, and sometimes even race conditions and
       | reentrancy. When you try to represent all of this logic as a
       | State object, you're basically maintaining a snapshot of a "call
       | stack" as plain data, and manually resuming that "program"
       | whenever you handle an action. It doesn't seem ideal.
       | 
       | I've been sketching a board game engine which would represent the
       | game logic as normal code instead. It seems promising, but it
       | really needs a couple of language features which don't exist in
       | the mainstream yet, like serialisation of suspended async
       | functions.
        
         | NathanaelRea wrote:
         | Can you explain more what type of game would need a call stack
         | snapshot? I've never developed a game, but it seems like as
         | long as you store like the initial state and prng you could
         | always get the current state by replaying the full history. All
         | the other logic would be stored outside the state, and only
         | added when "committed". As long as prng is stable and you start
         | from the clean state every time, you'd get the same outcome.
        
           | yojo wrote:
           | I think I have a good example from Magic: the Gathering.
           | 
           | There's a card called "Fact or Fiction". You reveal the top
           | five cards of your deck. Then your opponent splits the cards
           | into two piles. Then you pick one of the two piles to take
           | into your hand.
           | 
           | You'll need to store structures representing the choices that
           | are intermediary steps (split cards, pick stack) in your
           | state, which is basically function calls and their params (a
           | call stack). This example could get hairier - Magic also
           | features cards with branching logic "choose 1: do a or b". I
           | can imagine designing cards with large and convoluted
           | possible execution paths.
           | 
           | You could have the card define a schema for state
           | transitions/params and represent all these choices as JSON
           | encoded POJOs, but as a developer it sounds a lot nicer to
           | just be able to suspend an async function every time a choice
           | is made.
        
             | Longwelwind wrote:
             | I had the same issue in AGoT:BG and I solved it by
             | representing the state of the game as a tree. At any point
             | of the game, the current game state is a leaf of the tree.
             | 
             | You'd represent this kind of choice as a child node. When
             | the user has made their choice, the code can return to the
             | parent node with the choice being made so it can continue
             | with the next "step" of the game.
        
               | scrollaway wrote:
               | This is the correct response. Hearthstone is structured
               | like this internally.
               | 
               | If you are curious about it, I wrote a cc0 spec which
               | stores hearthstone game state in xml. It's based on how
               | hearthstone stores game state on the server and client,
               | and it was the first time a replay format was created for
               | hearthstone: https://hearthsim.info/hsreplay/
               | 
               | Incidentally the UI we wrote for hearthstone replays is a
               | react app. It's funny because looking back it was the
               | first time I used react and typescript, and both were not
               | at all adopted by the js community yet at the time.
               | 
               | https://github.com/hearthsim/joust
        
           | fleabitdev wrote:
           | That's the exact approach I'm considering for the new engine
           | I mentioned!
           | 
           | Although that strategy enables you to store and recover the
           | state of a game, it doesn't give you the ability to inspect a
           | snapshot of that state. How can you print the card which has
           | just been played, if that data only exists as an argument in
           | the call stack of a suspended async function? In the same way
           | that you can't inspect the local variables captured by a
           | closure, mainstream languages also provide no way to inspect
           | a suspended stack frame.
           | 
           | This problem interferes with debugging, consistency checks
           | (e.g. hashing the game state to check that two clients are in
           | sync), and unit testing.
        
         | LudwigNagasena wrote:
         | My main pain point with any sort of Flux-like state management
         | is transitions [1]. The state of UI is not fully described by
         | the state of the game [2]. If I play a card, the game state can
         | be instantly updated to the next decison-making point, but in
         | reality I want to show steps of the game through animations,
         | some of which are concurrent and some of which are consecutive.
         | That usually ends up in a mess; and I've never seen someone
         | implement it nicely.
         | 
         | [1] And generally dynamic stuff like drag-n-drop, which is
         | infinitely times simpler in any other architecture than in
         | React.
         | 
         | [2] That is also true for business apps, but their animations
         | are usually so simple you can simply use CSS.
        
           | semitones wrote:
           | In my experience, the way to solve [1] and [2] is to design a
           | game state that can also _fully_ describe the state of the
           | UI, including animation cues.
        
           | Longwelwind wrote:
           | The way I wanted to implement this in my turn-based game
           | engine:
           | 
           | If you implement the deterministic update pattern to handle
           | state synchronisation you can add "event" inside the logic
           | that handles updates that pause the processing allowing your
           | animations to be played. In JS, for example:
           | async function handleUpdate(update) {             if
           | (update.type == "sell-items") {
           | this.player.inventory[update.itemId] -= 1;
           | await emitEvent("itemSold");
           | this.player.money += 10;                      await
           | emitEvent("moneyGain");             }         }
           | 
           | Server-side, "emitEvents" would be a no-op. Everything would
           | resolve synchronously.
           | 
           | Client-side, the UI can listen to those events to pause the
           | updating of the game state to see the intermediary state of
           | the game and play animations. When the animation is done, it
           | can resolve the promise, resuming the game updating logic.
           | 
           | If an update arrives while an update is being handled, it can
           | be queued so it can be played after the current update
           | finishes.
        
           | sjrd wrote:
           | The way I did this was to design a more-or-less monadic
           | container `Result<A>` for all my game logic functions. It
           | batches a sequence of animation steps with a result. It can
           | also model error conditions (like not having enough resources
           | for example). I can then instantiate it any concrete result
           | type, such as a full game state or just the result of
           | individual computations. It was very nice to concisely write
           | complicated game logic with animations while retaining the
           | happy path.
           | 
           | https://github.com/sjrd/barrage/blob/main/src/main/scala/be/.
           | ..
        
             | LudwigNagasena wrote:
             | Interesting. Unfortunately, your repo seems to be private.
        
               | sjrd wrote:
               | Oh shoot, yes. I have imitation copies of the original
               | game graphics in there, and so I can't make it public
               | without violating copyright of their assets. :-(
               | 
               | Here is a public gist with the `Result` data structure,
               | as well a good portion of the file handling all the game
               | mechanics, which should show it gets used. https://gist.g
               | ithub.com/sjrd/34fe234d1b6232cf42ffda5d23292d3...
        
           | nkrisc wrote:
           | I toyed with an approach once that separated animations from
           | game state updates.
           | 
           | Every player action could cause a cascade of updates, which
           | would all be resolved "instantly" to the point no more
           | cascaded updates were left to be processed.
           | 
           | While this is happening, any update that includes an
           | animation pushes that to an "animation stack", then the
           | animations are played back one by one to show the player what
           | happened. In this animation state most input in disabled and
           | the game is effectively on hold until the animations complete
           | (or are skipped by the player).
           | 
           | The "animations" were basically commands that the Model used
           | to update the View, just with the option to apply them one by
           | one over time.
        
         | bbminner wrote:
         | Yep, that's the exact issue I wanted to address with my own
         | twist on the idea of an online boardgame engine - I was trying
         | to actually persist the callstack of an async wasm vm function
         | (game loop) execution into a database in rust. It is working in
         | a sense that you can implement battle ships or tick tack toe,
         | but I did not quite finish it. Happy to still make repo public
         | if helpful.
         | 
         | To be more specific, async wasm function was implemented as a
         | poll loop sync function exported to the caller, there was (at
         | the time) no way to move wasm mv memory, so it was persisted
         | while the game was live and replayed from a message log stored
         | in a db after/if preemption.
        
       | billnreed wrote:
       | I've seen this engine before and thought it was really cool!
       | 
       | I've been playing around with writing my own turn-based game
       | engine with TypeScript: https://github.com/snowbillr/turn-based-
       | game-engine
       | 
       | It's a WIP still, but what's really been the struggle for me is
       | coming up with a data structure and traversal algorithm for the
       | turn order. I wanted that to be extremely configurable by whoever
       | uses the library.
       | 
       | ```
       | 
       | engine.defineFlow((f) => {                 f.node({
       | actions: f.actions(WelcomeMessage),       })            f.node(
       | {           actions: f.actions(RoundStart),           cleanups:
       | f.cleanups(RoundEnd, TestLog),         },
       | players.map(player => f.node({           playerId: player.id,
       | actions: f.actions(TurnStart),           cleanups:
       | f.cleanups(TurnEnd),         })),       )
       | 
       | });
       | 
       | ```
       | 
       | This example shows a TicTacToe game defined like this:
       | 
       | ```
       | 
       | - welcome
       | 
       | - round                 - player 1 turn            - player 2
       | turn
       | 
       | ```
       | 
       | What I ended up with was essentially a tree that's traversed
       | depth-first to enter each node, and then goes back up the same
       | traversal path until a sibling node is found to dive into.
       | 
       | That lets the user define rounds/turns/phases as children of each
       | other in whatever shape they want.
       | 
       | It's been a real fun project!
        
       | DominikPeters wrote:
       | Is there a simple demo that one can test? I see a tutorial about
       | tic tac toe, but the result doesn't seem to be hosted anywhere.
        
         | freetonik wrote:
         | The tutorial page[1] has a link to open an interactive sandbox
         | with a TicTacToe example. The link is titled "Edit in
         | CodeSandbox".
         | 
         | 1. https://boardgame.io/documentation/#/tutorial
        
       | tasuki wrote:
       | It's really cool that it has a MCTS bot built-in!
        
       | throw94838211 wrote:
       | I tried to use this before, but many parts didn't really work
       | right, lots of conflict between dependencies, especially the
       | server parts. I had to abandon what I wanted to do with it. Shame
       | because many ideas were interesting, but felt it was a bit
       | untested.
        
       | mvolfik wrote:
       | 10 months ago, there was also Boardzilla
       | (https://www.boardzilla.io/) posted here:
       | https://news.ycombinator.com/item?id=39180953 . Curious to see
       | how these two compare
        
       | Lucasoato wrote:
       | If anybody knows of any reference, article, book to study and
       | implement turn-based engines like this, please add them under
       | this thread.
        
       ___________________________________________________________________
       (page generated 2024-12-20 23:00 UTC)