home *** CD-ROM | disk | FTP | other *** search
- # -*- coding: utf-8 -*-
- import xml.sax.handler
-
- "<UPDATE TYPE='player' ACTION='delete' ROOM='40' TOROOM='-1'>"
- "<PLAYER ID='kostaya'/>"
- "</UPDATE>"
-
- "<UPDATE TYPE='table' ACTION='leave' ROOM='40'>"
- "<TABLE ID='1' SEATS='2'>"
- "<SEAT NUM='0' TYPE='player'>kostaya</SEAT>"
- "</TABLE>"
- "</UPDATE>"
-
- "<UPDATE TYPE='table' ACTION='status' ROOM='40'>"
- "<TABLE ID='1' STATUS='3' SEATS='2'/>"
- "</UPDATE>"
-
- "<UPDATE TYPE='table' ACTION='delete' ROOM='40'>"
- "<TABLE ID='1' STATUS='-1' SEATS='2'/>"
- "</UPDATE>"
-
- class ParserFeedback:
- def onResult(self, action, code):
- pass
-
- def onMOTD(self, motd):
- pass
-
- def onChat(self, chatType, sender, text):
- pass
-
- def onJoin(self, tableId, isSpectator):
- pass
-
- def onLeave(self, reason):
- pass
-
- def gameAdded(self, gameId, name, version, author, url, numPlayers, protocol_engine, protocol_version):
- pass
-
- def roomAdded(self, roomId, gameId, name, description, nPlayers):
- pass
-
- def roomPlayersUpdate(self, roomId, nPlayers):
- pass
-
- def tableAdded(self, roomId, tableId, gameId, status, nSeats, description):
- pass
-
- def tableStatusChanged(self, tableId, status):
- pass
-
- def seatChanged(self, roomId, tableId, seatId, seatType, user):
- pass
-
- def tableRemoved(self, tableId):
- pass
-
- def onPlayerList(self, room, players):
- pass
-
- def playerAdded(self, name, playerType, tableId, perms, lag, room, fromRoom):
- pass
-
- def playerRemoved(self, name, room, toRoom):
- pass
-
- class GGZParser:
- """
- """
- parent = None
-
- parser = None
-
- def startElement(self, name, attributes):
- if self.parser is not None:
- self.parser.startElement(name, attributes)
- return
- try:
- method = getattr(self, 'start_%s' % name.lower())
- except AttributeError:
- print 'Unknown start element: %s' % name
- else:
- method(attributes)
-
- def characters(self, data):
- if self.parser is not None:
- self.parser.characters(data)
- return
- self.handle_data(data)
-
- def endElement(self, name):
- if self.parser is not None:
- self.parser.endElement(name)
- return
- try:
- method = getattr(self, 'end_%s' % name.lower())
- except AttributeError:
- print 'Unknown end element: %s' % name
- else:
- method()
-
- def push(self, parser, attributes):
- assert(self.parser is None)
- parser.attributes = attributes
- parser.decoder = self.decoder
- parser.parent = self
- self.parser = parser
-
- def pop(self):
- assert(self.parent is not None)
- parser = self.parent.parser
- self.parent.parser = None
- self.parent.childFinished(parser)
-
- def handle_data(self, data):
- pass
-
- def childFinished(self, parser):
- pass
-
- class GameParser(GGZParser):
- """
- <GAME ID='24' NAME='TicTacToe' VERSION='0.0.9'>
- <PROTOCOL ENGINE='TicTacToe' VERSION='4'/>
- <ALLOW PLAYERS='2' BOTS='1' SPECTATORS='true' PEERS='false'/>
- <BOT NAME='Alfred' CLASS='easy'/>
- <BOT NAME='Tarantula' CLASS='hard'/>
- <ABOUT AUTHOR='Brent Hendricks' URL='http://www.ggzgamingzone.org/games/tictactoe/'/>
- <DESC>Simple GGZ game module for playing Tic-Tac-Toe</DESC>
- </GAME>
- """
-
- def __init__(self):
- self.bots = []
-
- def start_desc(self, attributes):
- self.push(DescriptionParser(), attributes)
-
- def start_protocol(self, attributes):
- self.push(GameProtocolParser(), attributes)
-
- def start_allow(self, attributes):
- self.push(GameAllowParser(), attributes)
-
- def start_bot(self, attributes):
- self.push(GameBotParser(), attributes)
-
- def start_about(self, attributes):
- self.push(GameAboutParser(), attributes)
-
- def end_game(self):
- self.gameId = self.attributes['ID']
- self.name = self.attributes['NAME']
- self.version = self.attributes['VERSION']
- self.pop()
-
- def __str__(self):
- return 'GGZ Game id=%s protocol=%s (%s) description=%s' % (self.gameId, repr(self.protocol.engine), self.protocol.version, repr(self.description))
-
- class DescriptionParser(GGZParser):
- """
- <DESC>Simple GGZ game module for playing Tic-Tac-Toe</DESC>
- """
-
- def handle_data(self, data):
- self.parent.description = data
-
- def end_desc(self):
- self.pop()
-
- class GameProtocolParser(GGZParser):
- """
- <PROTOCOL ENGINE='TicTacToe' VERSION='4'/>
- """
-
- def end_protocol(self):
- self.parent.protocol = self
- self.engine = self.attributes['ENGINE']
- self.version = self.attributes['VERSION']
- self.pop()
-
- class GameAllowParser(GGZParser):
- """
- <ALLOW PLAYERS='2' BOTS='1' SPECTATORS='true' PEERS='false'/>
- """
-
- def end_allow(self):
- self.parent.allow = self
- self.numPlayers = self.attributes['PLAYERS']
- self.pop()
-
- class GameBotParser(GGZParser):
- """
- <BOT NAME='Alfred' CLASS='easy'/>
- <BOT NAME='Tarantula' CLASS='hard'/>
- """
-
- def end_bot(self):
- self.parent.bots.append(self)
- self.name = self.attributes['NAME']
- self.difficulty = self.attributes['CLASS']
- self.pop()
-
- class GameAboutParser(GGZParser):
- """
- <ABOUT AUTHOR='Brent Hendricks' URL='http://www.ggzgamingzone.org/games/tictactoe/'/>
- """
-
- def end_about(self):
- self.parent.about = self
- self.author = self.attributes['AUTHOR']
- self.url = self.attributes['URL']
- self.pop()
-
- class RoomParser(GGZParser):
-
- def start_desc(self, attributes):
- self.push(DescriptionParser(), attributes)
-
- def end_room(self):
- self.pop()
-
- def __str__(self):
- return 'GGZ Room id=%s game=%s description=%s' % (self.roomId, self.game, repr(self.description))
-
- class PlayerParser(GGZParser):
-
- def end_player(self):
- self.pop()
-
- def __str__(self):
- return 'GGZ Player id=%s type=%s table=%s perms=%s lag=%s' % (self.id, self.type, self.table, self.perms, self.lag)
-
- class TableSeatParser(GGZParser):
-
- def __init__(self):
- self.label = ''
-
- def handle_data(self, data):
- self.label += data
-
- def end_seat(self):
- self.pop()
-
- class TableParser(GGZParser):
-
- def __init__(self):
- self.seats = []
- self.description = ''
-
- def start_desc(self, attributes):
- self.push(DescriptionParser(), attributes)
-
- def start_seat(self, attributes):
- self.push(TableSeatParser(), attributes)
-
- def childFinished(self, parser):
- if isinstance(parser, TableSeatParser):
- self.seats.append(parser)
-
- def end_table(self):
- self.pop()
-
- class GameListParser(GGZParser):
-
- def __init__(self):
- self.games = []
-
- def start_game(self, attributes):
- self.push(GameParser(), attributes)
-
- def childFinished(self, parser):
- self.games.append(parser)
-
- def end_list(self):
- for g in self.games:
- self.decoder.feedback.gameAdded(g.gameId, g.name, g.version, g.about.author, g.about.url, g.allow.numPlayers,
- g.protocol.engine, g.protocol.version)
- self.pop()
-
- class TableListParser(GGZParser):
-
- def __init__(self):
- self.tables = []
-
- def start_table(self, attributes):
- self.push(TableParser(), attributes)
-
- def childFinished(self, parser):
- self.tables.append(parser)
-
- def end_list(self):
- for t in self.tables:
- room = self.attributes['ROOM']
- tableId = t.attributes['ID']
- gameId = t.attributes['GAME']
- status = t.attributes['STATUS']
- nSeats = int(t.attributes['SEATS'])
- self.decoder.feedback.tableAdded(room, tableId, gameId, status, nSeats, t.description)
- for seat in t.seats:
- self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], seat.label)
- self.pop()
-
- class PlayerListParser(GGZParser):
-
- def __init__(self):
- self.players = []
-
- def start_player(self, attributes):
- self.push(PlayerParser(), attributes)
-
- def childFinished(self, playerParser):
- playerParser.name = playerParser.attributes['ID']
- playerParser.type = playerParser.attributes['TYPE']
- playerParser.tableId = playerParser.attributes['TABLE']
- try:
- playerParser.perms = playerParser.attributes['PERMS']
- except KeyError:
- playerParser.perms = ''
- playerParser.lag = playerParser.attributes['LAG']
- self.players.append(playerParser)
-
- def end_list(self):
- self.decoder.feedback.onPlayerList(self.attributes['ROOM'], self.players)
- self.pop()
-
- class RoomListParser(GGZParser):
-
- def __init__(self):
- self.rooms = []
-
- def start_room(self, attributes):
- self.push(RoomParser(), attributes)
-
- def childFinished(self, parser):
- parser.roomId = parser.attributes['ID']
- parser.name = parser.attributes['NAME']
- parser.game = parser.attributes['GAME']
- parser.nPlayers = int(parser.attributes['PLAYERS'])
- self.rooms.append(parser)
-
- def end_list(self):
- for r in self.rooms:
- self.decoder.feedback.roomAdded(r.roomId, r.game, r.name, r.description, r.nPlayers)
- self.pop()
-
- class ServerOptionsParser(GGZParser):
-
- def end_options(self):
- self.pop()
-
- class ServerParser(GGZParser):
-
- def start_options(self, attributes):
- self.push(ServerOptionsParser(), attributes)
-
- def end_server(self):
- self.decoder.feedback.onConnected()
- self.pop()
-
- class MOTDParser(GGZParser):
-
- def __init__(self):
- self.motd = ''
-
- def handle_data(self, data):
- self.motd += data
-
- def end_motd(self):
- self.decoder.feedback.onMOTD(self.motd)
- self.pop()
-
- class RoomUpdateParser(GGZParser):
-
- def __init__(self):
- pass
-
- def start_room(self, attributes):
- self.push(RoomParser(), attributes)
-
- def childFinished(self, parser):
- action = self.attributes['ACTION'].lower()
- if action == 'players':
- roomId = parser.attributes['ID']
- nPlayers = int(parser.attributes['PLAYERS'])
- self.decoder.feedback.roomPlayersUpdate(roomId, nPlayers)
- else:
- print 'Unknown player update action %s' % action
-
- def end_update(self):
- self.pop()
-
- class PlayerUpdateParser(GGZParser):
-
- def start_player(self, attributes):
- self.push(PlayerParser(), attributes)
-
- def childFinished(self, parser):
- action = self.attributes['ACTION'].lower()
- if action == 'add':
- name = parser.attributes['ID']
- playerType = parser.attributes['TYPE']
- table = parser.attributes['TABLE']
- try:
- perms = parser.attributes['PERMS']
- except KeyError:
- perms = ''
- lag = parser.attributes['LAG']
- roomId = self.attributes['ROOM']
- fromRoomId = self.attributes['FROMROOM']
- self.decoder.feedback.playerAdded(name, playerType, table, perms, lag, roomId, fromRoomId)
- elif action == 'lag':
- playerId = parser.attributes['ID']
- lag = parser.attributes['LAG']
- print 'Player %s lag changed to %s' % (playerId, lag)
- elif action == 'join':
- pass
- elif action == 'leave':
- pass
- elif action == 'desc':
- pass
- elif action == 'seat':
- pass
- elif action == 'delete':
- playerId = parser.attributes['ID']
- room = self.attributes['ROOM']
- toRoom = self.attributes['TOROOM']
- self.decoder.feedback.playerRemoved(playerId, room, toRoom)
- else:
- print 'Unknown player update action %s' % action
-
- def end_update(self):
- self.pop()
-
- class TableUpdateParser(GGZParser):
-
- def __init__(self):
- self.table = None
-
- def start_table(self, attributes):
- self.push(TableParser(), attributes)
-
- def childFinished(self, parser):
- self.table = parser
-
- def end_update(self):
- room = self.attributes['ROOM']
- action = self.attributes['ACTION']
- if action == 'add':
- "<UPDATE TYPE='table' ACTION='add' ROOM='3'>"
- " <TABLE ID='1' GAME='30' STATUS='1' SEATS='2'>"
- " <DESC></DESC>"
- " <SEAT NUM='0' TYPE='reserved'>bob</SEAT>"
- " <SEAT NUM='1' TYPE='bot'/>"
- " </TABLE>"
- "</UPDATE>"
- room = self.attributes['ROOM']
- tableId = self.table.attributes['ID']
- gameId = self.table.attributes['GAME']
- status = self.table.attributes['STATUS']
- nSeats = int(self.table.attributes['SEATS'])
- description = self.table.description
- # FIXME: Include the seats with the add event somehow (and other adds)
- self.decoder.feedback.tableAdded(room, tableId, gameId, status, nSeats, description)
- for seat in self.table.seats:
- self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], seat.label)
-
- elif action == 'join':
- "<UPDATE TYPE='table' ACTION='join' ROOM='3'>"
- " <TABLE ID='1' SEATS='2'>"
- " <SEAT NUM='0' TYPE='player'>bob</SEAT>"
- " </TABLE>"
- "</UPDATE>"
- room = self.attributes['ROOM']
- tableId = self.table.attributes['ID']
- for seat in self.table.seats:
- self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], seat.label)
-
- elif action == 'leave':
- "<UPDATE TYPE='table' ACTION='leave' ROOM='3'>"
- " <TABLE ID='1' SEATS='2'>"
- " <SEAT NUM='0' TYPE='player'>bob</SEAT>"
- " </TABLE>"
- "</UPDATE>"
- room = self.attributes['ROOM']
- tableId = self.table.attributes['ID']
- for seat in self.table.seats:
- self.decoder.feedback.seatChanged(room, tableId, seat.attributes['NUM'], seat.attributes['TYPE'], '') # seat.label)???
-
- elif action == 'status':
- "<UPDATE TYPE='table' ACTION='status' ROOM='3'>"
- " <TABLE ID='1' STATUS='3' SEATS='2'/>"
- "</UPDATE>"
- self.decoder.feedback.tableStatusChanged(self.table.attributes['ID'], self.table.attributes['STATUS'])
-
- elif action == 'delete':
- "<UPDATE TYPE='table' ACTION='delete' ROOM='3'>"
- " <TABLE ID='1' STATUS='-1' SEATS='2'/>"
- "</UPDATE>"
- self.decoder.feedback.tableRemoved(self.table.attributes['ID'])
-
- else:
- print 'Unknown table update action: %s' % action
-
- self.pop()
-
- "<UPDATE TYPE='table' ACTION='add' ROOM='13'>"
- " <TABLE ID='1' GAME='24' STATUS='1' SEATS='4'>"
- " <DESC>I play alone...</DESC>"
- " <SEAT NUM='0' TYPE='reserved'>helg</SEAT>"
- " <SEAT NUM='1' TYPE='bot'/>"
- " <SEAT NUM='2' TYPE='bot'/>"
- " <SEAT NUM='3' TYPE='bot'/>"
- " </TABLE>"
- "</UPDATE>"
- "<UPDATE TYPE='table' ACTION='join' ROOM='13'>"
- " <TABLE ID='1' SEATS='4'>"
- " <SEAT NUM='0' TYPE='player'>helg</SEAT>"
- " </TABLE>"
- "</UPDATE>"
-
- class ChatParser(GGZParser):
-
- def __init__(self):
- self.text = ''
-
- def handle_data(self, data):
- self.text += data
-
- def end_chat(self):
- chatType = self.attributes['TYPE']
- sender = self.attributes['FROM']
- self.decoder.feedback.onChat(chatType, sender, self.text)
- self.pop()
-
- class ResultParser(GGZParser):
-
- def start_list(self, attributes):
- t = attributes['TYPE'].lower()
- if t == 'player':
- self.push(PlayerListParser(), attributes)
- elif t == 'room':
- self.push(RoomListParser(), attributes)
- elif t == 'game':
- self.push(GameListParser(), attributes)
- elif t == 'table':
- self.push(TableListParser(), attributes)
- else:
- print 'Unknown list: %s' % t
-
- def end_result(self):
- action = self.attributes['ACTION']
- code = self.attributes['CODE']
- self.decoder.feedback.onResult(action, code)
- self.pop()
-
- class JoinParser(GGZParser):
-
- def end_join(self):
- tableId = self.attributes['TABLE']
- isSpectator = self.attributes['SPECTATOR'] == 'true'
- self.decoder.feedback.onJoin(tableId, isSpectator)
- self.pop()
-
- class LeaveParser(GGZParser):
- "<LEAVE REASON='gameover'/>"
-
- def end_leave(self):
- reason = self.attributes['REASON']
- self.decoder.feedback.onLeave(reason)
- self.pop()
-
- class SessionParser(GGZParser):
-
- def start_server(self, attributes):
- self.push(ServerParser(), attributes)
-
- def start_motd(self, attributes):
- self.push(MOTDParser(), attributes)
-
- def start_update(self, attributes):
- t = attributes['TYPE'].lower()
- if t == 'room':
- self.push(RoomUpdateParser(), attributes)
- elif t == 'player':
- self.push(PlayerUpdateParser(), attributes)
- elif t == 'table':
- self.push(TableUpdateParser(), attributes)
- else:
- print 'Unknown update type: %s' % t
-
- def start_join(self, attributes):
- self.push(JoinParser(), attributes)
-
- def start_leave(self, attributes):
- self.push(LeaveParser(), attributes)
-
- def start_result(self, attributes):
- self.push(ResultParser(), attributes)
-
- def start_chat(self, attributes):
- self.push(ChatParser(), attributes)
-
- def start_ping(self, attributes):
- self.decoder.feedback.send("<PONG/>\n")
-
- def end_ping(self):
- pass
-
- def end_session(self):
- self.decoder.feedback.onSessionEnded()
- pass
-
- class BaseParser(GGZParser):
-
- def __init__(self, decoder):
- self.decoder = decoder
-
- def start_session(self, attributes):
- self.push(SessionParser(), attributes)
-
- class Decoder(xml.sax.handler.ContentHandler):
-
- def __init__(self, feedback):
- xml.sax.handler.ContentHandler.__init__(self)
- self.feedback = feedback
- self.parser = None
- self.xparser = xml.sax.make_parser()
- self.handler = BaseParser(self)
- self.xparser.setContentHandler(self)
-
- def startElement(self, name, attributes):
- self.handler.startElement(name, attributes)
-
- def characters(self, data):
- self.handler.characters(data)
-
- def endElement(self, name):
- self.handler.endElement(name)
-
- def feed(self, data):
- """Feed data into the decoder.
-
- 'data' is the raw data to feed.
-
- Returns the next block of data to process, keep feeding until '' is returned.
- """
- index = data.find('\n')
- if index < 0:
- index = len(data) - 1
-
- chunk = data[:index+1]
- try:
- self.xparser.feed(chunk)
- except xml.sax.SAXParseException:
- print 'Invalid XML: %s' % repr(chunk)
- return data[index+1:]
-
- if __name__ == '__main__':
- import chess
-
- class F:
-
- def onSeat(self, seatNum, version):
- print ('onSeat', seatNum, version)
-
- def onPlayers(self, whiteType, whiteName, blackType, blackName):
- print ('onPlayers', whiteType, whiteName, blackType, blackName)
-
- def onTimeRequest(self):
- print ('onTimeRequest',)
-
- def onSetTime(self, time):
- print ('onSetTime', time)
-
- def onStart(self):
- print ('onStart',)
-
- def onMove(self, move):
- print ('onMove', move)
-
- f = F()
- d = chess.Chess(f);
-
- data = '\x01\x01\x06' # Seat seat=1 version=6
- for c in data:
- d.decode(c)
-
- data = '\x02\x03\x00\x00\x00\x0eglchess-test2\x00\x03\x00\x00\x00\x0dglchess-test\x00' # players type1=03 name1=glchess-test2 type2=03 name2=glchess-test
- for c in data:
- d.decode(c)
-
- data = '\x04\x00\x00\x00\x00' # rsp time time=0
- for c in data:
- d.decode(c)
-
- d.decode('\x05') # start
-
- data = '\x07\x00\x00\x00\x05F2F4\x00' # move move=F2F4
- for c in data:
- d.decode(c)
-
- data = '\x0a\x00\x00\x00\x00\x00\x00\x00\x00' # update
- for c in data:
- d.decode(c)
-