-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.py
150 lines (128 loc) · 4.83 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import os
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import sockjs.tornado
import dominion
from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)
# handles GET and POST requests
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render('index.html', error='')
def post(self):
name = self.get_argument('name')
# return to previous page if a game is already in progress, the maximum player count has been reached,
# or the specified username is already being used by another player
if GameConnection.game != None:
self.render('index.html', error='A match is already in progress, please try again later.')
elif len(GameConnection.participants) >= 4:
self.render('index.html', error='We are at maximum player count, please try again later.')
elif name in GameConnection.names:
self.render('index.html', error='That name is already taken, please try again.')
else:
self.render('dominion.html', name=name)
# handles websocket connection between the server and clients
class GameConnection(sockjs.tornado.SockJSConnection):
participants = []
names = []
game = None
coro = None
def on_open(self, info):
cls = GameConnection
cls.participants.append(self)
# messages are parsed from clients
# each message sent from the client to the server is in the format '<command>:<info>'
def on_message(self, message):
cls = GameConnection
command = message.split(':')[0]
info = message.split(':')[1]
if command == 'Open':
cls.names.append(info)
self.broadcast(cls.participants, 'Names:' + ','.join(name for name in cls.names))
elif command == 'Chat':
self.broadcast(cls.participants, message)
elif command == 'Trash':
cls = GameConnection
if cls.game._trash.is_empty():
self.send('Public:The trash is empty.')
else:
self.send('Public:Cards in trash are ' + ', '.join([card.name for card in cls.game._trash]) + '.')
# once a game is started, an instance of the dominion class is created
# all relevant information is presented to each player
elif command == 'Start':
self.broadcast(cls.participants, 'Start: (blank)')
cls.game = dominion.Dominion(cls.names)
cls.coro = cls.game.game_loop()
ret = next(cls.coro)
self.broadcast(cls.participants, ret)
self.display_supply()
self.display_curses()
self.display_trash()
self.display_hands()
self.display_stats()
self.display_decks()
self.display_discards()
else:
ret = cls.coro.send(message)
self.display_supply()
self.display_curses()
self.display_trash()
self.display_hands()
while cls.game.info_list != []:
msg = cls.game.info_list.pop(0)
self.broadcast(cls.participants, msg)
if msg.split(':')[0] == 'End Game':
cls.game = None
return
if ret: self.broadcast(cls.participants, ret)
self.display_stats()
self.display_decks()
self.display_discards()
def on_close(self):
cls = GameConnection
idx = cls.participants.index(self)
cls.participants.pop(idx)
rage_quitter = cls.names.pop(idx)
self.broadcast(cls.participants, 'Names:' + ','.join(name for name in cls.names))
if cls.participants == []:
cls.game = None
self.broadcast(cls.participants, 'Leave:{} has left the game.'.format(rage_quitter))
# various functions that grab infomation from the dominion class and sends it to client
def display_supply(self):
cls = GameConnection
self.broadcast(cls.participants, 'Supply:' + cls.game.supply_string())
def display_curses(self):
cls = GameConnection
self.broadcast(cls.participants, 'Curses:' + cls.game.curse_string())
def display_trash(self):
cls = GameConnection
self.broadcast(cls.participants, 'Trash:' + cls.game.trash_string())
def display_hands(self):
cls = GameConnection
for idx, participant in enumerate(cls.participants):
participant.send('Hand:' + cls.game.hand_string(idx))
def display_discards(self):
cls = GameConnection
for idx, participant in enumerate(cls.participants):
participant.send('Discard:' + cls.game.discard_string(idx))
def display_stats(self):
cls = GameConnection
for idx, participant in enumerate(cls.participants):
participant.send('Stats:' + cls.game.stats_string(idx))
def display_decks(self):
cls = GameConnection
for idx, participant in enumerate(cls.participants):
participant.send('Deck:' + cls.game.deck_string(idx))
if __name__ == '__main__':
GameRouter = sockjs.tornado.SockJSRouter(GameConnection, '/router')
tornado.options.parse_command_line()
app = tornado.web.Application(
handlers=[(r'/', IndexHandler)] + GameRouter.urls,
template_path=os.path.join(os.path.dirname(__file__), 'templates'),
static_path=os.path.join(os.path.dirname(__file__), 'static'),
debug=True
)
app.listen(int(os.environ.get('PORT', 8000)))
tornado.ioloop.IOLoop.instance().start()