0
\$\begingroup\$

I want to make a multi player card game, allowing several people to play with each other (each game session should be able to have between 5 - 10 players).

I'm doing this in Python (Django and Socket.IO).

Because you have to wait for all players to finish before you can move on to the next round, issues will arise if one player leaves his computer or is disconnected, thus leaving all the other players waiting.

To solve this, I want to give each player a time limit to act within.

If there are 1,000 games going on at the same time, and 5 players in each game, that would hypothetically mean that at one point, you could have 5,000 timers counting down at the same time (or if not timers, some other way of dealing with this issue).

What is the best way to do this in Python? Spawn loads of threads with timers? Have something more complex like a dictionary with 100 games in each dictionary, and for every second, iterate through the list and check each player? (seems a bit finicky)?

I really want to hear what the best approach to this would be.

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

This isn't so much of a Python issue as a Django issue - there are many ways in Python (and indeed most languages) of watching for a time to pass, but the problem is how you act upon it. With Django and websockets you'll need to tell it to send data down an existing websocket, and how to do that will depend on how exactly the websockets are implemented (which in turn is likely to depend on Django).

A threaded approach that is more effective than having one per timer is to have one timer thread manage all the timers. Keep a list of timers and game IDs and sort them by time, ascending. Then you only have to check the first timer to see if it's expired; if so, send a signal to that game, pop it from the list, and repeat. If the first timer has not expired, you can have that thread sleep for a while. The first complication with this approach is safely getting a timer into the thread, but you can probably use the Queue module to help there. The second complication, as hinted at in the first paragraph, is how to go from knowing a move has timed-out to actually notifying a player. You'd need some way of communicating back to the main Django thread, which is not simple, and it appears that most developers have to resort to using an external message queue. There's some discussion here: http://www.turnkeylinux.org/blog/django-celery-rabbitmq

Iterating through a list of all games and checking the timer would also work. It's unlikely to be a drain on resources unless you're doing it every millisecond. I don't know if there's any way to get Django to perform a task such as this every so often (eg. once a second) but the answers to this question are not very encouraging.

The unfortunate answer is that web applications are poorly suited to real-time systems like this. They're usually configured in a way that makes it difficult to respond at arbitrary times and the HTTP protocol makes it difficult to send that response even if you managed to form it. (This doesn't apply so much to Websockets - but unfortunately you're stuck within the structure of the traditional web application.) You might want to consider using a different server application that features a main loop and which would allow you to have more control over executing background tasks.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for that descriptive response. This gives me some direction and I can factor this into the design. \$\endgroup\$
    – user200341
    Jul 26, 2012 at 12:37
0
\$\begingroup\$

If you are going to use websockets, I wouldn't recommend django, since its not made to work with realtime applications (although this is a general problem with any wsgi application). You should use an async webserver, like tornado or twisted

Besides, tornado supports websockets natively, and i think there's a library to work with socket.io

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .