#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
This module implement a simple wrapper for output messages (send by clients or server).
It respect the semantics about the communications (this document is available here `specification_slides <../../specification_slides.pdf>`_).
Basically, it a collection of mini pretty-printer.
It also provides the function *try_pickling*, to save datas from binary files (load them with ParseMessageIn.try_unpickling).
"""
__author__='Lilian BESSON (mailto:lilian.besson[AT]normale.fr)' # Automatically update with update__date__.sh, a Naereen Corp. (c) bash script.
__version__='1.7a'
__date__='mar. 19/02/2013 at 01h:03m:24s ' #: The date of the file, automatically update with update__date__.sh, a Naereen Corp. (c) bash script.
#: This can be erased by the module Constants to modify the global verbosity of this module
PRINT_ALL_PARSEOUT = True
#1###############
# Usual Modules #
#import pprint #: Use pprint to print the data which are pickling with pickle.
try:
import cPickle as pickle
except:
import pickle
#2#################
# Project Modules #
import ANSIColors # ANSIColors.py : just some colors definition.
from Constants import * # Constants.py : all the constants
# About Pickling
#################
[docs]def try_pickling(data, info="(no info about the pickling was given)", verb=True, fn=filename_pickling):
""" Save the datas *data* to the file *fn*.
This file will be **erase** if present, so be cautious. The file *fn* can then be load with ParseMessageOut.try_pickling.
The goal of *info* is to say what variables are picked (see the examples below).
If *verb* is here, this function print a log saying from which file datas are being read.
This function doesn't handle exception, so be prudent with it.
Example:
>>> from ParseMessageIn import try_unpickling
>>> a, b, c = 0, 2.0, u"ok !" # Make a tuple.
>>> try_pickling((a,b,c)) # Save the tuple, in the default file (.datas_saved_by_picked_python.pkl).
>>> aa, bb, cc = try_unpickling(info="aa, bb, cc") # Load the tuple from the default file, and save it to (aa, bb, cc).
Warning:
.. warning::
All datas cannot be picked and upicked.
Fore more details, see directly the documentation of the **pickle** module.
"""
if verb:
ANSIColors.printc('\t/pickle/ <blue>Saving<white> datas %s, to <u>%s<U>...' % (info, fn))
try:
output = open(fn, 'wb')
# Pickle dictionary using protocol -1.
pickle.dump(data, output, -1)
output.close()
except Exception as e:
if verb:
ANSIColors.printc('\t/pickle/ <red>failed<white> when saving to <u>%s<U>\n\t/pickle/ Cause : %s.' % (fn, e))
raise e
return False
if verb:
ANSIColors.printc('\t/pickle/ <green>succed<white> when saving to <u>%s<U>.' % fn)
return True
[docs]def str_of_state(state):
""" str_of_state(state) -> '0', '1', or '2'.
The simpliest conversion from a state (Board.State) to a string.
Returned values:
* '0' for an empty spot.
* '1' for a destructible wall.
* '2' for a undestructible wall."""
if state.wall:
if state.destr: return '1'
else: return '2'
else: return '0'
[docs]def str_of_players(board, pl):
""" str_of_players(board, pl) -> ";p.pseudo ,p.x,p.y" sequence
Simply return a string representing the list of Player.Player associated with their position.
All found players *have to be* in the list [pl].
.. warning::
Take care of the **space** between pseudo and the first *;*.
"""
ANSIColors.printc("<warning> <neg><magenta> Generating the string to seng my list of players....<reset><white> ......")
res = ""
res_list = ["0"] * len(pl)
for i, j, spot in board: #: ok.
if spot.players:
for p in spot.players:
if p in pl:
#: res += ";%s,%i,%i" % (p.pseudo, p.x, p.y)
res_list[ p.id ] = ";%s,%i,%i" % (p.pseudo, p.x, p.y)
ANSIColors.printc("<warning> <magenta> I have the player <white>[%s], with id=<u>%i<U>, and he/she will be sent as : <neg>%s<Neg>. " % (p, p.id, res_list[ p.id ] ) )
for s in res_list:
res += s
# Now, we are sure that we are sending the players in a good order.
#
# And this is maybe simpler !
#: # Ok, this is like in our formal semantics.
#: for p in pl:
#: res += ";%s,%i,%i" % (p.pseudo, p.x, p.y)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_players<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_newplayer(player):
""" str_of_newplayer(player) -> "NEW_PLAYER(player.pseudo)"
Sent message by a new player when he try to connect to the server.
Contains the pseudo of the player.
Can be unpack with ParseMessageIn.newplayer_of_str.
"""
res = "NEW_PLAYER(%s)" % (player.pseudo)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_newplayer<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_newcolor(player):
""" str_of_newcolor(player) -> "color=player.color"
Sent message by a new player to annouce his color.
Currently, not used by the server.
Can be unpack with ParseMessageIn.newplayer_of_str.
"""
res = "color=%s" % (player.color)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_newcolor<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_move(move_to_send):
""" Return a string representing an action (a move or dropping a bomb).
The *move_to_send* string is one of 'BOMB', 'LEFT', 'RIGHT', 'UP', 'DOWN'.
From the client to the server.
Returned value :
* PLANT_BOMB.
* MOVE_LEFT.
* MOVE_RIGHT.
* MOVE_UP.
* MOVE_DOWN.
"""
if move_to_send=="BOMB":
res = "PLANT_BOMB\n"
else:
res = "MOVE_%s\n" % move_to_send
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_move<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_board_and_player(board, pl):
""" Convert a game state (composed of a board [board], instance of Board.Board; and a list of players [pl], of Player.Player.).
Of course, positions of players in [pl] have to be concording with states (State.State) of the board.
FIXME:
if lx and ly are not sent, they are constants.
not very awesome isn't it ?
"""
res = "GAME_START("
for i, j, spot in board: #: ok.
res += "%s" % spot.to_send() #: 1,2, or 3
if (i<board.lx-1)or(j<board.ly-1):
res += ","
print res
res += board.str_of_players(pl)
#: res += ")\n"
res += ")" # FIXME?
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_board_and_player<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_gameover(player):
""" str_of_gameover(player) -> "GAME_OVER(player.id)"
Sent message by the server to announce the winner of the game, by refering to his [id].
For the player who have the same id is the *winner*, and the other *lost*.
Can be unpack with ParseMessageIn.gameover_of_str.
"""
res = "GAME_OVER(%i)" % (player.id)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_gameover<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_posplantbomb(i, j):
""" str_of_posplantbomb(i, j) -> "PLANT_BOMB(i,j)"
Sent message by the server to announce that a bomb have been planted in the spot (i,j).
Can be unpack with ParseMessageIn.posplantbomb_of_str.
"""
res = "PLANT_BOMB(%i,%i)" % (i,j)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_posplantbomb<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_blowbomb(i, j, radius):
""" str_of_blowbomb(i, j, radius) -> "BLOW_BOMB(i,j,radius)"
Sent message by the server to announce that a bomb have blowed up
in the spot (i,j), with the radius [radius].
Can be unpack with ParseMessageIn.blowbomb_of_str.
"""
res = "BLOW_BOMB(%i,%i,%i)" % (i, j, radius)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_blowbomb<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
[docs]def str_of_moveplayer(player):
""" str_of_moveplayer(player) -> "MOVE_PLAYER(player.id,player.x,player.y)"
Sent message by the server to announce that a player have moved.
Can be unpack with ParseMessageIn.moveplayer_of_str.
"""
res = "MOVE_PLAYER(%i,%i,%i)" % (player.id, player.x, player.y)
if PRINT_ALL_PARSEOUT:
ANSIColors.printc("<magenta>/PRINT_ALL_PARSEOUT/ <u>str_of_moveplayer<U>: returns <neg>'%s'<Neg>.<white>" % res)
return res
#END