#!/usr/bin/python
# -*- encoding: utf-8 -*-
""" This module implement a simple Bomberman game.
No concrete net yet (just some try : connect all players to a server, and log all move).
.. warning::
This script is **deprecated**, don't use it.
Delete me ! I'm useless now...
Can also be used as a program, currently just for testing.
./SimpleGame.py [OPTIONS]
Options:
========
* --help, -h Exit and print this help message.
* -v1 Increase verbosity (default).
* -v2 Increase again ! (not very good).
* --debug Run with pygdb.
* --noANSI Disable colors and escape caracters from ANSIColors.
Usefull to run the program with bpython.
* --noUTF Disable UTF caracters for boxes printing.
Uggly, but more universal !
"""
__author__='Lilian BESSON (mailto:lilian.besson[AT]normale.fr)' # Automatically update with update__date__.sh, a Naereen Corp. (c) bash script.
__version__='1.00b'
__date__='jeu. 14/02/2013 at 05h:17m:53s ' #: The date of the file, automatically update with update__date__.sh, a Naereen Corp. (c) bash script.
#1###############
# Usual Modules #
import sys, copy, random
#2#################
# Project Modules #
#:import Bomb # Bomb.py : implements the simple bomb system. (actions, representation etc)
import Player # Player.py : implements the simple player system. (actions, representation etc)
import ANSIColors # ANSIColors.py : just some colors definition.
import Matrix # Matrix.py : simple module to manipulate matrix, for the board.
import Board # Board.py : two classes Board.Board and Board.State.
import KeyBinding # KeyBinding.py : implements the key binding.
import ParseMessageOut # ParseMessageOut.py : pretty printing of data types, for exchange on the net.
#:import ToolReadline # ToolReadline.py : make sure that raw_input is used as it have to.
##############################################################################
from Constants import *
from AffichPygame import *
#####################################
#### Creating the game variable. ####
[docs]def initGame(lx=LX_CST, ly=LY_CST, nb=NB_PLAYER, server=(SERVEUR_INIT, PORT_INIT)):
""" Creating all Game variables."""
# Pseudos and colors for players
pseudos, colors = pseudos_colors(nb)
# Start position
Mi, Mj=start_position(TYPE_MAP, lx, ly, nb)
# This one is always like this.
nbmax=len(pseudos)
if nbmax>NB_PLAYER or 0>nbmax:
sys.exit(ANSIColors.sprint("\n\t/E/ <red>Nb of players (=len(players)) have to be strictly in [|1;%i|] !<white>" % NB_PLAYER))
# Example of list of player.
pl=list()
for i in range(nbmax):
#: pl.append(Player.Player(info_server=server, pseudo=pseudos[i], color=colors[i]))
pl.append(Player.PlayerServer(pseudo=pseudos[i], color=colors[i]))
# Just a try about creating the players FIXME
#: ANSIColors.printc("\t/n/ This player is number #%i, id=%i <blue>Tap '?' or 'help' for help<white>\n%s" % (i, pl[i].id, keyBindingList[i].get_help()))
#: atexit.register(closeAll, pl=pl) #: FIXME
# Convert players to state
spl=list()
for i in range(nbmax):
spl.append(Board.State(wall=False, players=[pl[i]]))
# Initialize the board
board = Board.Board(Board.empty, lx, ly)
print board
for i, j, spot in board: #: ok.
newspot = copy.copy( random.choice( [Board.dmur, Board.empty] ) )
if PROBA_UMUR > random.random():
newspot = copy.copy( Board.umur )
#: print newspot #: DELETE
newspot.players = copy.copy([])
board[i,j] = copy.copy(newspot)
print board
for i in range(nbmax):
# do not use copy.copy here : spl[i] are pointers to pl[k]
pl[i].move(Mi[i],Mj[i])
board[Mi[i], Mj[i]] = spl[i]
print board
# Initialize the board
#: board=Board.Board(Board.empty, lx, ly)
#: for i in range(lx):
#: for j in range(ly):
#: # FIXME : it is NOT normal that I'm obliged to fix it here. (no players initially)
#: if (i==2 or i==lx-3) or (j==2 or j==ly-3):
#: board[i,j]=copy.copy(Board.State(wall=True, destr=True))
#: if (i==2 or i==lx-3) and (j==2 or j==ly-3):
#: board[i,j]=copy.copy(Board.State(wall=True, destr=False))
#: board[i, j]=copy.copy(board[i, j])
#: board[i, j].players=copy.copy([])
#: for i in range(nbmax):
#: # do not use copy.copy here : spl[i] are pointers to pl[k]
#: pl[i].move(Mi[i],Mj[i])
#:#: board.mat.mat[Mi[i]][Mj[i]]=spl[i]
#: board[Mi[i],Mj[i]] = spl[i]
return (nbmax, lx, ly, pl, board, Mi, Mj)
######################
#### Using Pickle ####
[docs]def save_current_game(variables_to_save, info="variables_to_save"):
""" Save all variables content the list *variables_to_save*, in a .pkl file.
The game can be restored then, by setting all variables equals
to their previous values
(**of course** this only work if the .pkl file is still there)."""
ANSIColors.writec("<reset><white>\n")
return ParseMessageOut.try_pickling(variables_to_save, info=info)
########################
#### Principal Loop ####
[docs]def main(nbmax, lx, ly, pl, board, Mi, Mj, verb=verb, verb2=verb2, keyBindingList=keyBindingList):
""" Big loop to test some behaviour.
How to print bombs and bonuses in text mod ?
How to move players, allow theme to drop bombs ?
Make bombs explosion ?
There are a lot of stuff to work arround !
Parameters:
===========
* [nbmax] Is max number of players,
* [lx], [ly] Are lenght of the board,
* [pl] Is the list of player (represented as Player.Player instances),
* [board] Is ... the board (represented as Board.Board instance !),
* [Mi], [Mj] Are list of players' position to initiate the game,
* [verb], [verb2] Are option for verbosity of the game,
* [keyBindingList] Is a KeyBinding.KeyBinding to map key to moves.
For now, just ONE key (from a to z, A to Z, or ASCII caracters e.g. ~?;/ etc...).
"""
# Use initialization from AffichPygame.
# Initialization of the pygame window.
pygame.init()
# Initialization of music mixer.
pygame.mixer.init()
# Resolution of the screen.
resX, resY = RESOLUTION_X*lx, RESOLUTION_Y*ly
screen = pygame.display.set_mode((resX, resY))
pygame.display.set_caption('.: Bomberman - MPRI - 1-21 - (c) Lilian BESSON :.')
# Background
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((14, 0, 0)) #: A dark brown.
global spotsSprites
# Make the sprites for the spots.
spotsSprites = listsprite_of_board(board)
# Make the window.
screen.blit(background, (0, 0))
pygame.display.flip()
# Initialization of the clock frequency.
clock = pygame.time.Clock()
ANSIColors.printc("\t/pygame/ <INFO> The screen is initializing with resolution (%i,%i) (in pixels: %i,%i).<white>" % (lx,ly, resX,resY))
# Launching the music.
pygame.mixer.music.load('datas/sound/' + MUSIC_loop)
pygame.mixer.music.play(-1)
# Change how to print boxes of the board (|-+/\\ or nonANSI)
if Board.UTFSupported:
board.mat.box=Matrix.boxnoASCII
else:
board.mat.box=Matrix.boxASCII
ANSIColors.writec("\a\n\t/s/ <green>Bomberman game is going to start ... <white>\n")
nb_turn=1
try:
# Handle exceptions
while True:
#: To ensure that the printing is not too quick.
clock.tick(CLOCK_FREQUENCY)
# Infinite loop, may quite with all players' death except one.
# FIXME : try to simulate "synchronisation" step
assert(len(pl) > 0)
save_current_game((nbmax, lx, ly, pl, board, Mi, Mj), info="(nbmax, lx, ly, pl, board, Mi, Mj)")
#: pl[0].send(ParseMessageOut.str_of_board_and_player(board, pl), True)
for event in pygame.event.get():
if event.type == QUIT:
return (nbmax, lx, ly, pl, board, Mi, Mj)
elif event.type == KEYDOWN:
ANSIColors.printc("\t/pygame/ <warning> A key have been pressed : %i => %s.<white>" % (event.key, KeyBinding.print_keynum_as_str(event.key)))
if event.key == K_ESCAPE:
return (nbmax, lx, ly, pl, board, Mi, Mj)
if event.key == K_RIGHT: ANSIColors.printc("\t/pygame/ <INFO> Moving right.<white>")
if event.key == K_LEFT: ANSIColors.printc("\t/pygame/ <INFO> Moving left.<white>")
if event.key == K_UP: ANSIColors.printc("\t/pygame/ <INFO> Moving up.<white>")
if event.key == K_DOWN: ANSIColors.printc("\t/pygame/ <INFO> Moving down.<white>")
if event.key == K_SPACE: ANSIColors.printc("\t/pygame/ <INFO> Dropping bomb.<white>")
for k in range(nbmax):
player=pl[k]
# Loop over player. k is an index of a player.
print_clear(board)
# PYGAME stuff.
spotsSprites = listsprite_of_board(board)
screen.blit(background, (0, 0))
pygame.display.flip()
spotsSprites.update()
spotsSprites.draw(screen)
# Print.
pygame.display.flip()
# Clear the screen, and print the [board] (using Board.Board.__str__)
for itmp in range(board.lx):
for jtmp in range(board.ly):
if board.mat[itmp,jtmp].explosion: board.mat[itmp,jtmp].explosion=False
# The explosion is just print once
if verb2:
tmp="\t/P/ "
for kk in range(nbmax):
tmp+=("PV[%s]=%i;" % (pl[kk], pl[kk].pv))
ANSIColors.printc("<white>%s<white>" % tmp)
# If verb2, print all players' PV
# Store old positions
#: Mi_old=Mi
#: Mj_old=Mj
i=Mi[k]
j=Mj[k]
# get moves
#: sys.stdout.flush()
try:
inp='K_'+raw_input("[Turn %i] Move for player #%i (this player is :[%s]) located in (%i,%i) =? " % (nb_turn, k, player, i, j))
len(inp)
except KeyboardInterrupt:
ANSIColors.printc("\a\n\t/raw_input/ <red>FAIL !<white> Maybe you hit ^C or ^D ?\n")
raise KeyboardInterrupt
#: sys.stdout.flush()
if inp in ["="]: #: Save the game *rigth* now.
save_current_game((nbmax, lx, ly, pl, board, Mi, Mj), info="(nbmax, lx, ly, pl, board, Mi, Mj)")
if inp in ["!", "$", "stop"]:
raise KeyboardInterrupt
if inp=="":
continue
# Do nothing.
if keyBindingList[k].ok(inp, 'help'):
ANSIColors.printc("\t/h/ <blue>Tap '?' or 'help' for help<white>\n%s" % keyBindingList[k].get_help())
continue
move_to_send=""
bool_action=False
#: Analyse moves, validate them, update the new position
#: but this new position (i,j) will be checked later.
if keyBindingList[k].ok(inp, 'up'):
if i>0: move_to_send+="UP"
if verb2: ANSIColors.printc("\t/u/ <blue>Player #%i <white>[%s]<white> wants to go <green>up<white>." % (k, player))
i=max(0,i-1)
if keyBindingList[k].ok(inp, 'down'):
if i<lx: move_to_send+="DOWN"
if verb2: ANSIColors.printc("\t/d/ <blue>Player #%i <white>[%s]<white> wants to go <green>down<white>." % (k, player))
i=min(lx-1,i+1)
if keyBindingList[k].ok(inp, 'left'):
if j>0: move_to_send+="LEFT"
if verb2: ANSIColors.printc("\t/l/ <blue>Player #%i <white>[%s]<white> wants to go <green>left<white>." % (k, player))
j=max(0,j-1)
if keyBindingList[k].ok(inp, 'right'):
if j<ly: move_to_send+="RIGHT"
if verb2: ANSIColors.printc("\t/r/ <blue>Player #%i <white>[%s]<white> wants to go <green>right<white>." % (k, player))
j=min(ly-1,j+1)
if keyBindingList[k].ok(inp, 'bomb'):
if board[i,j].bomb:
ANSIColors.printc("\t/!/ <u><red>This is not allowed<U><black>, you cannot drop a second bomb <u>here<U>.<white>")
elif player.nb_bomb >= NB_BOMB_MAX_ALLOW:
ANSIColors.printc("\t/!/ <u><red>This is not allowed<U><black>, you cannot drop a new bomb on the board (max allow : %i).<white>" % NB_BOMB_MAX_ALLOW)
else:
move_to_send+="BOMB"
board[i,j].bomb=player.drop() # a new bomb
bool_action=True
# If the new place is new, and is not a wall, move the player to it
if verb2 and (move_to_send != "BOMB") and bool_action: ANSIColors.printc("\t/w/ <green>Player #%i<white> wants to move from (%i,%i) to (%i,%i)." % (k, Mi[k], Mj[k], i, j))
if (move_to_send != "BOMB"):
if (not board[i,j].wall) and ((i != Mi[k]) or (j != Mj[k])):
# player=board[Mi[k], Mj[k]].players.pop()
# FIXME
board[Mi[k], Mj[k]].players.remove(player)
if verb: print "\t/o/ Old spot : (%i, %i) => %s" % (Mi[k], Mj[k], repr(board[Mi[k], Mj[k]]))
board[i,j].players.append(player)
# here the move is really stores
if verb2: ANSIColors.printc("\t/w/ <green>Player #%i<white> well moved from (%i,%i) to (%i,%i)." % (k, Mi[k], Mj[k], i, j))
Mi[k]=i
Mj[k]=j
# Try to store positions internally in the players
player.move(i,j)
bool_action=True
if verb: print "\t/n/ New spot : (%i, %i) => %s" % (i, j, repr(board[i, j]))
elif board[i,j].wall:
if verb2: ANSIColors.printc("\t/!/ <green>Player #%i<white> can not move from (%i,%i) to (%i,%i) because there is a wall in the wanted spot." % (k, Mi[k], Mj[k], i, j))
elif i==Mi[k] and j==Mj[k]:
if verb2: ANSIColors.printc("\t/!/ <green>Player #%i<white> can not move from (%i,%i) to (%i,%i) because there is the natural limitation of the board." % (k, Mi[k], Mj[k], i, j))
else:
if verb2: ANSIColors.printc("\t/!/ <green>Player #%i<white> can not move from (%i,%i) to (%i,%i)." % (k, Mi[k], Mj[k], i, j))
if move_to_send and bool_action:
#:#:# move_to_send=("MOVE(id=%i;%s)" % (player.pseudo, player.color))+move_to_send+")"
move_to_send=ParseMessageOut.str_of_move(move_to_send)
#: ANSIColors.printc("\t/#/ <green>Player #%i<white> try to send a message [%s] to the server %s. He is known as %s." % (k, move_to_send, str(player.info_server), str(player.info_connection)))
#: try:
#FIXME a test to send all moves sequences to the server
#: player.send(move_to_send, verb or verb2)
#: except:
#: print "\t/F/ Failure : %s send %s. Verbosity=%s" % (str(player), move_to_send, str(verb or verb2))
board.tic(1, True) # Handle all bombs
ANSIColors.printc("\t/t/ <blue>New turn !<white>")
nb_turn+=1
# Handling of all uncaugth exception
except:
raise
#: except Exception as e:
#: save_current_game((nbmax, lx, ly, pl, board, Mi, Mj), info="(nbmax, lx, ly, pl, board, Mi, Mj)")
#: closeAll(pl)
#: ANSIColors.printc("\n\t/!/ <red>Game closed !<black> nicely close all players : TODO<white> %s" % e)
#: raise e
###############
##### End #####
if __name__ == '__main__':
#: import argparse #: No longer used here. FIXED.
import ParseCommandArgs
#: Generate the parser, with another module.
#: This variable is the preprocessor, given to description and epilog by ParseCommandArgs,
#: * erase: to print with no colors.
#: * sprint: to print with colors.
preprocessor = ANSIColors.sprint if ANSIColors.ANSISupported else ANSIColors.erase #:preprocessor = __builtin__.str, if you wanna to *see* the balises.
#: Generate the parser, with another module.
parser = ParseCommandArgs.parser_default(\
description='<green>SimpleGame <red>module<reset> and <blue>script<reset>.',\
epilog="""\n\
<yellow>About:
======<reset>
A lot of tests.""", \
version=__version__, date=__date__, author=__author__, \
preprocessor=preprocessor)
#: Description for the part with '--file' and '--generate' options.
group = parser.add_argument_group('A SimpleGame test', preprocessor("""\
<b>**THIS** <u>is a test<U>. So, use it for tests ... <reset>
"""))
#: Remember that action can be used to many things.
group.add_argument("-s","--server", help="The address of the server (eg '138.231.139.1', or 'bomberman-server.crans.org').") #:, required=True)
group.add_argument("-p","--port", type=int, help="The port on which the connection to the server will be established (eg 9312, or 12882).\n\t This port *have* to be an open port on your machine **and** have to be the listened port of the server !") #:, required=True)
# A group for handling save restore
group = parser.add_argument_group('Saving and restoring previous sessions :', preprocessor("""\
<b>This program <u>save his state<U> (the board, list of players etc) during the session<reset>,
so if there is a problem, the last valid state of the game will be keeped.
And this program can of course restore such a state, to restart from where it was !
"""))
group.add_argument('-l', '--load', help=preprocessor(""" If present, the server will try to restart a previously close session."""), action="store_true")
group.add_argument('-f', '--file', help=preprocessor(""" Try to load the savegame from the file FILE if possible, launch a <red>new one<reset> if not."""))
#: The parser is done,
#: Use it to extract the args from the command line.
args = parser.parse_args()
#: Use those args.
##################
verb=(args.verbose >= 1) or verb #: Default = True
verb2=(args.verbose >= 2) and verb2 #: Default = False
# Print with ANSI escape code for colors if possible
ANSIColors.ANSISupported=(not(args.noANSI) and ANSIColors.ANSISupported) or args.ANSI
# Disable all escape codes for color to be generated
if not(ANSIColors.ANSISupported):
ColorOff()
else: ColorOn()
ANSIColors.printc("\t/!/ ANSI escape code for colors supports = <green>%s<white>." % ANSIColors.ANSISupported)
# Print with non ASCII caracters for boxes if possible
Board.UTFSupported=not(args.noUTF) and Board.UTFSupported
ANSIColors.printc("\t/!/ UTF escape code for boxes supports = <green>%s<white>." % Board.UTFSupported)
# Set the server and the port
server = args.server if args.server else SERVEUR_INIT
port = int(args.port) if args.port else PORT_INIT
##########################################
#: If a save game is available, load it !
#: try:
if args.load:
ANSIColors.printc("\t/load/ <yellow>Trying to load<reset><white> \tthe game from a save file<reset><white>...")
from ParseMessageIn import try_unpickling
#: import Constants
if args.file:
nbmax, lx, ly, pl, board, Mi, Mj=try_unpickling("(nbmax, lx, ly, pl, board, Mi, Mj)", fn=args.file)
else: # use the default value !
nbmax, lx, ly, pl, board, Mi, Mj=try_unpickling("(nbmax, lx, ly, pl, board, Mi, Mj)")
for i in range(lx):
for j in range(ly):
board[i,j] = copy.copy(board[i,j])
board[i,j].players = copy.copy(board[i,j].players)
ANSIColors.printc("\t/load/ <green>Succeed to load<reset><white> \tthe game from a save file<reset><white>...")
#: except Exception as e:
else:
e = "<yellow>-l neither --load found if the argument.<reset>"
#: Otherwise create a new game.
ANSIColors.printc("\t/load/ <u><red>Failed to load<reset><white> \tthe game from a save file...\n\t/load/ Cause : %s" % e)
ANSIColors.printc("\t/init/ <yellow>The game will run on the server : (%s:%i)<reset><white>" % (server, port))
nbmax, lx, ly, pl, board, Mi, Mj = initGame( server=(server, port))
# The game is initialized
###############################################
main(nbmax, lx, ly, pl, board, Mi, Mj, verb=verb, verb2=verb2)
#END