One of my spare-time projects over the last few weeks has been a browser-based, pure HTML and SVG implementation of the Go board game. This has reached a usable state (although definitely still pre-alpha) and is worth some reflection on the architectural implicatons.
My starting point was that I wanted to build the game using a Django / Python back-end and HTML / AJAX / SVG front-end. The project came out of my experimenting with Django and I am considering other types of game but Go was a good starting point.
A more commercially realistic approach would be to build a Java or Flash client but I wanted to see how much could be achieved using SVG. Also, I dislike Flash (due to its over-use) and I am tired of problems with Java installers.
The two drawbacks that I have found with this approach are browser support and the lack of drag and drop.
My early experiments with IE and Konqueror show poor SVG support so I just worked in Firefox for now. If I persist with the project longer term then an alternative would be to draw the board and pieces server-side into a PNG file and send that combined with a client-side image map. This would be more work on the server side and would require more data transfer but I would quite enjoy creating a basic PNG library in Python.
SVG includes onClick events so I was able to put hidden items on the points to be selected. This works fine for Go but would not work in, for example, chess where a drag and drop action would be desirable. It would be possible to click once to seect the piece and then again to select the destination but I will have to try it out to see if it feels too clumsy.
I was deliberately working with a Django back-end intended for ease of deploymen so I wanted no non-standard server features. this proved interesting as what I initially considered to be a clumsy architecture turns out to have some attractive aspects.
Dedicated server versus HTTP transactions
If I had not been basing the design on Django then I would have started with a server that kept each active game in memory and applied moves as they were received. As I was using Django, each browser action was totally separate and so the POST request to play a move requires the game to be loaded from the database, the move applied and a response sent to the browser with captured stones etc. and the game saved in an updated form.
In a quick-moving game, having to load and save the game for each move is an overhead but when a longer-term view is taken the Django approach (really , the generic web-server approach) has robustness advantages. With a server running direct connections to clients I would have to work out what to do if a connection went down - how could a client re-connect and resume their game. Also, what if players want to pause a game overnight? Basing the whole approach on an atomic move basis automatically handles these aspects and also provides a re-play feature almost for free.
Another aspect that was less convenient was trying to implement server-push. I want to be able to update player A's browser when player B makes a move (I also included a chat pane in the game which has the same requirement). In a dedicated server, I would use a long-standing read from the client and would provide a practically instant response. This is not really workable using an HTTP server.
In theory, I could use a dedicated HTTP GET request to fetch updates and have the server delay replying until there is event data to return. On the browser side this should work fine. Unfortunately, it has two problems on the server side
Firstly, it means that each game would involve two dedicated requests outstanding at all times in addition to the transient requests to fetch game state, post moves etc. With conventional HTTP servers this would likely cause a scalability problem as each connection requires resources and servers are configured to limit connections.
Secondly, HTTP servers running Django or other CGI frameworks keep each request separate (for very good reasons). Therefore, if I had a pending request for player A and a separate POST from player B it would be tricky to communicate between those requests. This might not be insuperable (and would be trivial in a dedicated server) but I did not investigate further given the resource issues.
This means that my event handling is based on poll-based requests that mostly return no new event data. This is fine in terms of server resources but it does consume network bandwidth and means that the responses can be delayed for a few seconds. This type of problem has been met by a lot of other people (look up Comet in Wikipedia for example) and I expect that I will return to it to investigate further at some time. For example, at what point does the server load from repeated requests with no events outweigh the resource cost from outstanding requests and how can I pass events from one request to another (maybe the new Django signals will help)?