Advice on writing a scalable real time turn based strategy game using websockets and node.js

I'm planning to write a real time turn based strategy game server ontop of node.js using websockets. I will be catering to modern browsers with good html5 support and am not too concerned with backwards compatibility.

The games served will each be played/observed by a small number of players at a time (say 2-10) and will have a clock timer as used in chess and as implemented at www.chess.com. The timed games will last an hour at most & there may also be the option of playing non-timed games.

The servers will take care of the players' ratings, players' friend lists, as well as managing running/finished game state, and running the game clocks. The game state will just be a bit of json, and will be a few kilobytes at most per game.

One constraint is that all of the actual game logic must take place on the clients, not on my servers. Because of this I need a mechanism by which if a client signals an illegal move, either because it or its opponent is malfunctioning/malicious, then an unrelated client or clients (i.e. somebody else using my site) will have the game state loaded up into their browser in the background and the dispute will be settled there.

That about sums up my requirements.

This is not a toy project, and I am hoping to have many users, so I would like to think about backend architecture and scalability up front. I am not particularly knowledgeable about node.js or website deployment in general, so any advice or insights vis a vis architecture, technologies/libraries, scalability/proxying/load-balancing, how to implement the clock and deal with latency issues, where/how to store game state, etc, much appreciated.

Node.js and it's popular libraries are written with scalability in mind, so… generic tools like express, mongodb/redis, socket.io will do just fine.

About client-side logic:

an unrelated client or clients (i.e. somebody else using my site) will have the game state loaded up into their browser in the background and the dispute will be settled there.

One of the great things about node.js is that it's the same javascript as in the browser. :) So you can run the same code in your server and settle any disputes there.

The first thing with any project is putting together a list of technical requirements. Here's an example based on what you've written in your post:

  1. "servers will take care of[...]" - The list of items in your post indicate you would need some sort of user login authentication mechanism.
  2. "players' ratings, players' friend lists" - These would need to be stored in some sort of database.
  3. "managing running/finished game state, running the game clocks" - Real time data processing between connected players to a running session.
  4. If you plan on storing the results from a match then you'll need to interface the real time application with the database storage.
  5. "all of the actual game logic must take place on the clients" - Did you ever see Browser Quest? Huge problem with the game is all user information is stored on the client. To gain all in game perks you just needed to manually edit the localStorage. Only thing I can think of to get around this is to code the entire game logic into the browser, then verify each move with every client connected. But that creates a problem where users could modify the logic to dispute moves that should be legal.

When you have a well defined list of technical requirements for the project then it should be a lot easier to find the libraries you're looking for. For example, socket.io is an excellent library for handling web sockets.

Is there any reason why the game code is 'untrusted'? All you should need to do is to validate the JSON input and that the move does not violate any rules. Without knowing more details, I'm not sure I can give advice on how to resolve disputes between clients, but I see no reason why the game code cannot be trusted.

This problem actually sounds similar to a paper I read on distributed collision detection and resolution, which reduces server network stress. This is accomplished by having all 'clients' vote on a future state that is predictable, where each client directly . If there is no contention, then an agreement is reached, and the game continues. If there is contention, and an agreement cannot be reached, the move is aborted.

It also gives some interesting ideas for whether or not the vote is completed 'in-time' (you may not have to handle this scenario, given that your game is turn-based).

Instead of having a move be aborted when a collision cannot be reached, you would have to write some logic to determine whether the move is valid or not. This is where it gets difficult to answer your question, as you don't seem to be able to trust anything except the server (which can't even trust the game code itself).

I think that in order to solve this issue reliably, you would likely have to go with one of your existing ideas: firing up a sandbox game on the server, asking an unrelated client (this can be unreliable), or remove one of the constraints, and ask the server directly.