mirror of
https://github.com/abakh/nbsdgames.git
synced 2025-02-02 15:07:27 -05:00
effort to make it py3
This commit is contained in:
parent
dd6e6354e4
commit
3381c4df1a
46
BubBob.py
46
BubBob.py
@ -9,7 +9,7 @@
|
||||
|
||||
# __________
|
||||
import os, sys
|
||||
print 'Running on Python', sys.version
|
||||
print('Running on Python', sys.version)
|
||||
if __name__ == '__main__':
|
||||
LOCALDIR = sys.argv[0]
|
||||
else:
|
||||
@ -61,12 +61,12 @@ def look_for_local_server():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect(('127.0.0.1', port))
|
||||
except socket.error, e:
|
||||
except socket.error as e:
|
||||
return None
|
||||
try:
|
||||
s.shutdown(2)
|
||||
s.close()
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
pass
|
||||
url2, port2 = load_url_file()
|
||||
if port2 != port:
|
||||
@ -93,9 +93,9 @@ def start_local_server():
|
||||
else:
|
||||
httppages.main(None, TAGFILENAME, 0)
|
||||
if logfile:
|
||||
print >> logfile
|
||||
print(file=logfile)
|
||||
if logfile:
|
||||
print "Logging to", logfile.filename
|
||||
print("Logging to", logfile.filename)
|
||||
fd = logfile.f.fileno()
|
||||
try:
|
||||
# detach from parent
|
||||
@ -130,35 +130,35 @@ if not url:
|
||||
if url:
|
||||
break
|
||||
else:
|
||||
print >> sys.stderr, 'The local server is not starting, giving up.'
|
||||
print('The local server is not starting, giving up.', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import webbrowser
|
||||
browser = webbrowser.get()
|
||||
name = getattr(browser, 'name', browser.__class__.__name__)
|
||||
print "Trying to open '%s' with '%s'..." % (url, name)
|
||||
print("Trying to open '%s' with '%s'..." % (url, name))
|
||||
browser.open(url)
|
||||
except:
|
||||
exc, val, tb = sys.exc_info()
|
||||
print '-'*60
|
||||
print >> sys.stderr, "Failed to launch the web browser:"
|
||||
print >> sys.stderr, " %s: %s" % (exc.__name__, val)
|
||||
print
|
||||
print "Sorry, I guess you have to go to the following URL manually:"
|
||||
print('-'*60)
|
||||
print("Failed to launch the web browser:", file=sys.stderr)
|
||||
print(" %s: %s" % (exc.__name__, val), file=sys.stderr)
|
||||
print()
|
||||
print("Sorry, I guess you have to go to the following URL manually:")
|
||||
else:
|
||||
print "Done running '%s'." % name
|
||||
print("Done running '%s'." % name)
|
||||
if look_for_local_server() != url:
|
||||
# assume that browser.open() waited for the browser to finish
|
||||
# and that the server has been closed from the browser.
|
||||
raise SystemExit
|
||||
print
|
||||
print '-'*60
|
||||
print "If the browser fails to open the page automatically,"
|
||||
print "you will have to manually go to the following URL:"
|
||||
print ' ', url
|
||||
print '-'*60
|
||||
print "Note that the server runs in the background. You have to use"
|
||||
print "the 'Stop this program' link to cleanly stop it."
|
||||
print "Normally, however, running this script multiple times should"
|
||||
print "not create multiple servers in the background."
|
||||
print()
|
||||
print('-'*60)
|
||||
print("If the browser fails to open the page automatically,")
|
||||
print("you will have to manually go to the following URL:")
|
||||
print(' ', url)
|
||||
print('-'*60)
|
||||
print("Note that the server runs in the background. You have to use")
|
||||
print("the 'Stop this program' link to cleanly stop it.")
|
||||
print("Normally, however, running this script multiple times should")
|
||||
print("not create multiple servers in the background.")
|
||||
|
164
BubBob.py.bak
Executable file
164
BubBob.py.bak
Executable file
@ -0,0 +1,164 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
#
|
||||
# This script is used to start the server.
|
||||
# For command-line usage please run
|
||||
#
|
||||
# python bubbob/bb.py --help
|
||||
#
|
||||
|
||||
# __________
|
||||
import os, sys
|
||||
print 'Running on Python', sys.version
|
||||
if __name__ == '__main__':
|
||||
LOCALDIR = sys.argv[0]
|
||||
else:
|
||||
LOCALDIR = __file__
|
||||
try:
|
||||
LOCALDIR = os.readlink(LOCALDIR)
|
||||
except:
|
||||
pass
|
||||
sys.argv[0] = os.path.abspath(LOCALDIR)
|
||||
LOCALDIR = os.path.dirname(sys.argv[0])
|
||||
# ----------
|
||||
|
||||
import socket, tempfile
|
||||
|
||||
sys.path.insert(0, LOCALDIR)
|
||||
os.chdir(LOCALDIR)
|
||||
|
||||
try:
|
||||
username = '-'+os.getlogin()
|
||||
except:
|
||||
try:
|
||||
import pwd
|
||||
username = '-'+pwd.getpwuid(os.getuid())[0]
|
||||
except:
|
||||
username = ''
|
||||
TAGFILENAME = 'BubBob-%s%s.url' % (socket.gethostname(), username)
|
||||
TAGFILENAME = os.path.join(tempfile.gettempdir(), TAGFILENAME)
|
||||
|
||||
|
||||
def load_url_file():
|
||||
try:
|
||||
url = open(TAGFILENAME, 'r').readline().strip()
|
||||
except (OSError, IOError):
|
||||
return None, None
|
||||
if not url.startswith('http://127.0.0.1:'):
|
||||
return None, None
|
||||
url1 = url[len('http://127.0.0.1:'):]
|
||||
try:
|
||||
port = int(url1[:url1.index('/')])
|
||||
except ValueError:
|
||||
return None, None
|
||||
return url, port
|
||||
|
||||
def look_for_local_server():
|
||||
# Look for a running local web server
|
||||
url, port = load_url_file()
|
||||
if port is None:
|
||||
return None
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.connect(('127.0.0.1', port))
|
||||
except socket.error, e:
|
||||
return None
|
||||
try:
|
||||
s.shutdown(2)
|
||||
s.close()
|
||||
except Exception, e:
|
||||
pass
|
||||
url2, port2 = load_url_file()
|
||||
if port2 != port:
|
||||
return None
|
||||
return url2
|
||||
|
||||
def start_local_server():
|
||||
MAINSCRIPT = os.path.join('bubbob', 'bb.py')
|
||||
has_server = os.path.exists(MAINSCRIPT)
|
||||
if hasattr(os, 'fork') and hasattr(os, 'dup2'):
|
||||
if os.fork() == 0:
|
||||
# in the child process
|
||||
if has_server:
|
||||
sys.path.insert(0, os.path.join(LOCALDIR, 'bubbob'))
|
||||
import bb
|
||||
bb.BubBobGame.Quiet = 1
|
||||
else:
|
||||
sys.path.insert(0, os.path.join(LOCALDIR, 'http2'))
|
||||
import httppages
|
||||
import gamesrv, stdlog
|
||||
logfile = stdlog.LogFile()
|
||||
if has_server:
|
||||
bb.start_metaserver(TAGFILENAME, 0)
|
||||
else:
|
||||
httppages.main(None, TAGFILENAME, 0)
|
||||
if logfile:
|
||||
print >> logfile
|
||||
if logfile:
|
||||
print "Logging to", logfile.filename
|
||||
fd = logfile.f.fileno()
|
||||
try:
|
||||
# detach from parent
|
||||
os.dup2(fd, 1)
|
||||
os.dup2(fd, 2)
|
||||
os.dup2(fd, 0)
|
||||
except OSError:
|
||||
pass
|
||||
logfile.close()
|
||||
gamesrv.mainloop()
|
||||
sys.exit(0)
|
||||
else:
|
||||
if not has_server:
|
||||
MAINSCRIPT = os.path.join('http2', 'httppages.py')
|
||||
args = [sys.executable, MAINSCRIPT, '--quiet',
|
||||
'--saveurlto=%s' % TAGFILENAME]
|
||||
# (quoting sucks on Windows) ** 42
|
||||
if sys.platform == 'win32':
|
||||
args[0] = '"%s"' % (args[0],)
|
||||
os.spawnv(os.P_NOWAITO, sys.executable, args)
|
||||
|
||||
|
||||
# main
|
||||
url = look_for_local_server()
|
||||
if not url:
|
||||
start_local_server()
|
||||
# wait for up to 5 seconds for the server to start
|
||||
for i in range(10):
|
||||
import time
|
||||
time.sleep(0.5)
|
||||
url = look_for_local_server()
|
||||
if url:
|
||||
break
|
||||
else:
|
||||
print >> sys.stderr, 'The local server is not starting, giving up.'
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import webbrowser
|
||||
browser = webbrowser.get()
|
||||
name = getattr(browser, 'name', browser.__class__.__name__)
|
||||
print "Trying to open '%s' with '%s'..." % (url, name)
|
||||
browser.open(url)
|
||||
except:
|
||||
exc, val, tb = sys.exc_info()
|
||||
print '-'*60
|
||||
print >> sys.stderr, "Failed to launch the web browser:"
|
||||
print >> sys.stderr, " %s: %s" % (exc.__name__, val)
|
||||
print
|
||||
print "Sorry, I guess you have to go to the following URL manually:"
|
||||
else:
|
||||
print "Done running '%s'." % name
|
||||
if look_for_local_server() != url:
|
||||
# assume that browser.open() waited for the browser to finish
|
||||
# and that the server has been closed from the browser.
|
||||
raise SystemExit
|
||||
print
|
||||
print '-'*60
|
||||
print "If the browser fails to open the page automatically,"
|
||||
print "you will have to manually go to the following URL:"
|
||||
print ' ', url
|
||||
print '-'*60
|
||||
print "Note that the server runs in the background. You have to use"
|
||||
print "the 'Stop this program' link to cleanly stop it."
|
||||
print "Normally, however, running this script multiple times should"
|
||||
print "not create multiple servers in the background."
|
BIN
bubbob/__pycache__/bb.cpython-39.pyc
Normal file
BIN
bubbob/__pycache__/bb.cpython-39.pyc
Normal file
Binary file not shown.
76
bubbob/bb.py
76
bubbob/bb.py
@ -1,6 +1,6 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
|
||||
# __________
|
||||
import os, sys
|
||||
@ -89,11 +89,11 @@ class BubBobGame(gamesrv.Game):
|
||||
if self.metaregister:
|
||||
self.do_updatemetaserver()
|
||||
frametime = 0.0
|
||||
for i in xrange(500):
|
||||
for i in range(500):
|
||||
import boards
|
||||
for gen in boards.BoardGen[:]:
|
||||
try:
|
||||
frametime += gen.next()
|
||||
frametime += next(gen)
|
||||
except StopIteration:
|
||||
try:
|
||||
boards.BoardGen.remove(gen)
|
||||
@ -110,7 +110,7 @@ class BubBobGame(gamesrv.Game):
|
||||
self.game_reset_gen = boards.game_reset()
|
||||
else:
|
||||
try:
|
||||
self.game_reset_gen.next()
|
||||
next(self.game_reset_gen)
|
||||
except StopIteration:
|
||||
self.game_reset_gen = None
|
||||
return frametime * boards.FRAME_TIME
|
||||
@ -132,9 +132,9 @@ class BubBobGame(gamesrv.Game):
|
||||
if kbd and not [p for p in BubPlayer.PlayerList if p.isplaying()]:
|
||||
return 0
|
||||
import traceback
|
||||
print "-"*60
|
||||
print("-"*60)
|
||||
traceback.print_exc()
|
||||
print "-"*60
|
||||
print("-"*60)
|
||||
if not kbd:
|
||||
try:
|
||||
if self.metaserver:
|
||||
@ -145,15 +145,15 @@ class BubBobGame(gamesrv.Game):
|
||||
else:
|
||||
if metaclient.metaclisrv:
|
||||
metaclient.metaclisrv.send_traceback()
|
||||
except Exception, e:
|
||||
print '! %s: %s' % (e.__class__.__name__, e)
|
||||
except Exception as e:
|
||||
print('! %s: %s' % (e.__class__.__name__, e))
|
||||
import boards
|
||||
num = getattr(boards.curboard, 'num', None)
|
||||
if self.Quiet:
|
||||
print "Crash recovery! Automatically restarting board %s" % num
|
||||
print("Crash recovery! Automatically restarting board %s" % num)
|
||||
import time; time.sleep(2)
|
||||
else:
|
||||
print "Correct the problem and leave pdb to restart board %s..."%num
|
||||
print("Correct the problem and leave pdb to restart board %s..."%num)
|
||||
import pdb; pdb.post_mortem(sys.exc_info()[2])
|
||||
self.openboard(num)
|
||||
return 1
|
||||
@ -183,7 +183,7 @@ class BubBobGame(gamesrv.Game):
|
||||
setuppath('metaserver')
|
||||
import metaclient
|
||||
metaclient.meta_register(self)
|
||||
print '.'
|
||||
print('.')
|
||||
else:
|
||||
try:
|
||||
import metaclient
|
||||
@ -201,8 +201,8 @@ class BubBobGame(gamesrv.Game):
|
||||
def setuppath(dirname):
|
||||
dir = os.path.abspath(os.path.join(LOCALDIR, os.pardir, dirname))
|
||||
if not os.path.isdir(dir):
|
||||
print >> sys.stderr, (
|
||||
'../%s: directory not found ("cvs update -d" ?)' % dirname)
|
||||
print((
|
||||
'../%s: directory not found ("cvs update -d" ?)' % dirname), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if dir not in sys.path:
|
||||
sys.path.insert(0, dir)
|
||||
@ -210,28 +210,28 @@ def setuppath(dirname):
|
||||
def parse_cmdline(argv):
|
||||
# parse command-line
|
||||
def usage():
|
||||
print >> sys.stderr, 'usage:'
|
||||
print >> sys.stderr, ' python bb.py'
|
||||
print('usage:', file=sys.stderr)
|
||||
print(' python bb.py', file=sys.stderr)
|
||||
## print >> sys.stderr, ' python bb.py [-w/--webbrowser=no]'
|
||||
## print >> sys.stderr, 'where:'
|
||||
## print >> sys.stderr, ' -w --webbrowser=no don''t automatically start web browser'
|
||||
print >> sys.stderr, 'or:'
|
||||
print >> sys.stderr, ' python bb.py [level-file.bin] [-m] [-b#] [-s#] [-l#] [-M#]'
|
||||
print >> sys.stderr, 'with options:'
|
||||
print >> sys.stderr, ' -m --metaserver register the server on the Metaserver so anyone can join'
|
||||
print >> sys.stderr, ' -b# --begin # start at board number # (default 1)'
|
||||
print >> sys.stderr, ' --start # synonym for --begin'
|
||||
print >> sys.stderr, ' --final # end at board number # (default 100)'
|
||||
print >> sys.stderr, ' -s# --step # advance board number by steps of # (default 1)'
|
||||
print >> sys.stderr, ' -l# --lives # limit the number of lives to #'
|
||||
print >> sys.stderr, ' --extralife # gain extra life every # points'
|
||||
print >> sys.stderr, ' --limitlives # max # of lives player can gain in one board'
|
||||
print >> sys.stderr, ' -M# --monsters # multiply the number of monsters by #'
|
||||
print >> sys.stderr, ' (default between 1.0 and 2.0 depending on # of players)'
|
||||
print >> sys.stderr, ' -i --infinite restart the server at the end of the game'
|
||||
print >> sys.stderr, ' --port LISTEN=# set fixed tcp port for game server'
|
||||
print >> sys.stderr, ' --port HTTP=# set fixed tcp port for http server'
|
||||
print >> sys.stderr, ' -h --help display this text'
|
||||
print('or:', file=sys.stderr)
|
||||
print(' python bb.py [level-file.bin] [-m] [-b#] [-s#] [-l#] [-M#]', file=sys.stderr)
|
||||
print('with options:', file=sys.stderr)
|
||||
print(' -m --metaserver register the server on the Metaserver so anyone can join', file=sys.stderr)
|
||||
print(' -b# --begin # start at board number # (default 1)', file=sys.stderr)
|
||||
print(' --start # synonym for --begin', file=sys.stderr)
|
||||
print(' --final # end at board number # (default 100)', file=sys.stderr)
|
||||
print(' -s# --step # advance board number by steps of # (default 1)', file=sys.stderr)
|
||||
print(' -l# --lives # limit the number of lives to #', file=sys.stderr)
|
||||
print(' --extralife # gain extra life every # points', file=sys.stderr)
|
||||
print(' --limitlives # max # of lives player can gain in one board', file=sys.stderr)
|
||||
print(' -M# --monsters # multiply the number of monsters by #', file=sys.stderr)
|
||||
print(' (default between 1.0 and 2.0 depending on # of players)', file=sys.stderr)
|
||||
print(' -i --infinite restart the server at the end of the game', file=sys.stderr)
|
||||
print(' --port LISTEN=# set fixed tcp port for game server', file=sys.stderr)
|
||||
print(' --port HTTP=# set fixed tcp port for http server', file=sys.stderr)
|
||||
print(' -h --help display this text', file=sys.stderr)
|
||||
#print >> sys.stderr, ' -rxxx record the game in file xxx'
|
||||
sys.exit(1)
|
||||
|
||||
@ -246,9 +246,9 @@ def parse_cmdline(argv):
|
||||
'lives=', 'monsters=', 'infinite', 'help',
|
||||
'extralife=', 'limitlives=', 'final=',
|
||||
'saveurlto=', 'quiet', 'port=', 'makeimages'])
|
||||
except error, e:
|
||||
print >> sys.stderr, 'bb.py: %s' % str(e)
|
||||
print >> sys.stderr
|
||||
except error as e:
|
||||
print('bb.py: %s' % str(e), file=sys.stderr)
|
||||
print(file=sys.stderr)
|
||||
usage()
|
||||
|
||||
options = {}
|
||||
@ -269,7 +269,7 @@ def parse_cmdline(argv):
|
||||
elif key in ('--final'):
|
||||
options['finalboard'] = int(value)
|
||||
if options['finalboard'] < options['beginboard']:
|
||||
print >> sys.stderr, 'bb.py: final board value must be larger than begin board.'
|
||||
print('bb.py: final board value must be larger than begin board.', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
elif key in ('--extralife'):
|
||||
options['extralife'] = int(value)
|
||||
@ -295,14 +295,14 @@ def parse_cmdline(argv):
|
||||
# webbrowser = value.startswith('y')
|
||||
if args:
|
||||
if len(args) > 1:
|
||||
print >> sys.stderr, 'bb.py: multiple level files specified'
|
||||
print('bb.py: multiple level files specified', file=sys.stderr)
|
||||
sys.exit(1)
|
||||
levelfile = os.path.abspath(args[0])
|
||||
os.chdir(LOCALDIR)
|
||||
BubBobGame(levelfile, **options)
|
||||
else:
|
||||
if options:
|
||||
print >> sys.stderr, 'bb.py: command-line options ignored'
|
||||
print('bb.py: command-line options ignored', file=sys.stderr)
|
||||
start_metaserver(save_url_to, quiet)
|
||||
|
||||
def start_metaserver(save_url_to, quiet):
|
||||
|
345
bubbob/bb.py.bak
Executable file
345
bubbob/bb.py.bak
Executable file
@ -0,0 +1,345 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
# __________
|
||||
import os, sys
|
||||
if __name__ == '__main__':
|
||||
LOCALDIR = sys.argv[0]
|
||||
else:
|
||||
LOCALDIR = __file__
|
||||
try:
|
||||
LOCALDIR = os.readlink(LOCALDIR)
|
||||
except:
|
||||
pass
|
||||
LOCALDIR = os.path.dirname(os.path.abspath(LOCALDIR))
|
||||
# ----------
|
||||
|
||||
import random, time
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(LOCALDIR), 'common'))
|
||||
sys.path.insert(0, LOCALDIR)
|
||||
import gamesrv
|
||||
|
||||
PROFILE = 0
|
||||
|
||||
|
||||
class BubBobGame(gamesrv.Game):
|
||||
|
||||
FnDesc = "Bub & Bob"
|
||||
FnBasePath = "bubbob"
|
||||
Quiet = 0
|
||||
End = 0
|
||||
|
||||
def __init__(self, levelfile,
|
||||
beginboard = 1,
|
||||
stepboard = 1,
|
||||
finalboard = 100,
|
||||
limitlives = None,
|
||||
extralife = 50000,
|
||||
lifegainlimit = None,
|
||||
autoreset = 0,
|
||||
metaserver = 0,
|
||||
monsters = 0):
|
||||
gamesrv.Game.__init__(self)
|
||||
self.game_reset_gen = None
|
||||
self.levelfile = levelfile
|
||||
self.beginboard = beginboard
|
||||
self.finalboard = finalboard
|
||||
self.stepboard = stepboard
|
||||
self.limitlives = limitlives
|
||||
self.lifegainlimit = lifegainlimit
|
||||
self.extralife = extralife
|
||||
self.autoreset = autoreset
|
||||
self.metaserver = metaserver
|
||||
self.f_monsters = monsters
|
||||
self.updatemetaserver()
|
||||
levelsname, ext = os.path.splitext(os.path.basename(levelfile))
|
||||
self.FnDesc = BubBobGame.FnDesc + ' ' + levelsname
|
||||
self.reset()
|
||||
self.openserver()
|
||||
|
||||
def openboard(self, num=None):
|
||||
self.End = 0
|
||||
if num is None:
|
||||
num = self.beginboard-1
|
||||
import boards
|
||||
boards.loadmodules(force=1)
|
||||
import boards # possibly re-import
|
||||
self.width = boards.bwidth + 9*boards.CELL
|
||||
self.height = boards.bheight
|
||||
boards.curboard = None
|
||||
boards.BoardGen = [boards.next_board(num)]
|
||||
self.updatemetaserver()
|
||||
|
||||
def reset(self):
|
||||
import player
|
||||
self.openboard()
|
||||
for p in player.BubPlayer.PlayerList:
|
||||
p.reset()
|
||||
|
||||
def FnPlayers(self):
|
||||
from player import BubPlayer
|
||||
result = {}
|
||||
for p in BubPlayer.PlayerList:
|
||||
result[p.pn] = p
|
||||
return result
|
||||
|
||||
def FnFrame(self):
|
||||
if self.metaregister:
|
||||
self.do_updatemetaserver()
|
||||
frametime = 0.0
|
||||
for i in xrange(500):
|
||||
import boards
|
||||
for gen in boards.BoardGen[:]:
|
||||
try:
|
||||
frametime += gen.next()
|
||||
except StopIteration:
|
||||
try:
|
||||
boards.BoardGen.remove(gen)
|
||||
except ValueError:
|
||||
pass
|
||||
if frametime >= 1.1:
|
||||
break
|
||||
else:
|
||||
# should normally never occur
|
||||
boards.BoardGen[:] = [boards.next_board()]
|
||||
frametime = 1.0
|
||||
if self.game_reset_gen is None:
|
||||
if self.End and self.autoreset:
|
||||
self.game_reset_gen = boards.game_reset()
|
||||
else:
|
||||
try:
|
||||
self.game_reset_gen.next()
|
||||
except StopIteration:
|
||||
self.game_reset_gen = None
|
||||
return frametime * boards.FRAME_TIME
|
||||
|
||||
def FnServerInfo(self, msg):
|
||||
try:
|
||||
from images import writestr
|
||||
writestr(50, 50, msg)
|
||||
self.sendudpdata()
|
||||
except:
|
||||
pass
|
||||
|
||||
def FnExcHandler(self, kbd):
|
||||
if kbd:
|
||||
self.FnServerInfo("Server was Ctrl-C'ed!")
|
||||
else:
|
||||
self.FnServerInfo('Ooops -- server crash!')
|
||||
from player import BubPlayer
|
||||
if kbd and not [p for p in BubPlayer.PlayerList if p.isplaying()]:
|
||||
return 0
|
||||
import traceback
|
||||
print "-"*60
|
||||
traceback.print_exc()
|
||||
print "-"*60
|
||||
if not kbd:
|
||||
try:
|
||||
if self.metaserver:
|
||||
try:
|
||||
import metaclient
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
if metaclient.metaclisrv:
|
||||
metaclient.metaclisrv.send_traceback()
|
||||
except Exception, e:
|
||||
print '! %s: %s' % (e.__class__.__name__, e)
|
||||
import boards
|
||||
num = getattr(boards.curboard, 'num', None)
|
||||
if self.Quiet:
|
||||
print "Crash recovery! Automatically restarting board %s" % num
|
||||
import time; time.sleep(2)
|
||||
else:
|
||||
print "Correct the problem and leave pdb to restart board %s..."%num
|
||||
import pdb; pdb.post_mortem(sys.exc_info()[2])
|
||||
self.openboard(num)
|
||||
return 1
|
||||
|
||||
def FnListBoards():
|
||||
import boards
|
||||
result = []
|
||||
for fn in os.listdir('levels'):
|
||||
base, ext = os.path.splitext(fn)
|
||||
if ext in ('.py', '.bin'):
|
||||
result.append((base, os.path.join('levels', fn)))
|
||||
return result
|
||||
FnListBoards = staticmethod(FnListBoards)
|
||||
|
||||
def FnExtraDesc(self):
|
||||
import boards
|
||||
s = gamesrv.Game.FnExtraDesc(self)
|
||||
if boards.curboard and self.End != 'gameover':
|
||||
s = '%s, board %d' % (s, boards.curboard.num+1)
|
||||
return s
|
||||
|
||||
def do_updatemetaserver(self):
|
||||
self.metaregister -= 1
|
||||
if self.metaregister > 0:
|
||||
return
|
||||
if self.metaserver and (self.autoreset or self.End != 'gameover'):
|
||||
setuppath('metaserver')
|
||||
import metaclient
|
||||
metaclient.meta_register(self)
|
||||
print '.'
|
||||
else:
|
||||
try:
|
||||
import metaclient
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
metaclient.meta_unregister(self)
|
||||
|
||||
def updatemetaserver(self):
|
||||
self.metaregister = 2
|
||||
|
||||
updateboard = updateplayers = updatemetaserver
|
||||
|
||||
|
||||
def setuppath(dirname):
|
||||
dir = os.path.abspath(os.path.join(LOCALDIR, os.pardir, dirname))
|
||||
if not os.path.isdir(dir):
|
||||
print >> sys.stderr, (
|
||||
'../%s: directory not found ("cvs update -d" ?)' % dirname)
|
||||
sys.exit(1)
|
||||
if dir not in sys.path:
|
||||
sys.path.insert(0, dir)
|
||||
|
||||
def parse_cmdline(argv):
|
||||
# parse command-line
|
||||
def usage():
|
||||
print >> sys.stderr, 'usage:'
|
||||
print >> sys.stderr, ' python bb.py'
|
||||
## print >> sys.stderr, ' python bb.py [-w/--webbrowser=no]'
|
||||
## print >> sys.stderr, 'where:'
|
||||
## print >> sys.stderr, ' -w --webbrowser=no don''t automatically start web browser'
|
||||
print >> sys.stderr, 'or:'
|
||||
print >> sys.stderr, ' python bb.py [level-file.bin] [-m] [-b#] [-s#] [-l#] [-M#]'
|
||||
print >> sys.stderr, 'with options:'
|
||||
print >> sys.stderr, ' -m --metaserver register the server on the Metaserver so anyone can join'
|
||||
print >> sys.stderr, ' -b# --begin # start at board number # (default 1)'
|
||||
print >> sys.stderr, ' --start # synonym for --begin'
|
||||
print >> sys.stderr, ' --final # end at board number # (default 100)'
|
||||
print >> sys.stderr, ' -s# --step # advance board number by steps of # (default 1)'
|
||||
print >> sys.stderr, ' -l# --lives # limit the number of lives to #'
|
||||
print >> sys.stderr, ' --extralife # gain extra life every # points'
|
||||
print >> sys.stderr, ' --limitlives # max # of lives player can gain in one board'
|
||||
print >> sys.stderr, ' -M# --monsters # multiply the number of monsters by #'
|
||||
print >> sys.stderr, ' (default between 1.0 and 2.0 depending on # of players)'
|
||||
print >> sys.stderr, ' -i --infinite restart the server at the end of the game'
|
||||
print >> sys.stderr, ' --port LISTEN=# set fixed tcp port for game server'
|
||||
print >> sys.stderr, ' --port HTTP=# set fixed tcp port for http server'
|
||||
print >> sys.stderr, ' -h --help display this text'
|
||||
#print >> sys.stderr, ' -rxxx record the game in file xxx'
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from getopt import gnu_getopt as getopt
|
||||
except ImportError:
|
||||
from getopt import getopt
|
||||
from getopt import error
|
||||
try:
|
||||
opts, args = getopt(argv, 'mb:s:l:M:ih',
|
||||
['metaserver', 'start=', 'step=',
|
||||
'lives=', 'monsters=', 'infinite', 'help',
|
||||
'extralife=', 'limitlives=', 'final=',
|
||||
'saveurlto=', 'quiet', 'port=', 'makeimages'])
|
||||
except error, e:
|
||||
print >> sys.stderr, 'bb.py: %s' % str(e)
|
||||
print >> sys.stderr
|
||||
usage()
|
||||
|
||||
options = {}
|
||||
#webbrowser = 1
|
||||
save_url_to = None
|
||||
quiet = 0
|
||||
for key, value in opts:
|
||||
if key in ('-m', '--metaserver'):
|
||||
options['metaserver'] = 1
|
||||
elif key in ('-b', '--start', '--begin'):
|
||||
options['beginboard'] = int(value)
|
||||
elif key in ('-s', '--step'):
|
||||
options['stepboard'] = int(value)
|
||||
elif key in ('-l', '--lives'):
|
||||
options['limitlives'] = int(value)
|
||||
elif key in ('--limitlives'):
|
||||
options['lifegainlimit'] = int(value)
|
||||
elif key in ('--final'):
|
||||
options['finalboard'] = int(value)
|
||||
if options['finalboard'] < options['beginboard']:
|
||||
print >> sys.stderr, 'bb.py: final board value must be larger than begin board.'
|
||||
sys.exit(1)
|
||||
elif key in ('--extralife'):
|
||||
options['extralife'] = int(value)
|
||||
elif key in ('-M', '--monsters'):
|
||||
options['monsters'] = float(value)
|
||||
elif key in ('-i', '--infinite'):
|
||||
options['autoreset'] = 1
|
||||
elif key in ('-h', '--help'):
|
||||
usage()
|
||||
elif key == '--saveurlto':
|
||||
save_url_to = value
|
||||
elif key == '--quiet':
|
||||
quiet = 1
|
||||
elif key == '--port':
|
||||
portname, portvalue = value.split('=')
|
||||
portvalue = int(portvalue)
|
||||
import msgstruct
|
||||
msgstruct.PORTS[portname] = portvalue
|
||||
elif key == '--makeimages':
|
||||
import images
|
||||
sys.exit(0)
|
||||
#elif key in ('-w', '--webbrowser'):
|
||||
# webbrowser = value.startswith('y')
|
||||
if args:
|
||||
if len(args) > 1:
|
||||
print >> sys.stderr, 'bb.py: multiple level files specified'
|
||||
sys.exit(1)
|
||||
levelfile = os.path.abspath(args[0])
|
||||
os.chdir(LOCALDIR)
|
||||
BubBobGame(levelfile, **options)
|
||||
else:
|
||||
if options:
|
||||
print >> sys.stderr, 'bb.py: command-line options ignored'
|
||||
start_metaserver(save_url_to, quiet)
|
||||
|
||||
def start_metaserver(save_url_to, quiet):
|
||||
os.chdir(LOCALDIR)
|
||||
setuppath('http2')
|
||||
import httppages
|
||||
httppages.main(BubBobGame, save_url_to, quiet)
|
||||
|
||||
|
||||
def setup():
|
||||
keybmp = gamesrv.getbitmap(os.path.join('images', 'keys.ppm'))
|
||||
def keybmplist(x):
|
||||
return [keybmp.geticon(x, y, 32, 32) for y in range(0, 128, 32)]
|
||||
BubBobGame.FnKeys = [
|
||||
("right", keybmplist(0), "kRight"),
|
||||
("left", keybmplist(32), "kLeft"),
|
||||
("jump", keybmplist(64), "kJump"),
|
||||
("fire", keybmplist(96), "kFire"),
|
||||
("-right", [], "kmRight"),
|
||||
("-left", [], "kmLeft"),
|
||||
("-jump", [], "kmJump"),
|
||||
("-fire", [], "kmFire"),
|
||||
]
|
||||
|
||||
setup()
|
||||
|
||||
def main():
|
||||
parse_cmdline(sys.argv[1:])
|
||||
if not PROFILE:
|
||||
gamesrv.mainloop()
|
||||
else:
|
||||
import profile
|
||||
prof = profile.Profile()
|
||||
try:
|
||||
prof = prof.run('gamesrv.mainloop()')
|
||||
finally:
|
||||
prof.dump_stats('profbb')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -20,7 +20,8 @@ def meancolor(img):
|
||||
b1 += b
|
||||
return r1/count, g1/count, b1/count
|
||||
|
||||
def addshadow(img, (r1, g1, b1), depth=8):
|
||||
def addshadow(img, xxx_todo_changeme, depth=8):
|
||||
(r1, g1, b1) = xxx_todo_changeme
|
||||
w = len(img[0])
|
||||
h = len(img)
|
||||
pad = depth * [keycol]
|
||||
@ -35,7 +36,8 @@ def addshadow(img, (r1, g1, b1), depth=8):
|
||||
result[1+d+i][w+d] = color
|
||||
return result
|
||||
|
||||
def addrshadow(img, (r1, g1, b1), depth=8):
|
||||
def addrshadow(img, xxx_todo_changeme1, depth=8):
|
||||
(r1, g1, b1) = xxx_todo_changeme1
|
||||
w = len(img[0])
|
||||
h = len(img)
|
||||
pad = depth * [keycol]
|
||||
@ -49,17 +51,17 @@ def addrshadow(img, (r1, g1, b1), depth=8):
|
||||
|
||||
|
||||
def load(filename):
|
||||
print "Loading %s..." % filename
|
||||
print("Loading %s..." % filename)
|
||||
Bin = macbinary.MacBinary(filename)
|
||||
levels = {}
|
||||
mnstrlist = [Nasty, Monky, Ghosty, Flappy,
|
||||
Springy, Orcy, Gramy, Blitzy]
|
||||
|
||||
for key, lvl in Bin['LEVL'].items():
|
||||
for key, lvl in list(Bin['LEVL'].items()):
|
||||
d = lvl.getlevel(mnstrlist)
|
||||
class BinBoard(boards.Board):
|
||||
pass
|
||||
for key1, value1 in d.items():
|
||||
for key1, value1 in list(d.items()):
|
||||
setattr(BinBoard, key1, value1)
|
||||
levels[key] = BinBoard
|
||||
|
||||
|
122
bubbob/binboards.py.bak
Normal file
122
bubbob/binboards.py.bak
Normal file
@ -0,0 +1,122 @@
|
||||
import macbinary
|
||||
import boards
|
||||
import gamesrv
|
||||
from mnstrmap import Nasty, Monky, Ghosty, Flappy
|
||||
from mnstrmap import Springy, Orcy, Gramy, Blitzy
|
||||
from images import KEYCOL
|
||||
|
||||
keycol = (KEYCOL & 0xFF,
|
||||
(KEYCOL>>8) & 0xFF,
|
||||
(KEYCOL>>16) & 0xFF)
|
||||
|
||||
|
||||
def meancolor(img):
|
||||
r1 = g1 = b1 = 0
|
||||
count = float(len(img) * len(img[0]))
|
||||
for line in img:
|
||||
for r, g, b in line:
|
||||
r1 += r
|
||||
g1 += g
|
||||
b1 += b
|
||||
return r1/count, g1/count, b1/count
|
||||
|
||||
def addshadow(img, (r1, g1, b1), depth=8):
|
||||
w = len(img[0])
|
||||
h = len(img)
|
||||
pad = depth * [keycol]
|
||||
result = [line + pad for line in img] + [
|
||||
(w+depth) * [keycol] for d in range(depth)]
|
||||
for d in range(depth):
|
||||
f = 1.0 - float(d)/depth
|
||||
color = (r1 * f, g1 * f, b1 * f)
|
||||
for i in range(w):
|
||||
result[h+d][1+d+i] = color
|
||||
for i in range(h):
|
||||
result[1+d+i][w+d] = color
|
||||
return result
|
||||
|
||||
def addrshadow(img, (r1, g1, b1), depth=8):
|
||||
w = len(img[0])
|
||||
h = len(img)
|
||||
pad = depth * [keycol]
|
||||
result = [line + pad for line in img]
|
||||
for d in range(depth):
|
||||
f = 1.0 - float(d)/depth
|
||||
color = (r1 * f, g1 * f, b1 * f)
|
||||
for i in range(h):
|
||||
result[i][w+d] = color
|
||||
return result
|
||||
|
||||
|
||||
def load(filename):
|
||||
print "Loading %s..." % filename
|
||||
Bin = macbinary.MacBinary(filename)
|
||||
levels = {}
|
||||
mnstrlist = [Nasty, Monky, Ghosty, Flappy,
|
||||
Springy, Orcy, Gramy, Blitzy]
|
||||
|
||||
for key, lvl in Bin['LEVL'].items():
|
||||
d = lvl.getlevel(mnstrlist)
|
||||
class BinBoard(boards.Board):
|
||||
pass
|
||||
for key1, value1 in d.items():
|
||||
setattr(BinBoard, key1, value1)
|
||||
levels[key] = BinBoard
|
||||
|
||||
def loader(code, rsrc=Bin['ppat'], cache={}):
|
||||
try:
|
||||
return cache[code]
|
||||
except KeyError:
|
||||
pass
|
||||
keycol1 = None
|
||||
bid = code[0]
|
||||
result = None
|
||||
if code[1] == 'l':
|
||||
# left border wall
|
||||
img = rsrc[bid + 228].getimage()
|
||||
color = meancolor(img)
|
||||
img = [line[:32] for line in img]
|
||||
result = addrshadow(img, color)
|
||||
elif code[1] == 'r':
|
||||
# right border wall
|
||||
img = rsrc[bid + 228].getimage()
|
||||
w = len(img[0])
|
||||
assert w in (32, 64), bid
|
||||
if w == 64:
|
||||
color = meancolor(img)
|
||||
img = [line[32:64] for line in img]
|
||||
result = addrshadow(img, color)
|
||||
else:
|
||||
# normal wall
|
||||
dx, dy = code[1:]
|
||||
img = rsrc[bid + 128].getimage()
|
||||
w = len(img[0])
|
||||
h = len(img)
|
||||
assert w & 15 == h & 15 == 0, bid
|
||||
dx *= 16
|
||||
dy *= 16
|
||||
if dx < w and dy < h:
|
||||
color = meancolor(img)
|
||||
img = [line[dx:dx+16] for line in img[dy:dy+16]]
|
||||
result = addshadow(img, color)
|
||||
keycol1 = KEYCOL
|
||||
if result is not None:
|
||||
w, h, data = macbinary.image2rgb(result)
|
||||
ppmdata = "P6\n%d %d\n255\n%s" % (w, h, data)
|
||||
result = gamesrv.newbitmap(ppmdata, keycol1), (0, 0, w, h)
|
||||
cache[code] = result
|
||||
return result
|
||||
|
||||
def bin_haspat(code, loader=loader):
|
||||
try:
|
||||
return loader(code) is not None
|
||||
except KeyError:
|
||||
return 0
|
||||
def bin_loadpattern(code, keycol=None, loader=loader):
|
||||
result = loader(code)
|
||||
assert result is not None, code
|
||||
return result
|
||||
|
||||
boards.haspat = bin_haspat
|
||||
boards.loadpattern = bin_loadpattern
|
||||
return levels
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import random, os, sys, math
|
||||
import gamesrv
|
||||
import images
|
||||
@ -72,8 +72,8 @@ class Board(Copyable):
|
||||
def enter(self, complete=1, inplace=0, fastreenter=False):
|
||||
global curboard
|
||||
if inplace:
|
||||
print "Re -",
|
||||
print "Entering board", self.num+1
|
||||
print("Re -", end=' ')
|
||||
print("Entering board", self.num+1)
|
||||
self.set_musics()
|
||||
# add board walls
|
||||
l = self.sprites.setdefault('walls', [])
|
||||
@ -96,9 +96,9 @@ class Board(Copyable):
|
||||
righticon = patget((self.num, 'r'))
|
||||
else:
|
||||
righticon = lefticon
|
||||
xrange = range(2, self.width-2)
|
||||
xrange = list(range(2, self.width-2))
|
||||
else:
|
||||
xrange = range(self.width)
|
||||
xrange = list(range(self.width))
|
||||
lefticon = righticon = None
|
||||
|
||||
if BOARD_BKGND == 1:
|
||||
@ -255,7 +255,7 @@ class Board(Copyable):
|
||||
|
||||
def reorder_walls(self):
|
||||
walls_by_pos = self.walls_by_pos
|
||||
items = [(yx, w1.ico) for yx, w1 in walls_by_pos.items()]
|
||||
items = [(yx, w1.ico) for yx, w1 in list(walls_by_pos.items())]
|
||||
if not items:
|
||||
return # otherwise self.sprites['walls'] would be emptied
|
||||
items.sort()
|
||||
@ -289,7 +289,7 @@ class Board(Copyable):
|
||||
yield 0.9
|
||||
i = 0
|
||||
sprites = []
|
||||
for l in self.sprites.values():
|
||||
for l in list(self.sprites.values()):
|
||||
sprites += l
|
||||
self.sprites.clear()
|
||||
self.walls_by_pos.clear()
|
||||
@ -440,7 +440,7 @@ def loadmodules(force=0):
|
||||
elif os.path.isfile(os.path.join(m, '__init__.py')):
|
||||
modulefiles[m] = os.path.join(m, '__init__.py')
|
||||
mtimes = {}
|
||||
for m, mfile in modulefiles.items():
|
||||
for m, mfile in list(modulefiles.items()):
|
||||
mtimes[m] = os.stat(mfile).st_mtime
|
||||
reload = force or (mtimes != getattr(sys, 'ST_MTIMES', None))
|
||||
import player
|
||||
@ -449,8 +449,8 @@ def loadmodules(force=0):
|
||||
delete = hasattr(sys, 'ST_MTIMES')
|
||||
sys.ST_MTIMES = mtimes
|
||||
if delete:
|
||||
print "Reloading modules."
|
||||
for m, mfile in modulefiles.items():
|
||||
print("Reloading modules.")
|
||||
for m, mfile in list(modulefiles.items()):
|
||||
if m is not None and m in sys.modules:
|
||||
del sys.modules[m]
|
||||
|
||||
@ -471,12 +471,12 @@ def loadmodules(force=0):
|
||||
del boards.BoardList[:]
|
||||
if levelfilename.lower().endswith('.py'):
|
||||
levels = {}
|
||||
print 'Source level file:', levelfilename
|
||||
execfile(levelfilename, levels)
|
||||
print('Source level file:', levelfilename)
|
||||
exec(compile(open(levelfilename, "rb").read(), levelfilename, 'exec'), levels)
|
||||
if 'GenerateLevels' in levels:
|
||||
levels = levels['GenerateLevels']()
|
||||
if isinstance(levels, list):
|
||||
levels = dict(zip(range(len(levels)), levels))
|
||||
levels = dict(list(zip(list(range(len(levels))), levels)))
|
||||
else:
|
||||
import binboards
|
||||
levels = binboards.load(levelfilename)
|
||||
@ -555,7 +555,7 @@ def wait_for_one_player():
|
||||
if random.random() > 0.4321:
|
||||
try:
|
||||
key, (filename, (x, y, w, h)) = random.choice(
|
||||
images.sprmap.items())
|
||||
list(images.sprmap.items()))
|
||||
except:
|
||||
w = h = 0
|
||||
if w == h == 32:
|
||||
@ -1116,7 +1116,7 @@ def extra_aquarium():
|
||||
for s in waves_sprites:
|
||||
s.kill()
|
||||
BubPlayer.SuperFish = True
|
||||
fishplayers(-sys.maxint)
|
||||
fishplayers(-sys.maxsize)
|
||||
|
||||
def extra_walls_falling():
|
||||
walls_by_pos = curboard.walls_by_pos
|
||||
@ -1156,7 +1156,7 @@ def single_blocks_falling(xylist):
|
||||
|
||||
def extra_display_repulse(cx, cy, dlimit=5000, dfactor=1000):
|
||||
offsets = {}
|
||||
for s in gamesrv.sprites_by_n.values():
|
||||
for s in list(gamesrv.sprites_by_n.values()):
|
||||
x, y = s.getdisplaypos()
|
||||
if x is not None:
|
||||
dx = x - cx
|
||||
@ -1172,7 +1172,7 @@ def extra_display_repulse(cx, cy, dlimit=5000, dfactor=1000):
|
||||
while offsets:
|
||||
prevoffsets = offsets
|
||||
offsets = {}
|
||||
for s, (dx, dy) in prevoffsets.items():
|
||||
for s, (dx, dy) in list(prevoffsets.items()):
|
||||
if s.alive:
|
||||
if dx < 0:
|
||||
dx += max(1, (-dx)//5)
|
||||
@ -1212,7 +1212,7 @@ def extra_light_off(timeout, icocache={}):
|
||||
for bubber in playerlist:
|
||||
for dragon in bubber.dragons:
|
||||
dragons[dragon] = True
|
||||
for s in gamesrv.sprites_by_n.values():
|
||||
for s in list(gamesrv.sprites_by_n.values()):
|
||||
try:
|
||||
ico = icocache[s.ico, s in dragons]
|
||||
except KeyError:
|
||||
@ -1220,12 +1220,12 @@ def extra_light_off(timeout, icocache={}):
|
||||
icocache[s.ico, s in dragons] = ico
|
||||
s.setdisplayicon(ico)
|
||||
yield 0
|
||||
for s in gamesrv.sprites_by_n.values():
|
||||
for s in list(gamesrv.sprites_by_n.values()):
|
||||
s.setdisplayicon(s.ico)
|
||||
|
||||
def extra_swap_up_down(N=27):
|
||||
# unregister all walls
|
||||
walls = curboard.walls_by_pos.items()
|
||||
walls = list(curboard.walls_by_pos.items())
|
||||
walls.sort()
|
||||
if not walls:
|
||||
return
|
||||
@ -1317,7 +1317,7 @@ def extra_make_random_level(cx=None, cy=None, repeat_delay=200):
|
||||
localdir = os.path.dirname(__file__)
|
||||
filename = os.path.join(localdir, 'levels', 'RandomLevels.py')
|
||||
d = {}
|
||||
execfile(filename, d)
|
||||
exec(compile(open(filename, "rb").read(), filename, 'exec'), d)
|
||||
Level = d['GenerateSingleLevel'](curboard.width, curboard.height)
|
||||
lvl = Level(curboard.num)
|
||||
walllist = []
|
||||
@ -1413,7 +1413,7 @@ def initsubgame(music, displaypoints):
|
||||
|
||||
def register(dict):
|
||||
global width, height, bwidth, bheight, bheightmod
|
||||
items = dict.items()
|
||||
items = list(dict.items())
|
||||
items.sort()
|
||||
for name, board in items:
|
||||
try:
|
||||
@ -1433,8 +1433,8 @@ def register(dict):
|
||||
test = B(-1)
|
||||
assert test.width == width, "some boards have a different width"
|
||||
assert test.height == height, "some boards have a different height"
|
||||
except Exception, e:
|
||||
print 'Caught "%s" in level "%s":' % (e, B.__name__)
|
||||
except Exception as e:
|
||||
print('Caught "%s" in level "%s":' % (e, B.__name__))
|
||||
raise e
|
||||
bwidth = width*CELL
|
||||
bheight = height*CELL
|
||||
|
1470
bubbob/boards.py.bak
Normal file
1470
bubbob/boards.py.bak
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import random, os, math
|
||||
import random as random_module
|
||||
import gamesrv
|
||||
@ -646,13 +646,13 @@ class Megabonus(Bonus):
|
||||
return self.y == boards.bheight - CELL - self.ico.h
|
||||
|
||||
def kill(self):
|
||||
for bubble in self.bubbles.values():
|
||||
for bubble in list(self.bubbles.values()):
|
||||
bubble.pop()
|
||||
Bonus.kill(self)
|
||||
|
||||
def taken(self, dragon):
|
||||
poplist = [dragon]
|
||||
for bubble in self.bubbles.values():
|
||||
for bubble in list(self.bubbles.values()):
|
||||
bubble.pop(poplist)
|
||||
|
||||
def bubbles_position(self):
|
||||
@ -712,7 +712,7 @@ class Megabonus(Bonus):
|
||||
while 1:
|
||||
for t in range(2):
|
||||
yield None
|
||||
bubbles = [dxy for dxy, b in self.bubbles.items()
|
||||
bubbles = [dxy for dxy, b in list(self.bubbles.items())
|
||||
if b.bubber is bubber]
|
||||
if not bubbles:
|
||||
break
|
||||
@ -776,7 +776,7 @@ class Megabonus(Bonus):
|
||||
while 1:
|
||||
for cycle in [1]*8 + [2]*10 + [1]*8 + [0]*10:
|
||||
yield None
|
||||
for (dx, dy), bubble in bubbles.items():
|
||||
for (dx, dy), bubble in list(bubbles.items()):
|
||||
if not hasattr(bubble, 'poplist'):
|
||||
if 0: # disabled clipping
|
||||
if (dx, north[dy]) in bubbles:
|
||||
@ -822,7 +822,7 @@ class Megabonus(Bonus):
|
||||
yield None
|
||||
bubble.pop(poplist)
|
||||
|
||||
for bubble in self.bubbles.values():
|
||||
for bubble in list(self.bubbles.values()):
|
||||
bubble.gen.append(bubble_timeout(bubble, self.vspeed))
|
||||
self.bubbles.clear()
|
||||
self.kill()
|
||||
@ -1249,7 +1249,7 @@ class Lollipop(TemporaryBonus):
|
||||
def taken(self, dragon):
|
||||
dragon.dcap['left2right'] = -dragon.dcap['left2right']
|
||||
if self.big:
|
||||
perm = range(4)
|
||||
perm = list(range(4))
|
||||
while perm[0] == 0 or perm[1] == 1 or perm[2] == 2 or perm[3] == 3:
|
||||
random.shuffle(perm)
|
||||
names = ('key_left', 'key_right', 'key_jump', 'key_fire')
|
||||
@ -1589,7 +1589,7 @@ class Egg(RandomBonus):
|
||||
d1 = dragons[0]
|
||||
d1.move(x, y)
|
||||
d1.dcap['shield'] = 50
|
||||
for d1, bubber2 in xchg.items():
|
||||
for d1, bubber2 in list(xchg.items()):
|
||||
d1.bubber.dragons.remove(d1)
|
||||
d1.bubber = bubber2
|
||||
bubber2.dragons.append(d1)
|
||||
@ -1705,7 +1705,7 @@ class Chestnut(RandomBonus):
|
||||
try:
|
||||
import statesaver
|
||||
except ImportError:
|
||||
print "'statesaver' module not compiled, no clock bonus"
|
||||
print("'statesaver' module not compiled, no clock bonus")
|
||||
Clock = None
|
||||
else:
|
||||
import new
|
||||
@ -1734,11 +1734,11 @@ else:
|
||||
boards.curboard,
|
||||
images.ActiveSprites,
|
||||
images.SpritesByLoc,
|
||||
BubPlayer.__dict__.items(),
|
||||
list(BubPlayer.__dict__.items()),
|
||||
gamesrv.sprites,
|
||||
gamesrv.sprites_by_n,
|
||||
ps,
|
||||
images.Snd.__dict__.items(),
|
||||
list(images.Snd.__dict__.items()),
|
||||
)
|
||||
#import pdb; pdb.set_trace()
|
||||
return statesaver.copy(topstate)
|
||||
@ -1938,8 +1938,8 @@ else:
|
||||
random = random_module.Random()
|
||||
localrandom = DustStar.localrandom
|
||||
self.state = 'pre'
|
||||
self.randombase1 = hash(localrandom.random()) * 914971L
|
||||
self.randombase2 = hash(localrandom.random()) * 914971L
|
||||
self.randombase1 = hash(localrandom.random()) * 914971
|
||||
self.randombase2 = hash(localrandom.random()) * 914971
|
||||
self.saved_next = None
|
||||
self.saved_last = self
|
||||
random.seed(self.randombase1)
|
||||
@ -2019,7 +2019,7 @@ else:
|
||||
for s in touching:
|
||||
if isinstance(s, interact):
|
||||
s.touched(ghost)
|
||||
for d, ghost in self.ghosts.items():
|
||||
for d, ghost in list(self.ghosts.items()):
|
||||
if d not in new_ghosts:
|
||||
ghost.kill()
|
||||
self.ghosts = new_ghosts
|
||||
@ -2036,12 +2036,12 @@ else:
|
||||
DragonBubble(*args)
|
||||
if self.state == 'restoring' and self.ghosts:
|
||||
self.state = 'post'
|
||||
for ghost in self.ghosts.values():
|
||||
for ghost in list(self.ghosts.values()):
|
||||
ghost.integrate()
|
||||
|
||||
def flush_ghosts(self):
|
||||
if self.latest_entries:
|
||||
for ghost in self.ghosts.values():
|
||||
for ghost in list(self.ghosts.values()):
|
||||
ghost.disintegrate()
|
||||
self.latest_entries.clear()
|
||||
self.dragonlist = None
|
||||
@ -2282,7 +2282,7 @@ class Sheep(RandomBonus):
|
||||
vy = 0
|
||||
while delta or slist:
|
||||
ndelta = {}
|
||||
for p, dp in delta.items():
|
||||
for p, dp in list(delta.items()):
|
||||
if dp:
|
||||
d1 = max(-250, min(250, dp))
|
||||
p.givepoints(d1)
|
||||
@ -2379,7 +2379,7 @@ class Donut(RandomBonus):
|
||||
b.kill()
|
||||
|
||||
|
||||
Classes = [c for c in globals().values()
|
||||
Classes = [c for c in list(globals().values())
|
||||
if type(c)==type(RandomBonus) and issubclass(c, RandomBonus)]
|
||||
Classes.remove(RandomBonus)
|
||||
Classes.remove(TemporaryBonus)
|
||||
@ -2500,5 +2500,5 @@ def __cheat(c):
|
||||
c[0] = globals()[c[0]]
|
||||
assert issubclass(c[0], Bonus)
|
||||
Cheat.append(tuple(c))
|
||||
import __builtin__
|
||||
__builtin__.__cheat = __cheat
|
||||
import builtins
|
||||
builtins.__cheat = __cheat
|
||||
|
2504
bubbob/bonuses.py.bak
Normal file
2504
bubbob/bonuses.py.bak
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import random, math
|
||||
import gamesrv
|
||||
import images
|
||||
@ -19,7 +19,7 @@ bubble_wind = {
|
||||
|
||||
|
||||
class Bubble(ActiveSprite):
|
||||
exploding_bubbles = range(131,136)
|
||||
exploding_bubbles = list(range(131,136))
|
||||
red_bubbles = [156, 157, 156, 155]
|
||||
white_bubbles = [164, 165, 164, 163]
|
||||
pink_bubbles = [172, 173, 172, 171]
|
||||
@ -233,7 +233,7 @@ class Bubble(ActiveSprite):
|
||||
ico = icons[1]
|
||||
yfrac = 0.0
|
||||
self.dragon_jumped = False
|
||||
for i in xrange(timeout):
|
||||
for i in range(timeout):
|
||||
hspeed = random.randrange(2, 4)
|
||||
if ico is not icons[1]:
|
||||
icotimeout += 1
|
||||
@ -410,7 +410,8 @@ class DragonBubble(Bubble):
|
||||
hspeed = -hspeed
|
||||
self.gen.append(self.throw_bubble(hspeed, special_bubble, (acos,asin)))
|
||||
|
||||
def throw_bubble(self, hspeed, special_bubble=None, (acos,asin)=(1,0)):
|
||||
def throw_bubble(self, hspeed, special_bubble=None, xxx_todo_changeme=(1,0)):
|
||||
(acos,asin) = xxx_todo_changeme
|
||||
from monsters import Monster
|
||||
nx = self.x
|
||||
ny = self.y
|
||||
@ -680,7 +681,7 @@ class BonusBubble(Bubble):
|
||||
def findhole(self, testline):
|
||||
holes = [x for x in range(len(testline)-1) if testline[x:x+2]==' ']
|
||||
if not holes:
|
||||
holes = range(2, len(testline)-3)
|
||||
holes = list(range(2, len(testline)-3))
|
||||
return random.choice(holes) * CELL
|
||||
|
||||
def thrown_bubble(self, x, y, hspeed, acossin):
|
||||
@ -688,7 +689,8 @@ class BonusBubble(Bubble):
|
||||
self.move(x, y)
|
||||
self.gen = [self.throwing_bubble(hspeed, acossin, self.imgsetter)]
|
||||
|
||||
def throwing_bubble(self, hspeed, (acos,asin), restore_img):
|
||||
def throwing_bubble(self, hspeed, xxx_todo_changeme1, restore_img):
|
||||
(acos,asin) = xxx_todo_changeme1
|
||||
nx = self.x
|
||||
ny = self.y
|
||||
while abs(hspeed) >= 4.0:
|
||||
@ -962,7 +964,7 @@ class WaterCell(ActiveSprite):
|
||||
ActiveSprite.kill(self)
|
||||
if not self.watercells[None].alive:
|
||||
del self.watercells[None]
|
||||
for s in self.watercells.values():
|
||||
for s in list(self.watercells.values()):
|
||||
if s.alive:
|
||||
s.in_charge()
|
||||
break
|
||||
@ -974,7 +976,7 @@ class WaterCell(ActiveSprite):
|
||||
|
||||
new = []
|
||||
nwatercells = {None: self}
|
||||
for key, s in watercells.items():
|
||||
for key, s in list(watercells.items()):
|
||||
if key:
|
||||
x, y, dir = key
|
||||
if s.repeat:
|
||||
@ -1012,7 +1014,7 @@ class WaterCell(ActiveSprite):
|
||||
for args in new:
|
||||
WaterCell(*args)
|
||||
|
||||
for key, s in watercells.items():
|
||||
for key, s in list(watercells.items()):
|
||||
if key:
|
||||
x, y, dir = key
|
||||
flag = 0
|
||||
|
1284
bubbob/bubbles.py.bak
Normal file
1284
bubbob/bubbles.py.bak
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,4 +7,4 @@ for ext in ['.py', '.bin']:
|
||||
break
|
||||
sys.argv[1] = levelfile
|
||||
|
||||
execfile('bb.py')
|
||||
exec(compile(open('bb.py', "rb").read(), 'bb.py', 'exec'))
|
||||
|
10
bubbob/command.py.bak
Normal file
10
bubbob/command.py.bak
Normal file
@ -0,0 +1,10 @@
|
||||
import os, sys
|
||||
|
||||
levels, ext = os.path.splitext(os.path.basename(sys.argv[1]))
|
||||
for ext in ['.py', '.bin']:
|
||||
levelfile = 'levels/%s%s' % (levels, ext)
|
||||
if os.path.exists(levelfile):
|
||||
break
|
||||
sys.argv[1] = levelfile
|
||||
|
||||
execfile('bb.py')
|
@ -16,7 +16,7 @@ except ImportError:
|
||||
def create_image(name,source,extralines=0,alt=''):
|
||||
if len(sys.argv) == 2 and sys.argv[1] == '-i':
|
||||
return
|
||||
print name, source
|
||||
print(name, source)
|
||||
src = open(source[0],'r')
|
||||
assert src.readline().strip() == 'P6'
|
||||
line = src.readline()
|
||||
@ -29,9 +29,9 @@ def create_image(name,source,extralines=0,alt=''):
|
||||
data = src.read()
|
||||
src.close()
|
||||
img = os.popen("convert PPM:- doc/images/"+name+'.png','w')
|
||||
print >> img, 'P6'
|
||||
print >> img, source[1][2], source[1][3]+extralines
|
||||
print >> img, c
|
||||
print('P6', file=img)
|
||||
print(source[1][2], source[1][3]+extralines, file=img)
|
||||
print(c, file=img)
|
||||
cx = source[1][0]+source[1][2]//2
|
||||
cy = source[1][1]+source[1][3]*6//7
|
||||
for y in range(source[1][1],source[1][1]+source[1][3]):
|
||||
@ -74,7 +74,7 @@ def split_name(name):
|
||||
return words
|
||||
|
||||
dfile = open('doc/bonuses.html','w')
|
||||
print >> dfile, """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
print("""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
@ -97,7 +97,7 @@ print >> dfile, """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<I>big bonus</I>
|
||||
</TD>
|
||||
</TR>
|
||||
"""
|
||||
""", file=dfile)
|
||||
#" A stupid comment to stop emacs from mis-fontifying.
|
||||
|
||||
class Potion4:
|
||||
@ -109,7 +109,7 @@ class Potion4:
|
||||
processed = {}
|
||||
|
||||
for bonus in bonuses.Classes:
|
||||
if processed.has_key(bonus):
|
||||
if bonus in processed:
|
||||
continue
|
||||
name = split_name(bonus.__name__)
|
||||
name.reverse()
|
||||
@ -125,25 +125,25 @@ def sorter(a,b):
|
||||
else:
|
||||
return 1
|
||||
|
||||
sorted_classes = processed.items()
|
||||
sorted_classes = list(processed.items())
|
||||
sorted_classes.sort(sorter)
|
||||
|
||||
for clasindex, clas in enumerate(sorted_classes):
|
||||
bonus = clas[0]
|
||||
images = ''
|
||||
name = bonus.__name__
|
||||
if bonus.__dict__.has_key('nimages'):
|
||||
if 'nimages' in bonus.__dict__:
|
||||
# A multi image entry.
|
||||
i = 0
|
||||
l = len(bonus.nimages)
|
||||
for image in bonus.nimages:
|
||||
if image == 'potion4':
|
||||
continue
|
||||
images += create_image(name+`i`, sprmap[image], alt=name)
|
||||
images += create_image(name+repr(i), sprmap[image], alt=name)
|
||||
i += 1
|
||||
if (l-3*(i/3) >= 3) and (i % 3) == 0:
|
||||
images += '<br>'
|
||||
elif bonus.__dict__.has_key('nimage'):
|
||||
elif 'nimage' in bonus.__dict__:
|
||||
images = create_image(name, sprmap[bonus.nimage], alt=name)
|
||||
doc = bonus.__doc__
|
||||
if doc == None:
|
||||
@ -155,16 +155,16 @@ for clasindex, clas in enumerate(sorted_classes):
|
||||
bgcolor = '"#E0FFE0"'
|
||||
else:
|
||||
bgcolor = 'white'
|
||||
print >> dfile, '<TR><TD width=132 align=right>',
|
||||
print >> dfile, images,
|
||||
print >> dfile, '</TD><TD width=20></TD>',
|
||||
print >> dfile, '<TD bgcolor=%s>%s</TD>' % (bgcolor, doc),
|
||||
print >> dfile, '</TD><TD width=20 bgcolor=%s></TD>' % bgcolor,
|
||||
print >> dfile, '<TD bgcolor=%s>%s</TD></TR>' % (bgcolor, bigdoc)
|
||||
print('<TR><TD width=132 align=right>', end=' ', file=dfile)
|
||||
print(images, end=' ', file=dfile)
|
||||
print('</TD><TD width=20></TD>', end=' ', file=dfile)
|
||||
print('<TD bgcolor=%s>%s</TD>' % (bgcolor, doc), end=' ', file=dfile)
|
||||
print('</TD><TD width=20 bgcolor=%s></TD>' % bgcolor, end=' ', file=dfile)
|
||||
print('<TD bgcolor=%s>%s</TD></TR>' % (bgcolor, bigdoc), file=dfile)
|
||||
|
||||
print >> dfile, """ </TABLE>
|
||||
print(""" </TABLE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
"""
|
||||
""", file=dfile)
|
||||
|
||||
dfile.close()
|
||||
|
170
bubbob/doc/bonus-doc.py.bak
Executable file
170
bubbob/doc/bonus-doc.py.bak
Executable file
@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os, sys, string, struct
|
||||
os.chdir(os.pardir)
|
||||
sys.path.insert(0, os.getcwd())
|
||||
sys.path.insert(1, os.path.abspath(os.path.join(os.pardir, 'common')))
|
||||
|
||||
from images import sprmap
|
||||
import bonuses, images
|
||||
|
||||
try:
|
||||
import psyco; psyco.full()
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
def create_image(name,source,extralines=0,alt=''):
|
||||
if len(sys.argv) == 2 and sys.argv[1] == '-i':
|
||||
return
|
||||
print name, source
|
||||
src = open(source[0],'r')
|
||||
assert src.readline().strip() == 'P6'
|
||||
line = src.readline()
|
||||
while line[0] == '#':
|
||||
line = src.readline()
|
||||
size = string.split(line)
|
||||
w = string.atoi(size[0])
|
||||
h = string.atoi(size[1])
|
||||
c = src.readline().strip()
|
||||
data = src.read()
|
||||
src.close()
|
||||
img = os.popen("convert PPM:- doc/images/"+name+'.png','w')
|
||||
print >> img, 'P6'
|
||||
print >> img, source[1][2], source[1][3]+extralines
|
||||
print >> img, c
|
||||
cx = source[1][0]+source[1][2]//2
|
||||
cy = source[1][1]+source[1][3]*6//7
|
||||
for y in range(source[1][1],source[1][1]+source[1][3]):
|
||||
for x in range(source[1][0],source[1][0]+source[1][2]):
|
||||
rgb = data[y*3*w+3*x:y*3*w+3*x+3]
|
||||
if rgb == '\x01\x01\x01':
|
||||
d = (x-cx)*(x-cx)+(y-cy)*(y-cy)*6
|
||||
if d > 255: d = 255
|
||||
rgb = chr(d)*3
|
||||
img.write(rgb)
|
||||
for y in range(y+1, y+1+extralines):
|
||||
for x in range(source[1][0],source[1][0]+source[1][2]):
|
||||
d = (x-cx)*(x-cx)+(y-cy)*(y-cy)*6
|
||||
if d > 255: d = 255
|
||||
rgb = chr(d)*3
|
||||
img.write(rgb)
|
||||
img.close()
|
||||
return html_tag(name, alt)
|
||||
|
||||
def html_tag(name, alt):
|
||||
url = 'images/%s.png' % (name,)
|
||||
f = open('doc/'+url, 'rb')
|
||||
alldata = f.read()
|
||||
f.close()
|
||||
url = 'data:image/png;base64,' + alldata.encode('base64').replace('\n','')
|
||||
return '<IMG SRC="%s" ALT="%s">' % (url, alt)
|
||||
|
||||
|
||||
def split_name(name):
|
||||
"Split a name into its words based on capitalisation."
|
||||
words = []
|
||||
word = ''
|
||||
for c in name:
|
||||
if c.isupper() and word != '':
|
||||
words.append(word)
|
||||
word = c
|
||||
else:
|
||||
word += c
|
||||
words.append(word)
|
||||
return words
|
||||
|
||||
dfile = open('doc/bonuses.html','w')
|
||||
print >> dfile, """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<META NAME="Author" CONTENT="The Bub's Brothers">
|
||||
<TITLE>The Bub's Brothers Bonuses</TITLE>
|
||||
</HEAD>
|
||||
<BODY bgcolor=white text=black>
|
||||
<TABLE cellspacing=0 border=0>
|
||||
<TR>
|
||||
<TD width=132 align=right>
|
||||
</TD>
|
||||
<TD width=20>
|
||||
</TD>
|
||||
<TD bgcolor="#80FF80" align=center>
|
||||
<I>regular bonus</I>
|
||||
</TD>
|
||||
<TD bgcolor="#80FF80" width=20>
|
||||
</TD>
|
||||
<TD bgcolor="#80FF80" align=center>
|
||||
<I>big bonus</I>
|
||||
</TD>
|
||||
</TR>
|
||||
"""
|
||||
#" A stupid comment to stop emacs from mis-fontifying.
|
||||
|
||||
class Potion4:
|
||||
"Subgame! For a while, let's play one of the seven mini-games."
|
||||
nimage = 'potion4'
|
||||
|
||||
# Some classes exists in more than one example just to increase their
|
||||
# probability. Removes the duplicate with the help of this dict.
|
||||
processed = {}
|
||||
|
||||
for bonus in bonuses.Classes:
|
||||
if processed.has_key(bonus):
|
||||
continue
|
||||
name = split_name(bonus.__name__)
|
||||
name.reverse()
|
||||
processed[bonus] = string.join(name)
|
||||
if bonus is bonuses.Potion:
|
||||
processed[Potion4] = string.join(name) + '.'
|
||||
|
||||
def sorter(a,b):
|
||||
if a[1] == b[1]:
|
||||
return 0
|
||||
elif a[1] < b[1]:
|
||||
return -1
|
||||
else:
|
||||
return 1
|
||||
|
||||
sorted_classes = processed.items()
|
||||
sorted_classes.sort(sorter)
|
||||
|
||||
for clasindex, clas in enumerate(sorted_classes):
|
||||
bonus = clas[0]
|
||||
images = ''
|
||||
name = bonus.__name__
|
||||
if bonus.__dict__.has_key('nimages'):
|
||||
# A multi image entry.
|
||||
i = 0
|
||||
l = len(bonus.nimages)
|
||||
for image in bonus.nimages:
|
||||
if image == 'potion4':
|
||||
continue
|
||||
images += create_image(name+`i`, sprmap[image], alt=name)
|
||||
i += 1
|
||||
if (l-3*(i/3) >= 3) and (i % 3) == 0:
|
||||
images += '<br>'
|
||||
elif bonus.__dict__.has_key('nimage'):
|
||||
images = create_image(name, sprmap[bonus.nimage], alt=name)
|
||||
doc = bonus.__doc__
|
||||
if doc == None:
|
||||
doc = ''
|
||||
bigdoc = getattr(bonus, 'bigdoc', None) or ''
|
||||
if hasattr(bonus, 'bigbonus'):
|
||||
assert bigdoc, "missing 'bigdoc' on %r" % (bonus,)
|
||||
if clasindex % 2 == 1:
|
||||
bgcolor = '"#E0FFE0"'
|
||||
else:
|
||||
bgcolor = 'white'
|
||||
print >> dfile, '<TR><TD width=132 align=right>',
|
||||
print >> dfile, images,
|
||||
print >> dfile, '</TD><TD width=20></TD>',
|
||||
print >> dfile, '<TD bgcolor=%s>%s</TD>' % (bgcolor, doc),
|
||||
print >> dfile, '</TD><TD width=20 bgcolor=%s></TD>' % bgcolor,
|
||||
print >> dfile, '<TD bgcolor=%s>%s</TD></TR>' % (bgcolor, bigdoc)
|
||||
|
||||
print >> dfile, """ </TABLE>
|
||||
</BODY>
|
||||
</HTML>
|
||||
"""
|
||||
|
||||
dfile.close()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -393,7 +393,7 @@ def run():
|
||||
|
||||
def setup():
|
||||
from player import BubPlayer
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
|
403
bubbob/ext1/__init__.py.bak
Normal file
403
bubbob/ext1/__init__.py.bak
Normal file
@ -0,0 +1,403 @@
|
||||
from __future__ import generators
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
from boards import CELL, HALFCELL
|
||||
from mnstrmap import GreenAndBlue
|
||||
from bubbles import BubblingEyes, Bubble
|
||||
from bonuses import Bonus
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
|
||||
localmap = {
|
||||
'ark-paddle': ('image1-%d.ppm', (0, 0, 80, 32)),
|
||||
}
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
snd_wall = gamesrv.getsample(os.path.join(LocalDir, 'wall.wav'))
|
||||
snd_brick = gamesrv.getsample(os.path.join(LocalDir, 'brick.wav'))
|
||||
|
||||
|
||||
def aget(x, y):
|
||||
if 0 <= x < curboard.width and y >= 0:
|
||||
if y >= curboard.height:
|
||||
return ' '
|
||||
return curboard.walls[y][x]
|
||||
else:
|
||||
return '#'
|
||||
|
||||
def sign(x):
|
||||
if x >= 0.0:
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
|
||||
class PaddleEyes(BubblingEyes):
|
||||
|
||||
def __init__(self, bubber, saved_caps, paddle):
|
||||
BubblingEyes.__init__(self, bubber, saved_caps, paddle)
|
||||
self.deltax = (paddle.ico.w - self.ico.w) // 2
|
||||
self.deltay = (paddle.ico.h - self.ico.h) // 2
|
||||
self.step(self.deltax, self.deltay)
|
||||
|
||||
def playing_bubble(self, paddle, accel=0.75, vmax=4.5):
|
||||
import boards
|
||||
dx = self.deltax
|
||||
dy = self.deltay
|
||||
bubber = paddle.bubber
|
||||
vx = 0.0
|
||||
fx = paddle.x
|
||||
while paddle.alive:
|
||||
wannago = bubber.wannago(self.dcap)
|
||||
if paddle.timeleft is None:
|
||||
keydy = 0
|
||||
else:
|
||||
keydy = -1
|
||||
key = ('eyes', wannago, keydy)
|
||||
if fx < 2*CELL:
|
||||
if vx < 0.0:
|
||||
vx = -vx * 0.45
|
||||
wannago = 1
|
||||
elif fx + paddle.ico.w > boards.bwidth - 2*CELL:
|
||||
if vx > 0.0:
|
||||
vx = -vx * 0.45
|
||||
wannago = -1
|
||||
if not wannago:
|
||||
if -accel <= vx <= accel:
|
||||
vx = 0
|
||||
elif vx < 0.0:
|
||||
wannago = 0.7
|
||||
else:
|
||||
wannago = -0.7
|
||||
vx += accel * wannago
|
||||
if vx < -vmax:
|
||||
vx = -vmax
|
||||
elif vx > vmax:
|
||||
vx = vmax
|
||||
fx += vx
|
||||
paddle.move(int(fx), paddle.y)
|
||||
self.move(paddle.x+dx, paddle.y+dy, images.sprget(key))
|
||||
yield None
|
||||
self.kill()
|
||||
|
||||
def bottom_up(self):
|
||||
return 0
|
||||
|
||||
|
||||
class Paddle(ActiveSprite):
|
||||
|
||||
def __init__(self, arkanoid, bubber, px, py):
|
||||
ico = images.sprget(('ark-paddle', bubber.pn))
|
||||
ActiveSprite.__init__(self, ico, px - (ico.w-2*CELL)//2,
|
||||
py - (ico.h-2*CELL)//2)
|
||||
self.arkanoid = arkanoid
|
||||
self.bubber = bubber
|
||||
self.timeleft = None
|
||||
self.gen.append(self.bounce_down())
|
||||
self.gen.append(self.bkgndstuff())
|
||||
self.arkanoid.paddles.append(self)
|
||||
|
||||
def bounce_down(self):
|
||||
import boards
|
||||
target_y = boards.bheight - self.ico.h
|
||||
fy = self.y
|
||||
vy = 0.0
|
||||
while fy < target_y or abs(vy) > 0.3:
|
||||
if fy < target_y:
|
||||
vy += 0.3
|
||||
elif vy > 0.0:
|
||||
vy = -vy / 3.0
|
||||
fy += vy
|
||||
self.move(self.x, int(fy))
|
||||
yield None
|
||||
while self.y > target_y:
|
||||
self.step(0, -2)
|
||||
yield None
|
||||
self.move(self.x, target_y)
|
||||
self.gen.append(self.wait_and_shoot())
|
||||
|
||||
def wait_and_shoot(self):
|
||||
timeout = 30
|
||||
while timeout > 0:
|
||||
timeout -= self.arkanoid.ready
|
||||
yield None
|
||||
self.gen.append(self.catch(Ball(self)))
|
||||
|
||||
def catch(self, ball):
|
||||
import boards
|
||||
while ball.alive:
|
||||
if ball.y > boards.bheight//2+1 and ball.vy > 0.0:
|
||||
deltay = self.y - Ball.Y_MARGIN - ball.y
|
||||
self.timeleft = deltay / ball.vy
|
||||
#if -1.25 <= self.timeleft <= 0.5:
|
||||
if -12 <= deltay <= 1:
|
||||
ball.bouncepad(self.arkanoid.paddles)
|
||||
yield None
|
||||
self.timeleft = None
|
||||
if ball.missed:
|
||||
self.kill()
|
||||
|
||||
def kill(self):
|
||||
images.Snd.Pop.play(1.0, pad=0.0)
|
||||
images.Snd.Pop.play(1.0, pad=1.0)
|
||||
ico = images.sprget(Bubble.exploding_bubbles[0])
|
||||
for i in range(11):
|
||||
s = ActiveSprite(ico,
|
||||
self.x + random.randrange(self.ico.w) - CELL,
|
||||
self.y + random.randrange(self.ico.h) - CELL)
|
||||
s.gen.append(s.die(Bubble.exploding_bubbles))
|
||||
try:
|
||||
self.arkanoid.paddles.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
ActiveSprite.kill(self)
|
||||
|
||||
def bkgndstuff(self):
|
||||
while 1:
|
||||
if self.timeleft is not None:
|
||||
self.arkanoid.order.append((self.timeleft, self))
|
||||
yield None
|
||||
touching = images.touching(self.x+1, self.y+1,
|
||||
self.ico.w-2, self.ico.h-2)
|
||||
touching.reverse()
|
||||
for s in touching:
|
||||
if isinstance(s, Bonus):
|
||||
s.touched(self)
|
||||
|
||||
def score(self, hits):
|
||||
bricks = self.arkanoid.bricks
|
||||
bricks[self.bubber] = bricks.get(self.bubber, 0) + hits
|
||||
self.bubber.givepoints(125*(2**hits))
|
||||
|
||||
|
||||
class Ball(ActiveSprite):
|
||||
|
||||
Y_MARGIN = 20
|
||||
SPEED = 5.8
|
||||
|
||||
def __init__(self, paddle):
|
||||
self.paddle = paddle
|
||||
imglist1 = GreenAndBlue.new_bubbles[paddle.bubber.pn]
|
||||
ActiveSprite.__init__(self, images.sprget(imglist1[0]),
|
||||
paddle.x + paddle.ico.w//2,
|
||||
paddle.y - Ball.Y_MARGIN)
|
||||
self.missed = 0
|
||||
self.setimages(self.imgseq(imglist1[1:], 6))
|
||||
self.bounceangle(0.2)
|
||||
self.gen.append(self.flying())
|
||||
|
||||
def bouncepad(self, paddles):
|
||||
for paddle in paddles:
|
||||
dx = (self.x + self.ico.w//2) - (paddle.x + paddle.ico.w//2)
|
||||
dxmax = paddle.ico.w//2
|
||||
angle = float(dx) / dxmax
|
||||
if 0.0 <= angle <= 1.0:
|
||||
angle = angle * 1.111 + 0.07
|
||||
elif -1.0 <= angle <= 0.0:
|
||||
angle = angle * 1.111 - 0.07
|
||||
else:
|
||||
continue
|
||||
self.bounceangle(angle)
|
||||
self.play(snd_wall)
|
||||
break
|
||||
|
||||
def bounceangle(self, angle):
|
||||
self.vx = math.sin(angle) * self.SPEED
|
||||
self.vy = - math.cos(angle) * self.SPEED
|
||||
|
||||
def flying(self):
|
||||
import boards
|
||||
fx = self.x
|
||||
fy = self.y
|
||||
while self.y < boards.bheight:
|
||||
fx += self.vx
|
||||
fy += self.vy
|
||||
self.move(int(fx), int(fy))
|
||||
yield None
|
||||
cx = self.x // CELL + 1
|
||||
cy = self.y // CELL + 1
|
||||
dx = sign(self.vx)
|
||||
dy = sign(self.vy)
|
||||
hits = 0.0
|
||||
if aget(cx, cy) == '#':
|
||||
hits += self.ahit(cx, cy, 0, 0)
|
||||
if aget(cx+dx, cy) == '#':
|
||||
hits += self.ahit(cx+dx, cy, 0, dy)
|
||||
self.vx = -self.vx
|
||||
if aget(cx, cy+dy) == '#':
|
||||
hits += self.ahit(cx, cy+dy, dx, 0)
|
||||
self.vy = -self.vy
|
||||
if hits:
|
||||
hits = int(hits)
|
||||
if hits:
|
||||
self.paddle.score(hits)
|
||||
self.play(snd_brick)
|
||||
else:
|
||||
self.play(snd_wall)
|
||||
self.missed = 1
|
||||
self.kill()
|
||||
|
||||
def ahit(self, cx, cy, dx, dy):
|
||||
total = 0.01
|
||||
for i in (-1, 0, 1):
|
||||
x = cx + i*dx
|
||||
y = cy + i*dy
|
||||
if (2 <= x < curboard.width - 2 and 0 <= y < curboard.height and
|
||||
aget(x, y) == '#'):
|
||||
curboard.killwall(x, y)
|
||||
self.paddle.arkanoid.killedbricks += 1
|
||||
total += 1.0
|
||||
return total
|
||||
|
||||
def pop(self):
|
||||
self.play(images.Snd.Pop)
|
||||
self.gen = [self.die(Bubble.exploding_bubbles)]
|
||||
|
||||
|
||||
class Arkanoid:
|
||||
|
||||
def bgen(self, limittime = 60.1): # 0:60
|
||||
import boards
|
||||
from player import BubPlayer
|
||||
|
||||
self.bricks = {}
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
|
||||
tc = boards.TimeCounter(limittime)
|
||||
self.ready = 0
|
||||
self.builddelay = {}
|
||||
self.nbbricks = 0
|
||||
self.order = []
|
||||
self.paddles = []
|
||||
#finish = 0
|
||||
for t in self.frame():
|
||||
self.order_paddles()
|
||||
t = boards.normal_frame()
|
||||
self.build_paddles()
|
||||
yield t
|
||||
#if len(self.paddles) == 0:
|
||||
# finish += 1
|
||||
# if finish == 20:
|
||||
# break
|
||||
#else:
|
||||
# finish = 0
|
||||
tc.update(t)
|
||||
if tc.time == 0.0:
|
||||
break
|
||||
if (BubPlayer.FrameCounter & 15) == 7:
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bonus):
|
||||
s.timeout = 0 # bonuses stay
|
||||
elif isinstance(s, Bubble):
|
||||
s.pop()
|
||||
|
||||
tc.restore()
|
||||
self.ready = 0
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, Ball):
|
||||
s.pop()
|
||||
for t in boards.result_ranking(self.bricks, self.nbbricks):
|
||||
self.build_paddles()
|
||||
yield t
|
||||
self.remove_paddles()
|
||||
self.unframe()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
return self.bricks.get(bubber, 0)
|
||||
|
||||
def frame(self):
|
||||
for y in range(curboard.height-1, curboard.height//2, -1):
|
||||
yield None
|
||||
yield None
|
||||
for x in range(2, curboard.width-2):
|
||||
if aget(x, y) == '#':
|
||||
curboard.killwall(x, y)
|
||||
brickline = curboard.width-4
|
||||
expected = (brickline * curboard.height) // 5
|
||||
y = curboard.height//2
|
||||
nbbricks = 0
|
||||
while y>=0 and nbbricks + (y+1)*brickline >= expected:
|
||||
yield None
|
||||
for x in range(2, curboard.width-2):
|
||||
if aget(x, y) == '#':
|
||||
nbbricks += 1
|
||||
y -= 1
|
||||
while y >= -1:
|
||||
yield None
|
||||
yield None
|
||||
for x in range(2, curboard.width-2):
|
||||
if y < 0 or aget(x, y) == ' ':
|
||||
curboard.putwall(x, y)
|
||||
nbbricks += brickline
|
||||
curboard.reorder_walls()
|
||||
y -= 1
|
||||
|
||||
nbbricks -= brickline
|
||||
self.ready = 1
|
||||
self.nbbricks = nbbricks
|
||||
self.killedbricks = 0
|
||||
while self.killedbricks < self.nbbricks:
|
||||
yield None
|
||||
|
||||
def unframe(self):
|
||||
for x in range(2, curboard.width-2):
|
||||
curboard.killwall(x, -1)
|
||||
|
||||
def build_paddles(self):
|
||||
from player import BubPlayer
|
||||
for p in BubPlayer.PlayerList:
|
||||
dragons = [d for d in p.dragons if not isinstance(d, PaddleEyes)]
|
||||
if dragons and len(p.dragons) == len(dragons):
|
||||
if self.builddelay.get(p):
|
||||
self.builddelay[p] -= 1
|
||||
else:
|
||||
self.builddelay[p] = 53
|
||||
dragon = random.choice(dragons)
|
||||
paddle = Paddle(self, p, dragon.x, dragon.y)
|
||||
eyes = PaddleEyes(p, dragon.dcap, paddle)
|
||||
p.dragons.append(eyes)
|
||||
p.emotic(dragon, 4)
|
||||
for d in dragons:
|
||||
d.kill()
|
||||
|
||||
def order_paddles(self):
|
||||
self.order.sort()
|
||||
self.order.reverse()
|
||||
for timeleft, paddle in self.order:
|
||||
try:
|
||||
self.paddles.remove(paddle)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
self.paddles.insert(0, paddle)
|
||||
paddle.to_front()
|
||||
del self.order[:]
|
||||
|
||||
def remove_paddles(self):
|
||||
killclasses = (Paddle, PaddleEyes, Ball, Bonus)
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, killclasses):
|
||||
s.kill()
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 1
|
||||
|
||||
def run():
|
||||
global curboard
|
||||
import boards
|
||||
from boards import curboard
|
||||
boards.replace_boardgen(Arkanoid().bgen())
|
||||
|
||||
def setup():
|
||||
from player import BubPlayer
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
images.sprmap[key, p.pn] = (filename % p.pn, rect)
|
||||
else:
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -397,8 +397,8 @@ class Pacman:
|
||||
# digs the rectangle (x1,y1,x2,y2) and marks it as
|
||||
# processed. Also recursively mark as processed all existing
|
||||
# holes that are pacman-connected to the rectangle.
|
||||
xrange = range(x1,x2)
|
||||
yrange = range(y1,y2)
|
||||
xrange = list(range(x1,x2))
|
||||
yrange = list(range(y1,y2))
|
||||
if not reversed:
|
||||
xrange.reverse()
|
||||
yrange.reverse()
|
||||
@ -479,7 +479,7 @@ class Pacman:
|
||||
|
||||
if not holes:
|
||||
holes[boards.width//2, boards.height//2] = 0
|
||||
holeslist = holes.keys()
|
||||
holeslist = list(holes.keys())
|
||||
random.shuffle(holeslist)
|
||||
startx, starty = holeslist.pop()
|
||||
# make the hole larger (2x2) towards the center of the board
|
||||
@ -572,7 +572,7 @@ def run():
|
||||
boards.replace_boardgen(Pacman().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
||||
|
578
bubbob/ext2/__init__.py.bak
Normal file
578
bubbob/ext2/__init__.py.bak
Normal file
@ -0,0 +1,578 @@
|
||||
from __future__ import generators
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
from boards import CELL, HALFCELL, bget
|
||||
from mnstrmap import GreenAndBlue, Ghost
|
||||
from bonuses import Bonus
|
||||
from bubbles import Bubble
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
|
||||
localmap = {
|
||||
('pac-lg', -1,0) : ('image1.ppm', ( 0, 0, 32, 32)),
|
||||
('pac-sm', -1,0) : ('image1.ppm', (32, 0, 32, 32)),
|
||||
('pac-lg', 0,-1) : ('image1.ppm', ( 0, 32, 32, 32)),
|
||||
('pac-sm', 0,-1) : ('image1.ppm', (32, 32, 32, 32)),
|
||||
('pac-lg', 1,0) : ('image1.ppm', ( 0, 64, 32, 32)),
|
||||
('pac-sm', 1,0) : ('image1.ppm', (32, 64, 32, 32)),
|
||||
('pac-lg', 0,1) : ('image1.ppm', ( 0, 96, 32, 32)),
|
||||
('pac-sm', 0,1) : ('image1.ppm', (32, 96, 32, 32)),
|
||||
'pac-black' : ('image2.ppm', ( 0, 0, 32, 32)),
|
||||
'pac-dot' : ('image2.ppm', ( 0, 32, 8, 8)),
|
||||
}
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
|
||||
|
||||
class PacSprite(ActiveSprite):
|
||||
|
||||
def __init__(self, ico, x, y):
|
||||
import boards
|
||||
if y < -2*CELL:
|
||||
y = -2*CELL
|
||||
elif y > boards.bheight:
|
||||
y = boards.bheight
|
||||
x = (x+HALFCELL) & -CELL
|
||||
y = (y+HALFCELL) & -CELL
|
||||
ActiveSprite.__init__(self, ico, x, y)
|
||||
self.wannadx = self.wannady = 0
|
||||
|
||||
def moving(self):
|
||||
import boards
|
||||
dx = dy = 0
|
||||
turned = None
|
||||
was_clear = 0
|
||||
while 1:
|
||||
if dx or dy:
|
||||
frontx = self.x+CELL+dx*(CELL+1)
|
||||
fronty = self.y+CELL+dy*(CELL+1)
|
||||
clear = (bget((frontx+dy)//CELL, (fronty-dx)//CELL) == ' ' and
|
||||
bget((frontx-dy)//CELL, (fronty+dx)//CELL) == ' ')
|
||||
if clear:
|
||||
blocked = 0
|
||||
else:
|
||||
blocked = (was_clear or (self.x<=2*CELL and dx<0) or
|
||||
(self.x>=boards.bwidth-4*CELL and dx>0))
|
||||
else:
|
||||
blocked = 1
|
||||
if blocked:
|
||||
if turned:
|
||||
dx, dy = turned
|
||||
turned = None
|
||||
continue
|
||||
self.lastmove = None
|
||||
else:
|
||||
if turned:
|
||||
self.resetimages(dx, dy)
|
||||
turned = None
|
||||
self.lastmove = dx, dy
|
||||
self.step(2*dx, 2*dy)
|
||||
self.vertical_warp()
|
||||
was_clear = clear
|
||||
yield None
|
||||
if self.wannadx != dx or self.wannady != dy:
|
||||
if ((self.wannadx and not (self.y % CELL)) or
|
||||
(self.wannady and not (self.x % CELL))):
|
||||
turned = dx, dy
|
||||
dx = self.wannadx
|
||||
dy = self.wannady
|
||||
|
||||
|
||||
class Pac(PacSprite):
|
||||
no_hat = 1
|
||||
|
||||
def __init__(self, pacman, bubber, x, y, dcap):
|
||||
ico = GreenAndBlue.normal_bubbles[bubber.pn][1]
|
||||
PacSprite.__init__(self, images.sprget(('eyes', 0, 0)), x, y)
|
||||
self.bubble = ActiveSprite(images.sprget(ico), x, y)
|
||||
self.bubber = bubber
|
||||
self.pacman = pacman
|
||||
self.ready = 0
|
||||
self.gen.append(self.playing())
|
||||
self.pacman.pacs.append(self)
|
||||
self.dcap = dcap
|
||||
|
||||
def resetimages(self, dx, dy):
|
||||
self.ready = 1
|
||||
self.setimages(self.cyclic([('pac-lg', dx, dy),
|
||||
'pac-black',
|
||||
('pac-sm', dx, dy)], 5))
|
||||
|
||||
def to_front(self):
|
||||
self.bubble.to_front()
|
||||
ActiveSprite.to_front(self)
|
||||
|
||||
def kill(self):
|
||||
self.play(images.Snd.Pop)
|
||||
self.bubble.gen = [self.bubble.die(Bubble.exploding_bubbles)]
|
||||
self.pacman.latestposition[self.bubber] = self.x, self.y
|
||||
try:
|
||||
self.bubber.dragons.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
self.pacman.pacs.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
ActiveSprite.kill(self)
|
||||
|
||||
def playing(self):
|
||||
bubber = self.bubber
|
||||
for t in self.moving():
|
||||
if self.pacman.ready:
|
||||
d = [(bubber.key_left, -1, 0),
|
||||
(bubber.key_right, 1, 0),
|
||||
(bubber.key_jump, 0,-1),
|
||||
(bubber.key_fire, 0, 1)]
|
||||
d.sort()
|
||||
if d[-1][0] > d[-2][0]:
|
||||
self.wannadx, self.wannady = d[-1][1:]
|
||||
|
||||
self.bubble.move(self.x, self.y)
|
||||
yield None
|
||||
|
||||
if self.ready:
|
||||
touching = images.touching(self.x+CELL-3, self.y+CELL-3, 6, 6)
|
||||
touching.reverse()
|
||||
for s in touching:
|
||||
if isinstance(s, Bonus):
|
||||
s.touched(self)
|
||||
elif isinstance(s, PacGhost):
|
||||
self.kill()
|
||||
return
|
||||
|
||||
|
||||
class PacGhost(PacSprite):
|
||||
|
||||
def __init__(self, pacman, x, y):
|
||||
left = random.random() < 0.5
|
||||
if left:
|
||||
ico = Ghost.left[0]
|
||||
else:
|
||||
ico = Ghost.right[0]
|
||||
PacSprite.__init__(self, images.sprget(ico), x, y)
|
||||
self.pacman = pacman
|
||||
self.gen.append(self.waiting())
|
||||
if left:
|
||||
self.wannadx = -1
|
||||
else:
|
||||
self.wannadx = 1
|
||||
self.resetimages(self.wannadx, self.wannady)
|
||||
|
||||
def resetimages(self, dx, dy):
|
||||
if dx > 0:
|
||||
self.setimages(self.cyclic(Ghost.right, 3))
|
||||
elif dx < 0:
|
||||
self.setimages(self.cyclic(Ghost.left, 3))
|
||||
#else: don't change image
|
||||
|
||||
def waiting(self, delay=45):
|
||||
while not self.pacman.ready:
|
||||
yield None
|
||||
for i in range(delay):
|
||||
yield None
|
||||
self.gen.append(self.walking())
|
||||
|
||||
def walking(self):
|
||||
round = 0
|
||||
self.touchable = 1
|
||||
lastmove_x = 0
|
||||
for t in self.moving():
|
||||
if random.random() < 0.1:
|
||||
lastmove_x = self.wannadx
|
||||
if self.lastmove is None and random.random() < 0.75:
|
||||
round = 0 # try to move again immediately
|
||||
if self.lastmove is None or random.random() < 0.01:
|
||||
dragons = self.pacman.pacs or images.ActiveSprites
|
||||
distances = [(abs(dragon.x-self.x)+abs(dragon.y-self.y),
|
||||
dragon) for dragon in dragons]
|
||||
distance, dragon = min(distances)
|
||||
if lastmove_x:
|
||||
self.wannadx = 0
|
||||
if (dragon.y < self.y) ^ (random.random() < 0.3):
|
||||
self.wannady = -1
|
||||
else:
|
||||
self.wannady = 1
|
||||
else:
|
||||
self.wannady = 0
|
||||
if (dragon.x < self.x) ^ (random.random() < 0.3):
|
||||
self.wannadx = -1
|
||||
else:
|
||||
self.wannadx = 1
|
||||
else:
|
||||
lastmove_x = self.lastmove[0]
|
||||
## for i in range(10):
|
||||
## dragon = random.choice(dragons)
|
||||
## dx = dragon.x - self.x
|
||||
## dy = dragon.y - self.y
|
||||
## if dx or dy:
|
||||
## dist = math.sqrt(dx*dx+dy*dy)
|
||||
## dx /= dist
|
||||
## dy /= dist
|
||||
## wx, wy = random.choice([(-1,0), (1,0), (0,-1), (0,1)])
|
||||
## ex = wx-dx
|
||||
## ey = wy-dy
|
||||
## if ex*ex + ey*ey < random.random()*3.14:
|
||||
## break
|
||||
## self.wannadx = wx
|
||||
## self.wannady = wy
|
||||
if round == 0: # go just a bit faster than the players
|
||||
round = 6
|
||||
else:
|
||||
round -= 1
|
||||
yield None
|
||||
|
||||
|
||||
class FruitBonus(Bonus):
|
||||
pass
|
||||
|
||||
|
||||
class Pacman:
|
||||
|
||||
def bgen(self, limittime = 45.1): # 0:45
|
||||
import boards
|
||||
from player import BubPlayer
|
||||
|
||||
self.ready = 0
|
||||
self.dots = []
|
||||
monsters = BubPlayer.MonsterList[:]
|
||||
random.shuffle(monsters)
|
||||
keep = len([p for p in BubPlayer.PlayerList if p.isplaying()])
|
||||
monsters = monsters[:2 + keep//2]
|
||||
for d in monsters:
|
||||
PacGhost(self, d.x, d.y)
|
||||
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
|
||||
tc = boards.TimeCounter(limittime)
|
||||
self.builddelay = {}
|
||||
self.latestposition = {}
|
||||
self.pacs = []
|
||||
#finish = 0
|
||||
for t in self.frame():
|
||||
t = boards.normal_frame()
|
||||
self.build_pacs()
|
||||
yield t
|
||||
#if len(self.pacs) == 0:
|
||||
# finish += 1
|
||||
# if finish == 20:
|
||||
# break
|
||||
#else:
|
||||
# finish = 0
|
||||
tc.update(t)
|
||||
if tc.time == 0.0:
|
||||
break
|
||||
if (BubPlayer.FrameCounter & 15) == 7:
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bubble):
|
||||
s.pop()
|
||||
|
||||
tc.restore()
|
||||
self.ready = 0
|
||||
results = {}
|
||||
for b in self.dots:
|
||||
for d in b.taken_by:
|
||||
bubber = d.bubber
|
||||
results[bubber] = results.get(bubber, 0) + 1
|
||||
for t in boards.result_ranking(results, len(self.dots)):
|
||||
self.remove_pacs()
|
||||
yield t
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, Bonus):
|
||||
s.kill()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
result = 0
|
||||
for b in self.dots:
|
||||
for d in b.taken_by:
|
||||
if d.bubber is bubber:
|
||||
result += 1
|
||||
return result
|
||||
|
||||
def frame(self):
|
||||
import boards
|
||||
from bonuses import Fruits
|
||||
for t in self.digwalls():
|
||||
yield t
|
||||
|
||||
def anywall(x1,y1,x2,y2):
|
||||
for tx in range(x1, x2):
|
||||
for ty in range(y1, y2):
|
||||
if bget(tx, ty) == '#':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def give_one_point(dragon):
|
||||
dragon.bubber.displaypoints += 1
|
||||
scoreboard()
|
||||
|
||||
dots = self.dots
|
||||
ico = images.sprget('pac-dot')
|
||||
for x in range(boards.width):
|
||||
for y in range(boards.height):
|
||||
if not anywall(x, y, x+2, y+2):
|
||||
if anywall(x-1, y-1, x+3, y+3):
|
||||
b = Bonus((x+1)*CELL - ico.w//2,
|
||||
(y+1)*CELL - ico.h//2,
|
||||
'pac-dot', points=-100, falling=0)
|
||||
b.sound = 'Extra'
|
||||
b.timeout = 0
|
||||
b.taken = give_one_point
|
||||
dots.append(b)
|
||||
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, PacGhost):
|
||||
s.to_front()
|
||||
yield None
|
||||
|
||||
self.ready = 1
|
||||
|
||||
for i in range(len([s for s in images.ActiveSprites
|
||||
if isinstance(s, PacGhost)])):
|
||||
for j in range(32):
|
||||
yield None
|
||||
for j in range(100):
|
||||
x = random.randrange(4, boards.width-6)
|
||||
y = random.randrange(3, boards.height-5)
|
||||
if not anywall(x-2, y-2, x+4, y+4):
|
||||
nimage, points = random.choice(Fruits.Fruits)
|
||||
points += 650 # boost to the range 750-1000
|
||||
b = FruitBonus(x*CELL, y*CELL,
|
||||
nimage, points, falling=0)
|
||||
b.timeout = 0
|
||||
break
|
||||
|
||||
while dots:
|
||||
dots = [b for b in dots if b.alive]
|
||||
yield None
|
||||
|
||||
def build_pacs(self):
|
||||
from player import BubPlayer
|
||||
for p in BubPlayer.PlayerList:
|
||||
dragons = [d for d in p.dragons if not isinstance(d, Pac)]
|
||||
if dragons and len(p.dragons) == len(dragons):
|
||||
if self.builddelay.get(p):
|
||||
self.builddelay[p] -= 1
|
||||
else:
|
||||
self.builddelay[p] = 109
|
||||
dragon = random.choice(dragons)
|
||||
if p in self.latestposition:
|
||||
dragon.move(*self.latestposition[p])
|
||||
pac = Pac(self, p, dragon.x, dragon.y, dragon.dcap)
|
||||
p.dragons.append(pac)
|
||||
p.emotic(dragon, 4)
|
||||
for d in dragons:
|
||||
d.kill()
|
||||
|
||||
def remove_pacs(self):
|
||||
from player import Dragon
|
||||
killclasses = (PacSprite, FruitBonus, Dragon)
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, killclasses):
|
||||
s.kill()
|
||||
|
||||
def digwalls(self):
|
||||
import boards
|
||||
holes = {}
|
||||
for x in range(2, boards.width-2):
|
||||
y = boards.height-1
|
||||
if bget(x, 0) == '#' or bget(x, y) == '#':
|
||||
if bget(x, 0) == ' ': curboard.putwall(x, 0)
|
||||
if bget(x, y) == ' ': curboard.putwall(x, y)
|
||||
curboard.reorder_walls()
|
||||
for y in range(1, boards.height-1):
|
||||
if bget(x, y) == ' ':
|
||||
holes[x, y] = 0
|
||||
if x % 7 == 0:
|
||||
yield None
|
||||
|
||||
# 'holes' maps coordinates (x,y) to 0 (not processed)
|
||||
# or 1 (processed).
|
||||
# All processed holes are pacman-connected.
|
||||
|
||||
def rdig(x1,y1,x2,y2, reversed, holes=holes):
|
||||
# digs the rectangle (x1,y1,x2,y2) and marks it as
|
||||
# processed. Also recursively mark as processed all existing
|
||||
# holes that are pacman-connected to the rectangle.
|
||||
xrange = range(x1,x2)
|
||||
yrange = range(y1,y2)
|
||||
if not reversed:
|
||||
xrange.reverse()
|
||||
yrange.reverse()
|
||||
if len(xrange) > len(yrange):
|
||||
xylist = [(x, y) for x in xrange for y in yrange]
|
||||
else:
|
||||
xylist = [(x, y) for y in yrange for x in xrange]
|
||||
t = 0
|
||||
for x, y in xylist:
|
||||
if bget(x, y) == '#':
|
||||
curboard.killwall(x, y)
|
||||
if t == 0:
|
||||
yield None
|
||||
t = 2
|
||||
else:
|
||||
t -= 1
|
||||
holes.setdefault((x, y), 0)
|
||||
fill = []
|
||||
for x in range(x1,x2-1):
|
||||
for y in range(y1,y2-1):
|
||||
fill.append((x, y))
|
||||
for x, y in fill:
|
||||
if ((x, y) in holes and
|
||||
(x, y+1) in holes and
|
||||
(x+1, y) in holes and
|
||||
(x+1, y+1) in holes):
|
||||
if (holes[x, y] == 0 or
|
||||
holes[x, y+1] == 0 or
|
||||
holes[x+1, y] == 0 or
|
||||
holes[x+1, y+1] == 0):
|
||||
|
||||
holes[x, y] = 1
|
||||
holes[x, y+1] = 1
|
||||
holes[x+1, y] = 1
|
||||
holes[x+1, y+1] = 1
|
||||
fill.append((x+1,y))
|
||||
fill.append((x-1,y))
|
||||
fill.append((x,y+1))
|
||||
fill.append((x,y-1))
|
||||
|
||||
def joined(x1,y1,x2,y2, holes=holes, boards=boards):
|
||||
# returns
|
||||
# 1 if the rectangle (x1,y1,x2,y2) is pac-connected to
|
||||
# some already-processed holes
|
||||
# 0 if it is not
|
||||
# -1 if (x1,y1,x2,y2) is out of the screen
|
||||
if x1<2 or y1<1 or x2>boards.width-2 or y2>boards.height-1:
|
||||
return -1
|
||||
accum1 = accum2 = 0
|
||||
for x in range(x1,x2):
|
||||
if holes.get((x,y1-1)):
|
||||
accum1 += 1
|
||||
if accum1 == 2:
|
||||
return 1
|
||||
else:
|
||||
accum1 = 0
|
||||
if holes.get((x,y2)):
|
||||
accum2 += 1
|
||||
if accum2 == 2:
|
||||
return 1
|
||||
else:
|
||||
accum2 = 0
|
||||
accum1 = accum2 = 0
|
||||
for y in range(y1,y2):
|
||||
if holes.get((x1-1,y)):
|
||||
accum1 += 1
|
||||
if accum1 == 2:
|
||||
return 1
|
||||
else:
|
||||
accum1 = 0
|
||||
if holes.get((x2,y)):
|
||||
accum2 += 1
|
||||
if accum2 == 2:
|
||||
return 1
|
||||
else:
|
||||
accum2 = 0
|
||||
return 0
|
||||
|
||||
if not holes:
|
||||
holes[boards.width//2, boards.height//2] = 0
|
||||
holeslist = holes.keys()
|
||||
random.shuffle(holeslist)
|
||||
startx, starty = holeslist.pop()
|
||||
# make the hole larger (2x2) towards the center of the board
|
||||
if startx > boards.width//2:
|
||||
startx -= 1
|
||||
if starty > boards.height//2:
|
||||
starty -= 1
|
||||
# initial 2x2 hole
|
||||
for t in rdig(startx, starty, startx+2, starty+2, 0):
|
||||
yield t
|
||||
|
||||
dlist = [
|
||||
(0,0,1,0, 0,-1), (0,0,1,0, 0,0), # right
|
||||
(0,0,0,1, -1,0), (0,0,0,1, 0,0), # bottom
|
||||
(-1,0,0,0, -1,-1), (-1,0,0,0, -1,0), # left
|
||||
(0,-1,0,0, -1,-1), (0,-1,0,0, 0,-1), # top
|
||||
]
|
||||
while holeslist:
|
||||
random.shuffle(dlist)
|
||||
pending = holeslist
|
||||
holeslist = []
|
||||
progress = 0
|
||||
for x, y in pending:
|
||||
if holes[x, y] != 0:
|
||||
continue
|
||||
for dx1, dy1, dx2, dy2, dx, dy in dlist:
|
||||
x1 = x + dx
|
||||
y1 = y + dy
|
||||
x2 = x1 + 2
|
||||
y2 = y1 + 2
|
||||
result = 0
|
||||
while result == 0:
|
||||
result = joined(x1,y1,x2,y2)
|
||||
if result == 1:
|
||||
# rectangle (x1,y1,x2,y2) is good
|
||||
for t in rdig(x1, y1, x2, y2,
|
||||
dx1<0 or dy1<0 or dx2<0 or dy2<0):
|
||||
yield t
|
||||
progress = 1
|
||||
break
|
||||
x1 += dx1
|
||||
y1 += dy1
|
||||
x2 += dx2
|
||||
y2 += dy2
|
||||
else:
|
||||
# rectangle (x1,y1,x2,y2) is too large for the screen
|
||||
# failure
|
||||
continue
|
||||
break
|
||||
else:
|
||||
# no successful direction found from this point
|
||||
holeslist.append((x, y)) # try again later
|
||||
if not progress:
|
||||
# deadlocked situation, add a new random hole
|
||||
x = random.randrange(2, boards.width-2)
|
||||
y = random.randrange(1, boards.height-1)
|
||||
holeslist.insert(0, (x, y))
|
||||
holes.setdefault((x, y), 0)
|
||||
yield None
|
||||
|
||||
# pattern transformation:
|
||||
# X. ..
|
||||
# ... --> ...
|
||||
# .X .X
|
||||
progress = 1
|
||||
while progress:
|
||||
progress = 0
|
||||
for y in range(1, boards.height-1):
|
||||
for x in range(3, boards.width-3):
|
||||
if (' ' == bget(x, y)
|
||||
== bget(x+1, y)
|
||||
== bget(x-1, y)
|
||||
== bget(x, y+1)
|
||||
== bget(x, y-1)):
|
||||
if '#' == bget(x-1, y-1) == bget(x+1, y+1):
|
||||
curboard.killwall(x-1, y-1)
|
||||
progress = 1
|
||||
elif '#' == bget(x+1, y-1) == bget(x-1, y+1):
|
||||
curboard.killwall(x+1, y-1)
|
||||
progress = 1
|
||||
yield None
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 1
|
||||
|
||||
def run():
|
||||
global curboard
|
||||
import boards
|
||||
from boards import curboard
|
||||
boards.replace_boardgen(Pacman().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -292,7 +292,7 @@ class Galaga:
|
||||
if in_place[1]:
|
||||
xbounds = [s.x for s in in_place[1]]
|
||||
self.alien_bounds = min(xbounds), max(xbounds)
|
||||
shifter.next()
|
||||
next(shifter)
|
||||
elif toohigh:
|
||||
self.globaly += 1
|
||||
squadtime -= 1
|
||||
@ -357,7 +357,7 @@ def run():
|
||||
boards.replace_boardgen(Galaga().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
|
367
bubbob/ext3/__init__.py.bak
Normal file
367
bubbob/ext3/__init__.py.bak
Normal file
@ -0,0 +1,367 @@
|
||||
from __future__ import generators
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
import boards
|
||||
from boards import CELL, HALFCELL, bget
|
||||
from mnstrmap import GreenAndBlue, Fire
|
||||
from bonuses import Bonus
|
||||
from player import Dragon, BubPlayer
|
||||
import monsters
|
||||
from bubbles import Bubble
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
localmap = {
|
||||
'gala': ('image1-%d.ppm', (0, 0, 32, 32)),
|
||||
}
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
snd_shoot = gamesrv.getsample(os.path.join(LocalDir, 'shoot.wav'))
|
||||
|
||||
|
||||
class Ship(ActiveSprite):
|
||||
|
||||
def __init__(self, galaga, bubber, x, y):
|
||||
ico = images.sprget(('gala', bubber.pn))
|
||||
ActiveSprite.__init__(self, ico, x, y)
|
||||
self.galaga = galaga
|
||||
self.bubber = bubber
|
||||
self.gen.append(self.movedown())
|
||||
self.gen.append(self.playing_ship())
|
||||
self.gen.append(self.doomed())
|
||||
self.galaga.ships.append(self)
|
||||
|
||||
def movedown(self):
|
||||
import boards
|
||||
target_y = boards.bheight - self.ico.h
|
||||
while self.y < target_y:
|
||||
yield None
|
||||
self.move(self.x, self.y + 3)
|
||||
self.move(self.x, target_y)
|
||||
|
||||
def playing_ship(self):
|
||||
import boards
|
||||
bubber = self.bubber
|
||||
xmin = HALFCELL
|
||||
xmax = boards.bwidth - HALFCELL - self.ico.w
|
||||
fire = 0
|
||||
while 1:
|
||||
wannago = bubber.wannago(self.dcap)
|
||||
nx = self.x + 2*wannago
|
||||
if nx < xmin:
|
||||
nx = xmin
|
||||
elif nx > xmax:
|
||||
nx = xmax
|
||||
self.move(nx, self.y)
|
||||
if fire:
|
||||
fire -= 1
|
||||
elif bubber.key_fire:
|
||||
self.firenow()
|
||||
fire = 28
|
||||
yield None
|
||||
|
||||
def firenow(self):
|
||||
ico = images.sprget(GreenAndBlue.new_bubbles[self.bubber.pn][0])
|
||||
s = Shot(ico, self.x, self.y)
|
||||
s.d = self
|
||||
s.gen = [s.straightup(self)]
|
||||
self.play(snd_shoot)
|
||||
|
||||
def doomed(self):
|
||||
dangerous = Alien, monsters.MonsterShot
|
||||
while 1:
|
||||
touching = images.touching(self.x+3, self.y+3, 26, 26)
|
||||
for s in touching:
|
||||
if isinstance(s, dangerous):
|
||||
self.kill()
|
||||
return
|
||||
yield None
|
||||
yield None
|
||||
|
||||
def kill(self):
|
||||
try:
|
||||
self.bubber.dragons.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
images.Snd.Pop.play(1.0, pad=0.0)
|
||||
images.Snd.Pop.play(1.0, pad=1.0)
|
||||
ico = images.sprget(Bubble.exploding_bubbles[0])
|
||||
for i in range(11):
|
||||
s = ActiveSprite(ico,
|
||||
self.x + random.randrange(self.ico.w) - CELL,
|
||||
self.y + random.randrange(self.ico.h) - CELL)
|
||||
s.gen.append(s.die(Bubble.exploding_bubbles))
|
||||
try:
|
||||
self.galaga.ships.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
ActiveSprite.kill(self)
|
||||
|
||||
|
||||
class Shot(Bubble):
|
||||
touchable = 0
|
||||
|
||||
def straightup(self, ship):
|
||||
ymin = -self.ico.h
|
||||
while self.y > ymin:
|
||||
self.step(0, -10)
|
||||
touching = images.touching(self.x+CELL-1, self.y+CELL-1, 2, 2)
|
||||
touching = [s for s in touching if isinstance(s, Alien)]
|
||||
if touching:
|
||||
alien = random.choice(touching)
|
||||
self.gen = []
|
||||
self.touchable = 1
|
||||
self.move(alien.x, alien.y)
|
||||
self.pop([ship])
|
||||
alien.kill()
|
||||
scores = ship.galaga.scores
|
||||
scores[ship.bubber] = scores.get(ship.bubber, 0) + 1
|
||||
ship.bubber.givepoints(100)
|
||||
return
|
||||
yield None
|
||||
|
||||
def popped(self, dragon):
|
||||
return 200
|
||||
|
||||
|
||||
class Alien(monsters.Monster):
|
||||
ANGLES = 32
|
||||
SPEED = 5
|
||||
ANGLE_TABLE = [(SPEED * math.cos(a*2.0*math.pi/ANGLES),
|
||||
-SPEED * math.sin(a*2.0*math.pi/ANGLES))
|
||||
for a in range(ANGLES)]
|
||||
touchable = 0
|
||||
|
||||
def __init__(self, galaga, squadron, rank, relativey):
|
||||
centerx = boards.bwidth // 2
|
||||
go_left = squadron % 2
|
||||
dx = (1,-1)[go_left]
|
||||
halfspan = centerx*7//12
|
||||
relativex = - halfspan + 4*CELL*rank
|
||||
if relativex > halfspan:
|
||||
raise StopIteration
|
||||
|
||||
if squadron % 3 == 2:
|
||||
from mnstrmap import Ghosty as mcls
|
||||
else:
|
||||
from mnstrmap import Flappy as mcls
|
||||
mdef = mcls(centerx // CELL - 1, -7, go_left)
|
||||
mdef.left_weapon = mdef.right_weapon = [Fire.drop]
|
||||
monsters.Monster.__init__(self, mdef)
|
||||
|
||||
self.path = [(None, centerx + (dx*centerx)*2//3, boards.bheight//3),
|
||||
(None, centerx - (dx*centerx)*4//5, boards.bheight//6),
|
||||
(galaga, -dx*relativex, -relativey)]
|
||||
self.gen = [self.waiting(rank * 20)]
|
||||
self.in_place = 0
|
||||
galaga.nbmonsters += 1
|
||||
|
||||
def default_mode(self, angle=ANGLES//4):
|
||||
self.touchable = 1
|
||||
speed = self.SPEED
|
||||
relative, tx, ty = self.path[0]
|
||||
fx = self.x
|
||||
fy = self.y
|
||||
ymax = boards.bheight - self.ico.h
|
||||
cont = 1
|
||||
if relative:
|
||||
shoot_prob = 0.0085
|
||||
else:
|
||||
shoot_prob = 0.021
|
||||
while cont:
|
||||
if self.angry:
|
||||
self.kill() # never getting out of a bubble
|
||||
return
|
||||
if relative:
|
||||
dx = relative.globalx + tx
|
||||
dy = relative.globaly + ty
|
||||
else:
|
||||
dx = tx
|
||||
dy = ty
|
||||
dx -= self.x
|
||||
dy -= self.y
|
||||
|
||||
tests = []
|
||||
for a1 in (-1, 0, 1):
|
||||
a1 = (angle+a1) % self.ANGLES
|
||||
testx, testy = self.ANGLE_TABLE[a1]
|
||||
testx -= dx
|
||||
testy -= dy
|
||||
tests.append((testx*testx+testy*testy, a1))
|
||||
ignored, angle = min(tests)
|
||||
if dx*dx+dy*dy > speed*speed:
|
||||
dx, dy = self.ANGLE_TABLE[angle]
|
||||
elif relative:
|
||||
self.in_place = 1
|
||||
if self.y > ymax and relative.ships:
|
||||
for ship in relative.ships[:]:
|
||||
ship.kill()
|
||||
relative.builddelay[ship.bubber] = 9999
|
||||
relative.gameover = 1
|
||||
#x0 = self.x//CELL + 1
|
||||
#if x0 < 2: x0 = 0
|
||||
#if x0 >= boards.width-2: x0 = boards.width-3
|
||||
#bubbles.FireFlame(x0, boards.height-2, None, [-1, 1],
|
||||
# boards.width)
|
||||
else:
|
||||
self.path.pop(0)
|
||||
self.gen.append(self.default_mode(angle))
|
||||
cont = 0
|
||||
fx += dx
|
||||
fy += dy
|
||||
self.move(int(fx), int(fy))
|
||||
if dx and (self.dir > 0) != (dx > 0):
|
||||
self.dir = -self.dir
|
||||
self.resetimages()
|
||||
if random.random() < shoot_prob and self.y >= 0:
|
||||
monsters.DownShot(self)
|
||||
yield None
|
||||
|
||||
|
||||
class Galaga:
|
||||
gameover = 0
|
||||
|
||||
def bgen(self):
|
||||
self.scores = {}
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
|
||||
self.ships = []
|
||||
self.builddelay = {}
|
||||
self.nbmonsters = 0
|
||||
#finish = 0
|
||||
for t in self.frame():
|
||||
t = boards.normal_frame()
|
||||
self.build_ships()
|
||||
yield t
|
||||
#if len(self.ships) == 0:
|
||||
# finish += 1
|
||||
# if finish == 50:
|
||||
# break
|
||||
#else:
|
||||
# finish = 0
|
||||
if (BubPlayer.FrameCounter & 15) == 7:
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bubble) and not isinstance(s, Shot):
|
||||
s.pop()
|
||||
|
||||
for t in boards.result_ranking(self.scores, self.nbmonsters):
|
||||
self.build_ships()
|
||||
yield t
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, (Alien, Ship)):
|
||||
s.kill()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
return self.scores.get(bubber, 0)
|
||||
|
||||
def frame(self):
|
||||
curboard.walls_by_pos.clear()
|
||||
curboard.winds = ['v' * curboard.width] * curboard.height
|
||||
for y in range(len(curboard.walls)):
|
||||
curboard.walls[y] = ' ' * len(curboard.walls[y])
|
||||
l1 = curboard.sprites['walls']
|
||||
l2 = curboard.sprites['borderwalls']
|
||||
while l1 or l2:
|
||||
for l in [l1, l2]:
|
||||
for w in l[:]:
|
||||
w.step(0, 5)
|
||||
if w.y >= boards.bheight:
|
||||
l.remove(w)
|
||||
w.kill()
|
||||
yield None
|
||||
|
||||
self.globalx = boards.bwidth // 2
|
||||
self.globaly = 0
|
||||
shifter = self.shifter()
|
||||
squadrons = len([p for p in BubPlayer.PlayerList if p.isplaying()])
|
||||
squadrons = 3 + (squadrons+1)//3
|
||||
nextsquad = 0
|
||||
relativey = 0
|
||||
squadtime = 0
|
||||
while not self.gameover:
|
||||
yield None
|
||||
#if random.random() < 0.015:
|
||||
# bubbles.sendbubble(bubbles.PlainBubble, top=0)
|
||||
in_place = {0: [], 1: [], 2: []}
|
||||
for s in BubPlayer.MonsterList:
|
||||
if isinstance(s, Alien):
|
||||
in_place[s.in_place].append(s)
|
||||
toohigh = self.globaly - relativey < -3*CELL
|
||||
if in_place[1]:
|
||||
xbounds = [s.x for s in in_place[1]]
|
||||
self.alien_bounds = min(xbounds), max(xbounds)
|
||||
shifter.next()
|
||||
elif toohigh:
|
||||
self.globaly += 1
|
||||
squadtime -= 1
|
||||
if nextsquad >= squadrons:
|
||||
if not (in_place[0] or in_place[1]):
|
||||
break
|
||||
elif squadtime < 0 and not toohigh:
|
||||
squadtime = 200
|
||||
try:
|
||||
rank = 0
|
||||
while 1:
|
||||
Alien(self, nextsquad, rank, relativey)
|
||||
rank += 1
|
||||
except StopIteration:
|
||||
pass
|
||||
nextsquad += 1
|
||||
relativey += 4*CELL
|
||||
for t in range(20):
|
||||
yield None
|
||||
|
||||
def shifter(self):
|
||||
while 1:
|
||||
# go right
|
||||
while self.alien_bounds[1] < boards.bwidth-5*CELL:
|
||||
self.globalx += 2
|
||||
yield None
|
||||
# go down
|
||||
for i in range(3*CELL):
|
||||
self.globaly += 1
|
||||
yield None
|
||||
# go left
|
||||
while self.alien_bounds[0] > 3*CELL:
|
||||
self.globalx -= 2
|
||||
yield None
|
||||
# go down
|
||||
for i in range(3*CELL):
|
||||
self.globaly += 1
|
||||
yield None
|
||||
|
||||
def build_ships(self):
|
||||
for p in BubPlayer.PlayerList:
|
||||
dragons = [d for d in p.dragons if not isinstance(d, Ship)]
|
||||
if dragons and len(p.dragons) == len(dragons):
|
||||
if self.builddelay.get(p):
|
||||
self.builddelay[p] -= 1
|
||||
else:
|
||||
self.builddelay[p] = 75
|
||||
dragon = random.choice(dragons)
|
||||
ship = Ship(self, p, dragon.x, dragon.y)
|
||||
ship.dcap = dragon.dcap
|
||||
p.dragons.append(ship)
|
||||
p.emotic(dragon, 4)
|
||||
for d in dragons:
|
||||
d.kill()
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 1
|
||||
|
||||
def run():
|
||||
global curboard
|
||||
from boards import curboard
|
||||
boards.replace_boardgen(Galaga().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
images.sprmap[key, p.pn] = (filename % p.pn, rect)
|
||||
else:
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -179,7 +179,7 @@ class BrickEyes(BubblingEyes):
|
||||
ico = images.sprget(Bubble.exploding_bubbles[0])
|
||||
self.tetris.score[self.bubber] = self.tetris.score.get(
|
||||
self.bubber, 0) + 1
|
||||
xlist = range(x1, x2)
|
||||
xlist = list(range(x1, x2))
|
||||
for x in xlist:
|
||||
s = ActiveSprite(ico,
|
||||
x*CELL + random.randrange(CELL) - CELL,
|
||||
@ -317,7 +317,7 @@ class Tetris:
|
||||
for t in boards.result_ranking(self.score):
|
||||
self.remove_eyes()
|
||||
yield t
|
||||
for s in self.staticbricks.values():
|
||||
for s in list(self.staticbricks.values()):
|
||||
s.remove()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
@ -339,7 +339,7 @@ class Tetris:
|
||||
else:
|
||||
height += 1
|
||||
heights[x] = height
|
||||
xlist = range(2, curboard.width-2)
|
||||
xlist = list(range(2, curboard.width-2))
|
||||
random.shuffle(xlist)
|
||||
for x in xlist:
|
||||
h = heights[x]
|
||||
@ -430,7 +430,7 @@ def run():
|
||||
|
||||
def setup():
|
||||
from player import BubPlayer
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
|
440
bubbob/ext4/__init__.py.bak
Normal file
440
bubbob/ext4/__init__.py.bak
Normal file
@ -0,0 +1,440 @@
|
||||
from __future__ import generators
|
||||
import os, math, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
from boards import CELL, HALFCELL, bget
|
||||
from mnstrmap import GreenAndBlue
|
||||
from bubbles import BubblingEyes, Bubble
|
||||
from bonuses import Bonus, points
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
|
||||
localmap = {
|
||||
't-brick1': ('image1-%d.ppm', (0, 0, 16, 16)),
|
||||
't-brick2': ('image1-%d.ppm', (16, 0, 16, 16)),
|
||||
}
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
|
||||
|
||||
class BrickEyes(BubblingEyes):
|
||||
|
||||
Patterns = [[(-2,0), (-1,0), (0,0), (1,0)],
|
||||
[(-2,0), (-1,0), (0,0), (0,-1)],
|
||||
[(-1,-1), (-1,0), (0,0), (1,0)],
|
||||
[(-1,0), (0,0), (0,-1), (1,0)],
|
||||
[(-1,-1), (0,-1), (0,0), (1,0)],
|
||||
[(-2,0), (-1,0), (-1,-1), (0,-1)],
|
||||
[(-1,-1), (-1,0), (0,-1), (0,0)]]
|
||||
|
||||
def __init__(self, tetris, bubber, saved_caps, olddragon):
|
||||
BubblingEyes.__init__(self, bubber, saved_caps, olddragon)
|
||||
self.tetris = tetris
|
||||
self.bricks = []
|
||||
|
||||
def playing_bubble(self, oldsprite):
|
||||
import boards
|
||||
self.pat = random.choice(self.Patterns)
|
||||
self.orientation = 1,0
|
||||
xmin = 2 - min([x for x,y in self.pat])
|
||||
xmax = boards.width-3 - max([x for x,y in self.pat])
|
||||
x = int(random.normalvariate(oldsprite.x, boards.bwidth/4))
|
||||
x = (x+HALFCELL) // CELL
|
||||
if x<xmin: x=xmin
|
||||
if x>xmax: x=xmax
|
||||
y = -1
|
||||
self.tx = x
|
||||
self.ty = y
|
||||
self.move((x-1)*CELL, (y-1)*CELL)
|
||||
for i in range(5):
|
||||
yield None
|
||||
self.bricks = [Brick(self.bubber, px, py)
|
||||
for px, py in self.brick_positions()]
|
||||
self.gen.append(self.step_control())
|
||||
self.gen.append(self.rotate_control())
|
||||
self.gen.append(self.fall_control())
|
||||
self.gen.append(self.move_eyes())
|
||||
|
||||
def bottom_up(self):
|
||||
return 0
|
||||
|
||||
def kill(self):
|
||||
for b in self.bricks:
|
||||
b.stop(self.tetris)
|
||||
b.remove()
|
||||
self.bricks = []
|
||||
BubblingEyes.kill(self)
|
||||
|
||||
def brick_positions(self):
|
||||
ox, oy = self.orientation
|
||||
result = []
|
||||
cx = self.tx*CELL - HALFCELL
|
||||
cy = self.ty*CELL - HALFCELL
|
||||
for px, py in self.pat:
|
||||
px = px*CELL + HALFCELL
|
||||
py = py*CELL + HALFCELL
|
||||
result.append((cx+px*ox-py*oy, cy+px*oy+py*ox))
|
||||
return result
|
||||
|
||||
def save_position(self):
|
||||
return self.tx, self.ty, self.orientation
|
||||
|
||||
def restore_position(self, p):
|
||||
self.tx, self.ty, self.orientation = p
|
||||
|
||||
def moved(self, old_position):
|
||||
for b in self.bricks:
|
||||
b.set(' ')
|
||||
try:
|
||||
for px, py in self.brick_positions():
|
||||
if bget(px//CELL, py//CELL) != ' ':
|
||||
self.restore_position(old_position)
|
||||
return 0
|
||||
for b, (px, py) in zip(self.bricks, self.brick_positions()):
|
||||
b.follow(px, py)
|
||||
finally:
|
||||
for b in self.bricks:
|
||||
b.set('!') # note: we need '!' < '#'
|
||||
return 1
|
||||
|
||||
def onground(self):
|
||||
for b in self.bricks:
|
||||
if b.gen: # brick still moving
|
||||
return 0
|
||||
for px, py in self.brick_positions():
|
||||
if bget(px//CELL, py//CELL+1) >= '#':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def step_control(self):
|
||||
while 1:
|
||||
while not self.bubber.wannago(self.dcap):
|
||||
yield None
|
||||
pos = self.save_position()
|
||||
self.tx += self.bubber.wannago(self.dcap)
|
||||
if self.moved(pos):
|
||||
for i in range(4):
|
||||
yield None
|
||||
yield None
|
||||
|
||||
def fall_control(self):
|
||||
delay = 1
|
||||
while 1:
|
||||
for i in range(delay and 14):
|
||||
if self.bubber.key_fire:
|
||||
break
|
||||
yield None
|
||||
pos = self.save_position()
|
||||
self.ty += 1
|
||||
delay = self.moved(pos)
|
||||
if delay:
|
||||
for i in range(3):
|
||||
yield None
|
||||
elif self.onground() and self.tetris.ready:
|
||||
self.gen = [self.stopping()]
|
||||
yield None
|
||||
|
||||
def rotate_control(self):
|
||||
while 1:
|
||||
while not self.bubber.key_jump:
|
||||
yield None
|
||||
pos = self.save_position()
|
||||
ox, oy = self.orientation
|
||||
self.orientation = oy, -ox
|
||||
if self.moved(pos):
|
||||
for i in range(7):
|
||||
yield None
|
||||
yield None
|
||||
|
||||
def stopping(self):
|
||||
self.move(self.x, -self.ico.h)
|
||||
positions = [(py//CELL, px//CELL) for px, py in self.brick_positions()
|
||||
if py >= 0]
|
||||
positions.sort()
|
||||
positions = [(px, py) for py, px in positions]
|
||||
for b in self.bricks:
|
||||
b.stop(self.tetris)
|
||||
if b.ty < 0:
|
||||
b.remove()
|
||||
self.bricks = []
|
||||
staticbricks = self.tetris.staticbricks
|
||||
pts = 500
|
||||
while 1:
|
||||
for px, py in positions:
|
||||
y = py
|
||||
x1 = px
|
||||
while (x1-1, y) in staticbricks:
|
||||
x1 -= 1
|
||||
if bget(x1-1, y) != '#':
|
||||
continue
|
||||
x2 = px
|
||||
while (x2, y) in staticbricks:
|
||||
x2 += 1
|
||||
if bget(x2, y) != '#':
|
||||
continue
|
||||
if x2-x1 < 2:
|
||||
continue
|
||||
# full line
|
||||
ico = images.sprget(Bubble.exploding_bubbles[0])
|
||||
self.tetris.score[self.bubber] = self.tetris.score.get(
|
||||
self.bubber, 0) + 1
|
||||
xlist = range(x1, x2)
|
||||
for x in xlist:
|
||||
s = ActiveSprite(ico,
|
||||
x*CELL + random.randrange(CELL) - CELL,
|
||||
y*CELL + random.randrange(CELL) - CELL)
|
||||
s.gen.append(s.die(Bubble.exploding_bubbles))
|
||||
s = staticbricks[x, y]
|
||||
points(x*CELL + HALFCELL, y*CELL + HALFCELL, s, pts)
|
||||
s.remove()
|
||||
if pts == 500:
|
||||
self.play(images.Snd.Fruit)
|
||||
elif pts == 4000:
|
||||
self.play(images.Snd.Extralife)
|
||||
else:
|
||||
self.play(images.Snd.Extra)
|
||||
pts *= 2
|
||||
for y in range(py-1, -1, -1):
|
||||
if not [x for x in xlist if (x, y) in staticbricks]:
|
||||
break
|
||||
for t in range(4):
|
||||
yield None
|
||||
if [x for x in xlist if (x, y+1) in staticbricks]:
|
||||
break
|
||||
for x in xlist:
|
||||
if (x, y) in staticbricks:
|
||||
staticbricks[x, y].shiftdown()
|
||||
yield None
|
||||
break
|
||||
else:
|
||||
break
|
||||
if self.tetris.ready < 2:
|
||||
self.gen.append(self.playing_bubble(self))
|
||||
|
||||
def move_eyes(self):
|
||||
while 1:
|
||||
tx = (self.tx-1) * CELL
|
||||
ty = (self.ty-1) * CELL
|
||||
for i in range(3):
|
||||
if tx < self.x:
|
||||
dx = -1
|
||||
elif tx > self.x:
|
||||
dx = +1
|
||||
else:
|
||||
dx = 0
|
||||
if ty > self.y:
|
||||
dy = +1
|
||||
else:
|
||||
dy = 0
|
||||
self.step(2*dx, 2*dy)
|
||||
key = ('eyes', dx, 0)
|
||||
self.seticon(images.sprget(key))
|
||||
yield None
|
||||
|
||||
|
||||
class Brick(ActiveSprite):
|
||||
|
||||
def __init__(self, bubber, x, y):
|
||||
ico = images.sprget(('t-brick1', bubber.pn))
|
||||
ActiveSprite.__init__(self, ico, x, y)
|
||||
self.tx = x//CELL
|
||||
self.ty = y//CELL
|
||||
self.bubber = bubber
|
||||
|
||||
def follow(self, x, y):
|
||||
self.tx = x//CELL
|
||||
self.ty = y//CELL
|
||||
self.gen = [self.following(x, y)]
|
||||
|
||||
def following(self, nx, ny):
|
||||
dx = (nx - self.x) / 7.0
|
||||
dy = (ny - self.y) / 7.0
|
||||
for i in range(6, 0, -1):
|
||||
self.move(nx - int(i*dx), ny - int(i*dy))
|
||||
yield None
|
||||
self.move(nx, ny)
|
||||
|
||||
def set(self, c):
|
||||
x, y = self.tx, self.ty
|
||||
if 0 <= x < curboard.width and 0 <= y < curboard.height:
|
||||
line = curboard.walls[y]
|
||||
curboard.walls[y] = line[:x] + c + line[x+1:]
|
||||
|
||||
def stop(self, tetris):
|
||||
self.set('X')
|
||||
self.seticon(images.sprget(('t-brick2', self.bubber.pn)))
|
||||
images.ActiveSprites.remove(self)
|
||||
tetris.staticbricks[self.tx, self.ty] = self
|
||||
self.staticbricks = tetris.staticbricks
|
||||
|
||||
def remove(self):
|
||||
del self.staticbricks[self.tx, self.ty]
|
||||
self.set(' ')
|
||||
gamesrv.Sprite.kill(self)
|
||||
|
||||
def shiftdown(self):
|
||||
del self.staticbricks[self.tx, self.ty]
|
||||
self.set(' ')
|
||||
self.ty += 1
|
||||
self.set('X')
|
||||
self.staticbricks[self.tx, self.ty] = self
|
||||
self.step(0, CELL)
|
||||
|
||||
|
||||
class Tetris:
|
||||
|
||||
def bgen(self, limittime = 90.1): # 1:30
|
||||
import boards
|
||||
from player import BubPlayer
|
||||
|
||||
self.score = {}
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
|
||||
tc = boards.TimeCounter(limittime)
|
||||
self.ready = 0
|
||||
self.staticbricks = {}
|
||||
finished = 0
|
||||
for t in self.frame():
|
||||
t = boards.normal_frame()
|
||||
self.build_eyes()
|
||||
yield t
|
||||
tc.update(t)
|
||||
if tc.time == 0.0:
|
||||
self.ready = 2
|
||||
finished += not self.still_playing()
|
||||
if finished > 16:
|
||||
break
|
||||
if (BubPlayer.FrameCounter & 15) == 7:
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bubble):
|
||||
s.pop()
|
||||
elif isinstance(s, Bonus):
|
||||
s.kill()
|
||||
|
||||
tc.restore()
|
||||
for t in boards.result_ranking(self.score):
|
||||
self.remove_eyes()
|
||||
yield t
|
||||
for s in self.staticbricks.values():
|
||||
s.remove()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
return self.score.get(bubber, 0)
|
||||
|
||||
def frame(self):
|
||||
heights = {1: curboard.height,
|
||||
curboard.width-2: curboard.height}
|
||||
ymax = curboard.height-1
|
||||
maxheight = curboard.height*3//4
|
||||
for x in range(2, curboard.width-2):
|
||||
if bget(x, ymax) == ' ':
|
||||
curboard.putwall(x, ymax)
|
||||
height = 1
|
||||
for y in range(ymax-1, -1, -1):
|
||||
if bget(x, y) == '#':
|
||||
if height == maxheight:
|
||||
curboard.killwall(x, y)
|
||||
else:
|
||||
height += 1
|
||||
heights[x] = height
|
||||
xlist = range(2, curboard.width-2)
|
||||
random.shuffle(xlist)
|
||||
for x in xlist:
|
||||
h = heights[x]
|
||||
x1 = x2 = x
|
||||
while heights[x1-1] == h:
|
||||
x1 -= 1
|
||||
while heights[x2] == h:
|
||||
x2 += 1
|
||||
parts = (x2-x1) // 8
|
||||
if not parts:
|
||||
continue
|
||||
left = 0
|
||||
if heights[x1-1] > h:
|
||||
x1 -= 1
|
||||
left += 1
|
||||
right = parts+1
|
||||
if heights[x2] > h:
|
||||
x2 += 1
|
||||
right -= 1
|
||||
for p in range(left, right):
|
||||
x = x1 + ((x2-x1-1)*p+parts//2)//parts
|
||||
y = ymax
|
||||
for i in range(2):
|
||||
while bget(x, y) == '#':
|
||||
y -= 1
|
||||
if y >= 3:
|
||||
curboard.putwall(x, y)
|
||||
heights[x] += 1
|
||||
curboard.reorder_walls()
|
||||
|
||||
walls_by_pos = curboard.walls_by_pos
|
||||
moves = 1
|
||||
s = 8.0
|
||||
while moves:
|
||||
moves = 0
|
||||
for y in range(curboard.height-3, -1, -1):
|
||||
for x in range(2, curboard.width-2):
|
||||
if ((y,x) in walls_by_pos and
|
||||
(y+1,x) not in walls_by_pos):
|
||||
y0 = y
|
||||
while (y0-1,x) in walls_by_pos:
|
||||
y0 -= 1
|
||||
w = curboard.killwall(x, y0, 0)
|
||||
curboard.putwall(x, y+1, w)
|
||||
moves = 1
|
||||
curboard.reorder_walls()
|
||||
for i in range(int(s)+2):
|
||||
yield None
|
||||
s *= 0.95
|
||||
self.ready = 1
|
||||
while 1:
|
||||
yield None
|
||||
|
||||
def build_eyes(self):
|
||||
from player import BubPlayer
|
||||
for p in BubPlayer.PlayerList:
|
||||
dragons = [d for d in p.dragons if not isinstance(d, BrickEyes)]
|
||||
if dragons and len(p.dragons) == len(dragons):
|
||||
dragon = random.choice(dragons)
|
||||
eyes = BrickEyes(self, p, dragon.dcap, dragon)
|
||||
p.dragons.append(eyes)
|
||||
#p.emotic(dragon, 4)
|
||||
for d in dragons:
|
||||
d.kill()
|
||||
|
||||
def still_playing(self):
|
||||
from player import BubPlayer
|
||||
for p in BubPlayer.PlayerList:
|
||||
for d in p.dragons:
|
||||
if d.gen:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def remove_eyes(self):
|
||||
from player import BubPlayer
|
||||
for p in BubPlayer.PlayerList:
|
||||
for d in p.dragons:
|
||||
d.kill()
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 1
|
||||
|
||||
def run():
|
||||
global curboard
|
||||
import boards
|
||||
from boards import curboard
|
||||
boards.replace_boardgen(Tetris().bgen())
|
||||
|
||||
def setup():
|
||||
from player import BubPlayer
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
images.sprmap[key, p.pn] = (filename % p.pn, rect)
|
||||
else:
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -251,7 +251,7 @@ class Lemmings:
|
||||
|
||||
testing = {}
|
||||
def addlemming():
|
||||
for x, y in testing.items():
|
||||
for x, y in list(testing.items()):
|
||||
if bget(x, y) != ' ' == bget(x, y-1):
|
||||
if x <= curboard.width//2:
|
||||
dir = 1
|
||||
@ -283,7 +283,7 @@ def run():
|
||||
boards.replace_boardgen(Lemmings().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
||||
|
289
bubbob/ext5/__init__.py.bak
Normal file
289
bubbob/ext5/__init__.py.bak
Normal file
@ -0,0 +1,289 @@
|
||||
from __future__ import generators
|
||||
import os, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
import boards
|
||||
from boards import CELL, HALFCELL, bget
|
||||
from monsters import Monster
|
||||
from player import Dragon, BubPlayer
|
||||
from bubbles import Bubble
|
||||
import bonuses
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
localmap = {
|
||||
('lem-walk', 1,0) : ('image1.ppm', ( 0, 0, 32, 32)),
|
||||
('lem-walk', 1,1) : ('image1.ppm', ( 32, 0, 32, 32)),
|
||||
('lem-walk', 1,2) : ('image1.ppm', ( 64, 0, 32, 32)),
|
||||
('lem-walk', 1,3) : ('image1.ppm', ( 96, 0, 32, 32)),
|
||||
('lem-walk', 1,4) : ('image1.ppm', (128, 0, 32, 32)),
|
||||
('lem-walk', 1,5) : ('image1.ppm', (160, 0, 32, 32)),
|
||||
('lem-walk', 1,6) : ('image1.ppm', (192, 0, 32, 32)),
|
||||
('lem-walk', 1,7) : ('image1.ppm', (224, 0, 32, 32)),
|
||||
('lem-fall', 1,0) : ('image1.ppm', (256, 0, 32, 32)),
|
||||
('lem-fall', 1,1) : ('image1.ppm', (288, 0, 32, 32)),
|
||||
('lem-fall', 1,2) : ('image1.ppm', (320, 0, 32, 32)),
|
||||
('lem-fall', 1,3) : ('image1.ppm', (352, 0, 32, 32)),
|
||||
|
||||
('lem-fall',-1,3) : ('image2.ppm', ( 0, 0, 32, 32)),
|
||||
('lem-fall',-1,2) : ('image2.ppm', ( 32, 0, 32, 32)),
|
||||
('lem-fall',-1,1) : ('image2.ppm', ( 64, 0, 32, 32)),
|
||||
('lem-fall',-1,0) : ('image2.ppm', ( 96, 0, 32, 32)),
|
||||
('lem-walk',-1,7) : ('image2.ppm', (128, 0, 32, 32)),
|
||||
('lem-walk',-1,6) : ('image2.ppm', (160, 0, 32, 32)),
|
||||
('lem-walk',-1,5) : ('image2.ppm', (192, 0, 32, 32)),
|
||||
('lem-walk',-1,4) : ('image2.ppm', (224, 0, 32, 32)),
|
||||
('lem-walk',-1,3) : ('image2.ppm', (256, 0, 32, 32)),
|
||||
('lem-walk',-1,2) : ('image2.ppm', (288, 0, 32, 32)),
|
||||
('lem-walk',-1,1) : ('image2.ppm', (320, 0, 32, 32)),
|
||||
('lem-walk',-1,0) : ('image2.ppm', (352, 0, 32, 32)),
|
||||
|
||||
('lem-jail', 0) : ('image4.ppm', ( 0, 0, 32, 32)),
|
||||
('lem-jail', 1) : ('image4.ppm', ( 0, 32, 32, 32)),
|
||||
('lem-jail', 2) : ('image4.ppm', ( 0, 64, 32, 32)),
|
||||
}
|
||||
for n in range(16):
|
||||
localmap[('lem-crash', n)] = ('image3.ppm', (32*n, 0, 32, 32))
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
snd_ouch = gamesrv.getsample(os.path.join(LocalDir, 'ouch.wav'))
|
||||
|
||||
|
||||
class Lemmy:
|
||||
right = [('lem-walk', 1,n) for n in range(8)]
|
||||
left = [('lem-walk',-1,n) for n in range(8)]
|
||||
jailed = [('lem-jail', n) for n in range(3)]
|
||||
|
||||
|
||||
class Lemming(Monster):
|
||||
|
||||
def __init__(self, lemmings, x, y, dir):
|
||||
Monster.__init__(self, Lemmy, x, y, dir, in_list=lemmings.lemlist)
|
||||
self.lemmings = lemmings
|
||||
|
||||
def argh(self, *args, **kwds):
|
||||
self.untouchable()
|
||||
self.gen = [self.jumpout()]
|
||||
|
||||
def resetimages(self):
|
||||
pass
|
||||
|
||||
def touched(self, dragon):
|
||||
if 20 >= abs(self.x - dragon.x) >= 14:
|
||||
if self.x < dragon.x:
|
||||
self.dir = -1
|
||||
else:
|
||||
self.dir = 1
|
||||
|
||||
def in_bubble(self, bubble):
|
||||
self.move(bubble.x, bubble.y)
|
||||
Monster.in_bubble(self, bubble)
|
||||
return -1
|
||||
|
||||
def bubbling(self, bubble):
|
||||
dx = random.randrange(-3, 4)
|
||||
dy = random.randrange(-4, 2)
|
||||
counter = 0
|
||||
while not hasattr(bubble, 'poplist'):
|
||||
if self.y < -CELL and bubble.y > CELL: # bubble wrapped
|
||||
self.leaveboard(bubble)
|
||||
return
|
||||
self.move(bubble.x+dx, bubble.y+dy)
|
||||
yield None
|
||||
if bubble.poplist is None and bubble.y <= -2*CELL+1:
|
||||
self.leaveboard(bubble)
|
||||
return
|
||||
self.setimages(None)
|
||||
self.gen = [self.jumpout()]
|
||||
|
||||
def jumpout(self):
|
||||
# jumping out of the bubble
|
||||
self.seticon(images.sprget(self.mdef.jailed[1]))
|
||||
dxy = [(random.random()-0.5) * 9.0,
|
||||
(random.random()+0.5) * (-5.0)]
|
||||
for n in self.parabolic(dxy):
|
||||
yield n
|
||||
if dxy[1] >= 2.0:
|
||||
break
|
||||
if dxy[0] < 0:
|
||||
self.dir = -1
|
||||
else:
|
||||
self.dir = 1
|
||||
self.touchable = 1
|
||||
self.gen.append(self.falling())
|
||||
|
||||
def falling(self):
|
||||
self.setimages(None)
|
||||
n = 0
|
||||
lemmap = self.lemmings.lemmap
|
||||
while not self.onground():
|
||||
yield None
|
||||
self.move(self.x, (self.y + 4) & ~3,
|
||||
lemmap['lem-fall', self.dir, n&3])
|
||||
n += 1
|
||||
if self.y >= boards.bheight:
|
||||
self.kill()
|
||||
return
|
||||
yield None
|
||||
if n <= 33:
|
||||
self.gen.append(self.walking())
|
||||
else:
|
||||
self.play(snd_ouch)
|
||||
self.untouchable()
|
||||
self.to_front()
|
||||
self.gen = [self.die([('lem-crash', n) for n in range(16)], 2)]
|
||||
|
||||
def walking(self):
|
||||
self.setimages(None)
|
||||
n = 0
|
||||
lemmap = self.lemmings.lemmap
|
||||
y0 = self.y // 16
|
||||
while self.y == y0*16:
|
||||
yield None
|
||||
nx = self.x + self.dir*2
|
||||
x0 = (nx+15) // 16
|
||||
if bget(x0, y0+1) == ' ':
|
||||
if bget(x0, y0+2) == ' ':
|
||||
y0 += 1 # fall
|
||||
elif bget(x0, y0) != ' ':
|
||||
self.dir = -self.dir
|
||||
self.resetimages()
|
||||
continue
|
||||
else: # climb
|
||||
y0 -= 1
|
||||
n2 = 0
|
||||
while self.y > y0*16:
|
||||
self.step(0, -2)
|
||||
if n2:
|
||||
n2 -= 1
|
||||
else:
|
||||
self.seticon(lemmap['lem-walk', self.dir, n&7])
|
||||
n += 1
|
||||
n2 = 2
|
||||
yield None
|
||||
self.move(nx, self.y, lemmap['lem-walk', self.dir, n&7])
|
||||
n += 1
|
||||
yield None
|
||||
yield None
|
||||
self.gen.append(self.falling())
|
||||
|
||||
def onground(self):
|
||||
if self.y & 15:
|
||||
return 0
|
||||
x0 = (self.x+15) // 16
|
||||
y0 = self.y // 16 + 2
|
||||
return bget(x0, y0) != ' ' == bget(x0, y0-1)
|
||||
|
||||
def leaveboard(self, bubble):
|
||||
if hasattr(bubble, 'd'):
|
||||
bubble.play(images.Snd.Extra)
|
||||
score = self.lemmings.score
|
||||
bubber = bubble.d.bubber
|
||||
score[bubber] = score.get(bubber, 0) + 1
|
||||
bonuses.points(bubble.x, bubble.y, bubble.d, 500)
|
||||
self.kill()
|
||||
|
||||
default_mode = walking
|
||||
|
||||
|
||||
class Lemmings:
|
||||
|
||||
def bgen(self, limittime = 60.1): # 0:60
|
||||
self.score = {}
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
self.lemmap = {}
|
||||
for key in localmap:
|
||||
self.lemmap[key] = images.sprget(key)
|
||||
|
||||
tc = boards.TimeCounter(limittime)
|
||||
self.lemlist = []
|
||||
self.lemtotal = 0
|
||||
for t in self.frame():
|
||||
t = boards.normal_frame()
|
||||
yield t
|
||||
tc.update(t)
|
||||
if tc.time == 0.0:
|
||||
break
|
||||
|
||||
tc.restore()
|
||||
for s in self.lemlist[:]:
|
||||
if s.alive:
|
||||
s.kill()
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, Bubble):
|
||||
s.pop()
|
||||
for t in boards.result_ranking(self.score.copy(), self.lemtotal):
|
||||
yield t
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
return self.score.get(bubber, 0)
|
||||
|
||||
def frame(self):
|
||||
windline = '>>' + '^'*(curboard.width-4) + '<<'
|
||||
curboard.winds = [windline] * curboard.height
|
||||
|
||||
countholes = 0
|
||||
ymax = curboard.height-1
|
||||
for x in range(2, curboard.width-2):
|
||||
if bget(x, ymax) == ' ':
|
||||
countholes += 1
|
||||
|
||||
xrange = []
|
||||
try:
|
||||
for delta in range(2, curboard.width):
|
||||
for x in [delta, curboard.width-delta-1]:
|
||||
if x in xrange: raise StopIteration
|
||||
xrange.append(x)
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
for x in xrange:
|
||||
if countholes > curboard.width//6 and bget(x, ymax) == ' ':
|
||||
curboard.putwall(x, ymax)
|
||||
curboard.reorder_walls()
|
||||
countholes -= 1
|
||||
for y in range(0, ymax):
|
||||
if bget(x, y) == ' ':
|
||||
break
|
||||
curboard.killwall(x, y)
|
||||
yield None
|
||||
|
||||
testing = {}
|
||||
def addlemming():
|
||||
for x, y in testing.items():
|
||||
if bget(x, y) != ' ' == bget(x, y-1):
|
||||
if x <= curboard.width//2:
|
||||
dir = 1
|
||||
else:
|
||||
dir = -1
|
||||
s = Lemming(self, x*CELL-HALFCELL, (y-2)*CELL, dir)
|
||||
self.lemtotal += 1
|
||||
if y < ymax:
|
||||
testing[x] = y+1
|
||||
else:
|
||||
del testing[x]
|
||||
for x in xrange:
|
||||
testing[x] = 1
|
||||
addlemming()
|
||||
yield None
|
||||
while testing:
|
||||
addlemming()
|
||||
yield None
|
||||
|
||||
while self.lemlist:
|
||||
yield None
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 1
|
||||
|
||||
def run():
|
||||
global curboard
|
||||
from boards import curboard
|
||||
boards.replace_boardgen(Lemmings().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -258,7 +258,7 @@ def run():
|
||||
boards.replace_boardgen(Tron().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
|
268
bubbob/ext6/__init__.py.bak
Normal file
268
bubbob/ext6/__init__.py.bak
Normal file
@ -0,0 +1,268 @@
|
||||
from __future__ import generators
|
||||
import os, random
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
import boards
|
||||
from boards import CELL, HALFCELL, bget
|
||||
from player import Dragon, BubPlayer
|
||||
from mnstrmap import Monky
|
||||
from bubbles import Bubble
|
||||
from bonuses import Bonus
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
localmap = {
|
||||
('trn-head', 0,-1): ('image1-%d.ppm', (0, 0, 8, 8)),
|
||||
('trn-head',-1, 0): ('image1-%d.ppm', (0, 8, 8, 8)),
|
||||
('trn-head', 0, 1): ('image1-%d.ppm', (0,16, 8, 8)),
|
||||
('trn-head', 1, 0): ('image1-%d.ppm', (0,24, 8, 8)),
|
||||
('trn', 0,-1, 1, 0): ('image1-%d.ppm', (0,32, 8, 8)),
|
||||
('trn', 0, 1, 1, 0): ('image1-%d.ppm', (0,40, 8, 8)),
|
||||
('trn', 1, 0, 0,-1): ('image1-%d.ppm', (0,48, 8, 8)),
|
||||
('trn', 1, 0, 0, 1): ('image1-%d.ppm', (0,56, 8, 8)),
|
||||
('trn', 1, 0, 1, 0): ('image1-%d.ppm', (0,64, 8, 8)),
|
||||
('trn', 0, 1, 0, 1): ('image1-%d.ppm', (0,72, 8, 8)),
|
||||
}
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
snd_crash = gamesrv.getsample(os.path.join(LocalDir, 'crash.wav'))
|
||||
|
||||
|
||||
class TronHead(ActiveSprite):
|
||||
|
||||
def __init__(self, tron, bubber, dcap, cx, cy, dir):
|
||||
self.tron = tron
|
||||
self.bubber = bubber
|
||||
self.dcap = dcap
|
||||
self.cx = cx
|
||||
self.cy = cy
|
||||
self.dir = dir
|
||||
self.icons = {}
|
||||
for key in localmap:
|
||||
ico = images.sprget((key, bubber.pn))
|
||||
key = key[1:]
|
||||
self.icons[key] = ico
|
||||
if len(key) == 4:
|
||||
dx1, dy1, dx2, dy2 = key
|
||||
key = -dx2, -dy2, -dx1, -dy1
|
||||
self.icons[key] = ico
|
||||
ActiveSprite.__init__(self, self.icons[self.dir],
|
||||
self.cx*8-2, self.cy*8-2)
|
||||
self.gen.append(self.trailing())
|
||||
|
||||
def forward_step(self, dir):
|
||||
s = gamesrv.Sprite(self.icons[self.dir + dir], self.x, self.y)
|
||||
self.tron.trailsprites.append(s)
|
||||
self.dir = dir
|
||||
self.cx += dir[0]
|
||||
self.cy += dir[1]
|
||||
self.move(self.cx*8-2, self.cy*8-2, self.icons[dir])
|
||||
|
||||
def trailing(self):
|
||||
unoccupied = self.tron.unoccupied
|
||||
bubber = self.bubber
|
||||
# first go straight forward until we enter the playing board itself
|
||||
while (self.cx, self.cy) not in unoccupied:
|
||||
self.forward_step(self.dir)
|
||||
yield None
|
||||
yield None
|
||||
# playing!
|
||||
unoccupied[self.cx, self.cy] = False
|
||||
while True:
|
||||
# turn
|
||||
d = [(bubber.key_left, -1, 0),
|
||||
(bubber.key_right, 1, 0),
|
||||
(bubber.key_jump, 0,-1),
|
||||
(bubber.key_fire, 0, 1)]
|
||||
d.sort()
|
||||
newdir = self.dir
|
||||
if d[-1][0] > d[-2][0]:
|
||||
newdir = d[-1][1:]
|
||||
if (self.dir + newdir) not in self.icons:
|
||||
newdir = self.dir # forbidden 180-degree turn
|
||||
# move one step forward
|
||||
self.forward_step(newdir)
|
||||
# crash?
|
||||
if not unoccupied.get((self.cx, self.cy)):
|
||||
self.crash()
|
||||
return
|
||||
unoccupied[self.cx, self.cy] = False
|
||||
yield None
|
||||
yield None
|
||||
|
||||
def to_front(self):
|
||||
if self.gen:
|
||||
ActiveSprite.to_front(self)
|
||||
|
||||
def crash(self):
|
||||
self.move(self.x - self.dir[0], self.y - self.dir[1],
|
||||
self.icons[self.dir+self.dir])
|
||||
self.to_back()
|
||||
self.play(snd_crash)
|
||||
ico = images.sprget(Monky.decay_weapon[1])
|
||||
s = ActiveSprite(ico, self.x + self.ico.w//2 - CELL,
|
||||
self.y + self.ico.h//2 - CELL)
|
||||
s.gen.append(s.die(Monky.decay_weapon[1:], 4))
|
||||
self.stop()
|
||||
|
||||
def stop(self):
|
||||
del self.gen[:]
|
||||
try:
|
||||
self.tron.trons.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def kill(self):
|
||||
self.stop()
|
||||
try:
|
||||
self.bubber.dragons.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
ActiveSprite.kill(self)
|
||||
|
||||
|
||||
class Tron:
|
||||
|
||||
def bgen(self, limittime = 60.1): # 1:00
|
||||
self.score = {}
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
|
||||
self.ready = 0
|
||||
self.trons = []
|
||||
self.trailsprites = []
|
||||
self.playerlist = BubPlayer.PlayerList[:]
|
||||
tc = boards.TimeCounter(limittime)
|
||||
for t in self.frame(tc):
|
||||
t = boards.normal_frame()
|
||||
self.build_trons()
|
||||
yield t
|
||||
tc.update(t)
|
||||
if (BubPlayer.FrameCounter & 15) == 7:
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bubble):
|
||||
s.pop()
|
||||
elif isinstance(s, Bonus):
|
||||
s.kill()
|
||||
|
||||
self.ready = 0
|
||||
tc.restore()
|
||||
for t in boards.result_ranking(self.score):
|
||||
for p in BubPlayer.PlayerList:
|
||||
for d in p.dragons[:]:
|
||||
d.kill()
|
||||
yield t
|
||||
self.remove_trons()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
return self.score.get(bubber, 0)
|
||||
|
||||
def build_trons(self):
|
||||
if self.ready == 0:
|
||||
self.remove_trons()
|
||||
return
|
||||
for p in self.playerlist:
|
||||
dragons = [d for d in p.dragons if not isinstance(d, TronHead)]
|
||||
if self.ready < 10 and dragons and len(p.dragons) == len(dragons):
|
||||
self.score.setdefault(p, 0)
|
||||
dragon = random.choice(dragons)
|
||||
x, y, dir = self.select_start_point()
|
||||
head = TronHead(self, p, dragon.dcap, x, y, dir)
|
||||
self.trons.append(head)
|
||||
p.dragons.append(head)
|
||||
#p.emotic(head, 4)
|
||||
for d in dragons:
|
||||
d.kill()
|
||||
|
||||
def remove_trons(self):
|
||||
for p in BubPlayer.PlayerList:
|
||||
for d in p.dragons[:]:
|
||||
d.kill()
|
||||
for s in self.trailsprites:
|
||||
s.kill()
|
||||
del self.trailsprites[:]
|
||||
|
||||
def select_start_point(self):
|
||||
distmin = 12
|
||||
while True:
|
||||
x, y, dir = random.choice(self.start_points)
|
||||
for head in self.trons:
|
||||
if abs(x-head.cx//2) + abs(y-head.cy//2) < distmin:
|
||||
break
|
||||
else:
|
||||
break
|
||||
distmin *= 0.95
|
||||
if (y, x) in curboard.walls_by_pos:
|
||||
curboard.killwall(x, y)
|
||||
x = 2*x+1
|
||||
y = 2*y - dir[1]
|
||||
if dir[1] < 0:
|
||||
y += 2
|
||||
return x, y, dir
|
||||
|
||||
def frame(self, tc):
|
||||
y1 = 1
|
||||
y2 = curboard.height-2
|
||||
while y1 <= y2:
|
||||
for y in [y1, y2]:
|
||||
for x in range(2, curboard.width-2):
|
||||
if (y, x) in curboard.walls_by_pos:
|
||||
curboard.killwall(x, y)
|
||||
yield None
|
||||
y1 += 1
|
||||
y2 -= 1
|
||||
|
||||
self.start_points = []
|
||||
for x in range(4, curboard.width-3):
|
||||
self.start_points.append((x, 0, (0, 1)))
|
||||
self.start_points.append((x, curboard.height-1, (0, -1)))
|
||||
|
||||
while tc.time != 0.0:
|
||||
for y in [0, curboard.height-1]:
|
||||
for x in range(2, curboard.width-2):
|
||||
if (y, x) not in curboard.walls_by_pos:
|
||||
curboard.putwall(x, y)
|
||||
curboard.reorder_walls()
|
||||
self.unoccupied = {}
|
||||
for x in range(5, 2*curboard.width-4):
|
||||
for y in range(3, 2*curboard.height-2):
|
||||
self.unoccupied[x, y] = True
|
||||
random.shuffle(self.playerlist)
|
||||
for i in range(5):
|
||||
yield None
|
||||
|
||||
min_players = 1
|
||||
while self.ready < 20 or len(self.trons) >= min_players:
|
||||
if len(self.trons) >= 2:
|
||||
min_players = 2
|
||||
self.ready += 1
|
||||
yield None
|
||||
|
||||
if len(self.trons) == 1:
|
||||
bubber = self.trons[0].bubber
|
||||
self.score[bubber] += 1
|
||||
bubber.givepoints(100)
|
||||
self.trons[0].stop()
|
||||
self.ready = 99
|
||||
|
||||
for i in range(28):
|
||||
yield None
|
||||
self.ready = 0
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 2
|
||||
|
||||
def run():
|
||||
global curboard
|
||||
from boards import curboard
|
||||
boards.replace_boardgen(Tron().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
images.sprmap[key, p.pn] = (filename % p.pn, rect)
|
||||
else:
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, random, math
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
@ -312,7 +312,7 @@ class Camel:
|
||||
|
||||
tc.restore()
|
||||
score = {}
|
||||
for player, shotlist in self.score.items():
|
||||
for player, shotlist in list(self.score.items()):
|
||||
score[player] = len(shotlist)
|
||||
for t in boards.result_ranking(score):
|
||||
for p in BubPlayer.PlayerList:
|
||||
@ -389,7 +389,7 @@ def run():
|
||||
boards.replace_boardgen(Camel().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
for key, (filename, rect) in list(localmap.items()):
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
|
399
bubbob/ext7/__init__.py.bak
Normal file
399
bubbob/ext7/__init__.py.bak
Normal file
@ -0,0 +1,399 @@
|
||||
from __future__ import generators
|
||||
import os, random, math
|
||||
import images, gamesrv
|
||||
from images import ActiveSprite
|
||||
import boards
|
||||
from boards import CELL
|
||||
from player import Dragon, BubPlayer, scoreboard
|
||||
from bubbles import Bubble
|
||||
from bonuses import Bonus
|
||||
from mnstrmap import PlayerBubbles
|
||||
from mnstrmap import Monky
|
||||
import bonuses
|
||||
from ext6 import snd_crash
|
||||
|
||||
LocalDir = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
ANGLE_COUNT = 24
|
||||
ANGLE_STEP = 360 / ANGLE_COUNT
|
||||
ANGLE_TABLE = {}
|
||||
for i in range(ANGLE_COUNT):
|
||||
a = i*ANGLE_STEP*math.pi/180.0
|
||||
ANGLE_TABLE[i*ANGLE_STEP] = (math.cos(a), math.sin(a))
|
||||
|
||||
|
||||
localmap = {}
|
||||
for i in range(ANGLE_COUNT):
|
||||
localmap['camel', i] = ('image1-%d.ppm', (0, i*36, 36, 36))
|
||||
|
||||
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
||||
snd_fire = gamesrv.getsample(os.path.join(LocalDir, 'fire.wav'))
|
||||
snd_hit = gamesrv.getsample(os.path.join(LocalDir, 'hit.wav'))
|
||||
|
||||
|
||||
class Plane(ActiveSprite):
|
||||
lock = None
|
||||
|
||||
def __init__(self, camel, bubber, dcap, x, y, dirhint=None):
|
||||
self.bubber = bubber
|
||||
self.dcap = dcap
|
||||
self.camel = camel
|
||||
self.shotlist = camel.score.setdefault(bubber, {})
|
||||
|
||||
if x < x_min:
|
||||
x = x_min
|
||||
elif x > x_max:
|
||||
x = x_max
|
||||
|
||||
if y < 4*CELL:
|
||||
y = 4*CELL
|
||||
elif y > (curboard.height-4)*CELL - 36:
|
||||
y = (curboard.height-4)*CELL - 36
|
||||
|
||||
if dirhint not in (1, -1):
|
||||
controldelay = 5
|
||||
if x < boards.bwidth//2:
|
||||
dir = 1
|
||||
else:
|
||||
dir = -1
|
||||
else:
|
||||
controldelay = 20
|
||||
if x < boards.bwidth//3:
|
||||
dir = 1
|
||||
elif x >= boards.bwidth*2//3:
|
||||
dir = -1
|
||||
else:
|
||||
dir = dirhint
|
||||
if dir > 0:
|
||||
self.angle = 0
|
||||
self.flipped = False
|
||||
else:
|
||||
self.angle = 180
|
||||
self.flipped = True
|
||||
|
||||
ActiveSprite.__init__(self, self.getico(), x, y)
|
||||
self.fx = self.x
|
||||
self.fy = self.y
|
||||
self.controlgen = self.control(delay=controldelay)
|
||||
self.gen.append(self.fly())
|
||||
self.gen.append(self.controlgen)
|
||||
self.gen.append(self.blink())
|
||||
self.gen.append(self.bob())
|
||||
|
||||
def controlled(self):
|
||||
return self.controlgen in self.gen
|
||||
|
||||
def getico(self):
|
||||
a = self.angle // ANGLE_STEP
|
||||
if self.flipped:
|
||||
if a:
|
||||
a = ANGLE_COUNT-a
|
||||
key = 'vflip', ('camel', a, self.bubber.pn)
|
||||
else:
|
||||
key = 'camel', a, self.bubber.pn
|
||||
return images.sprget(key)
|
||||
|
||||
def blink(self):
|
||||
for i in range(10):
|
||||
yield None
|
||||
yield None
|
||||
self.setdisplaypos(-256, -256)
|
||||
yield None
|
||||
self.setdisplaypos(-256, -256)
|
||||
yield None
|
||||
self.touchable = 1
|
||||
|
||||
def bob(self):
|
||||
f = 3.0
|
||||
for i in range(0, 1080, ANGLE_STEP):
|
||||
self.fy += f * ANGLE_TABLE[i % 360][1]
|
||||
f *= 0.98
|
||||
yield None
|
||||
|
||||
## def loosealtitude(self, y0, angle0):
|
||||
## if 90 <= angle0 < 270 or (angle0 == 270 and not self.flipped):
|
||||
## angledir = -1
|
||||
## else:
|
||||
## angledir = 1
|
||||
## for i in range(0, 180, ANGLE_STEP):
|
||||
## if i % (4*ANGLE_STEP) == 0 and not (45 <= angle0 <= 135):
|
||||
## angle0 += ANGLE_STEP * angledir
|
||||
## angle0 = (angle0 + 360) % 360
|
||||
## y0 += 4.0 * ANGLE_TABLE[i][1]
|
||||
## if y0 > self.fy:
|
||||
## self.fy = y0
|
||||
## self.angle = angle0
|
||||
## yield None
|
||||
|
||||
def turn(self, dir):
|
||||
self.angle += ANGLE_STEP * dir
|
||||
self.angle = (self.angle + 360) % 360
|
||||
|
||||
def control(self, delay=0):
|
||||
bubber = self.bubber
|
||||
prev_key_jump = 0
|
||||
for i in range(delay):
|
||||
yield None
|
||||
shootdelay = 0
|
||||
while True:
|
||||
wannago = bubber.wannago(self.dcap)
|
||||
self.turn(wannago)
|
||||
if shootdelay:
|
||||
shootdelay -= 1
|
||||
elif bubber.key_fire:
|
||||
x = self.x + self.ico.w//2
|
||||
y = self.y + self.ico.h//2
|
||||
acos, asin = ANGLE_TABLE[self.angle]
|
||||
x += acos * 20
|
||||
y += asin * 20
|
||||
if self.flipped:
|
||||
acos = -acos
|
||||
asin = -asin
|
||||
x -= asin * 5
|
||||
y += acos * 5
|
||||
self.play(snd_fire)
|
||||
Shot(self, int(x), int(y), self.angle, 2)
|
||||
Shot(self, int(x), int(y), self.angle)
|
||||
shootdelay = 7
|
||||
for i in range(2):
|
||||
if bubber.key_jump > prev_key_jump:
|
||||
self.flipped = not self.flipped
|
||||
prev_key_jump = bubber.key_jump
|
||||
yield None
|
||||
for s in self.touching(12):
|
||||
if isinstance(s, Plane) and s is not self:
|
||||
ico = images.sprget(Monky.decay_weapon[1])
|
||||
s1 = ActiveSprite(ico,
|
||||
(self.x+s.x)//2 + self.ico.w//2 - CELL,
|
||||
(self.y+s.y)//2 + self.ico.h//2 - CELL)
|
||||
s1.gen.append(s1.die(Monky.decay_weapon[1:], 4))
|
||||
s1.play(snd_crash)
|
||||
self.gen = [self.godowninflames(s)]
|
||||
s.gen = [s.godowninflames(self)]
|
||||
|
||||
def fly(self, speed=3.3):
|
||||
while True:
|
||||
if (self.y < 0 and not (0 < self.angle < 180) and
|
||||
((abs(270 - self.angle) < -4*self.y) or random.random() < 0.2)):
|
||||
if (90 <= self.angle < 270 or
|
||||
(self.angle == 270 and not self.flipped)):
|
||||
self.turn(-1)
|
||||
else:
|
||||
self.turn(1)
|
||||
ico = self.getico()
|
||||
acos, asin = ANGLE_TABLE[self.angle]
|
||||
self.fx += acos * speed
|
||||
self.fy += asin * speed
|
||||
self.move(int(self.fx), int(self.fy), ico)
|
||||
if self.x < x_min:
|
||||
self.angle = 2 * ANGLE_STEP
|
||||
self.flipped = not self.flipped
|
||||
self.gen = [self.godowninflames()]
|
||||
self.play(images.Snd.Pop)
|
||||
elif self.x > x_max:
|
||||
self.angle = 180 - 2 * ANGLE_STEP
|
||||
self.flipped = not self.flipped
|
||||
self.gen = [self.godowninflames()]
|
||||
self.play(images.Snd.Pop)
|
||||
elif self.y > y_max:
|
||||
self.gen = [self.crashed()]
|
||||
yield None
|
||||
|
||||
def godowninflames(self, hit_by_plane=None):
|
||||
if hit_by_plane and hit_by_plane in self.shotlist:
|
||||
hittime = self.shotlist[hit_by_plane]
|
||||
if BubPlayer.FrameCounter < hittime + 60:
|
||||
del self.shotlist[hit_by_plane]
|
||||
scoreboard()
|
||||
self.seticon(self.getico())
|
||||
self.gen.append(self.fly())
|
||||
trail = [(self.x, self.y)] * 7
|
||||
ico = images.sprget(PlayerBubbles.explosion[0])
|
||||
s = ActiveSprite(ico, self.x + self.ico.w//2 - CELL,
|
||||
self.y + self.ico.h//2 - CELL)
|
||||
s.gen.append(s.die(PlayerBubbles.explosion))
|
||||
self.bubber.emotic(self, 4)
|
||||
while True:
|
||||
yield None
|
||||
if random.random() < 0.37:
|
||||
ico = images.sprget(Bubble.exploding_bubbles[0])
|
||||
x, y = random.choice(trail)
|
||||
x += random.randint(-10, 10)
|
||||
y += random.randint(-10, 10)
|
||||
s = ActiveSprite(ico, x+2, y+2)
|
||||
s.gen.append(s.die(Bubble.exploding_bubbles))
|
||||
if random.random() < 0.5:
|
||||
yield None
|
||||
if 90 <= self.angle < 270:
|
||||
lst = [0, 0, 0, 0, -1, -1, -1, 1, 1]
|
||||
else:
|
||||
lst = [0, 0, 0, 0, -1, -1, 1, 1, 1]
|
||||
self.turn(random.choice(lst))
|
||||
trail.pop(0)
|
||||
trail.append((self.x, self.y))
|
||||
|
||||
def crashed(self):
|
||||
self.untouchable()
|
||||
self.play(snd_crash)
|
||||
ico = images.sprget(Monky.decay_weapon[1])
|
||||
self.seticon(ico)
|
||||
self.step(self.ico.w//2 - CELL,
|
||||
self.ico.h//2 - CELL)
|
||||
self.gen.append(self.die(Monky.decay_weapon[1:], 4))
|
||||
yield None
|
||||
|
||||
def kill(self):
|
||||
try:
|
||||
self.bubber.dragons.remove(self)
|
||||
except ValueError:
|
||||
pass
|
||||
ActiveSprite.kill(self)
|
||||
|
||||
|
||||
class Shot(ActiveSprite):
|
||||
|
||||
def __init__(self, plane, x, y, angle, steps=0):
|
||||
ico = images.sprcharacterget('.')
|
||||
ActiveSprite.__init__(self, ico, x-4, y-12)
|
||||
self.plane = plane
|
||||
self.angle = angle
|
||||
self.gen.append(self.moving(steps))
|
||||
|
||||
def moving(self, steps=0):
|
||||
minx = 2*CELL - 4
|
||||
maxx = (curboard.width-2)*CELL - 4
|
||||
maxy = (curboard.height-1)*CELL - 12
|
||||
fx = self.x
|
||||
fy = self.y
|
||||
dx, dy = ANGLE_TABLE[self.angle]
|
||||
dx *= 7.6
|
||||
dy *= 7.6
|
||||
fx += dx * steps
|
||||
fy += dy * steps
|
||||
for i in range(22-steps):
|
||||
for s in images.touching(self.x+3, self.y+11, 2, 2):
|
||||
if isinstance(s, Plane) and s is not self.plane:
|
||||
self.play(snd_hit)
|
||||
self.kill()
|
||||
if s.controlled():
|
||||
s.gen = [s.godowninflames(self.plane)]
|
||||
self.plane.shotlist[s] = BubPlayer.FrameCounter
|
||||
bonuses.points(self.x + 4 - CELL, self.y + 12 - CELL,
|
||||
self.plane, 100)
|
||||
return
|
||||
fx += dx
|
||||
fy += dy
|
||||
self.move(int(fx), int(fy))
|
||||
if self.x < minx or self.x > maxx or self.y > maxy:
|
||||
break
|
||||
yield None
|
||||
self.kill()
|
||||
|
||||
|
||||
class Camel:
|
||||
|
||||
def bgen(self, limittime = 90.1): # 1:30
|
||||
self.score = {}
|
||||
for t in boards.initsubgame(music, self.displaypoints):
|
||||
yield t
|
||||
|
||||
tc = boards.TimeCounter(limittime)
|
||||
for t in self.frame(tc):
|
||||
t = boards.normal_frame()
|
||||
self.build_planes()
|
||||
yield t
|
||||
tc.update(t)
|
||||
if (BubPlayer.FrameCounter & 15) == 7:
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bubble):
|
||||
s.pop()
|
||||
elif isinstance(s, Bonus):
|
||||
s.kill()
|
||||
|
||||
tc.restore()
|
||||
score = {}
|
||||
for player, shotlist in self.score.items():
|
||||
score[player] = len(shotlist)
|
||||
for t in boards.result_ranking(score):
|
||||
for p in BubPlayer.PlayerList:
|
||||
for d in p.dragons[:]:
|
||||
d.kill()
|
||||
yield t
|
||||
self.remove_planes()
|
||||
|
||||
def displaypoints(self, bubber):
|
||||
return len(self.score.get(bubber, ()))
|
||||
|
||||
def build_planes(self):
|
||||
for p in BubPlayer.PlayerList:
|
||||
dragons = [d for d in p.dragons if not isinstance(d, Plane)]
|
||||
if dragons and len(p.dragons) == len(dragons):
|
||||
dragon = random.choice(dragons)
|
||||
if dragon.dcap['infinite_shield']:
|
||||
start_position = self.select_start_position()
|
||||
dirhint = None
|
||||
else:
|
||||
start_position = dragon.x-2, dragon.y-2
|
||||
dirhint = getattr(dragon, 'dir', None)
|
||||
plane = Plane(self, p, dragon.dcap,
|
||||
start_position[0], start_position[1], dirhint)
|
||||
p.dragons.append(plane)
|
||||
p.emotic(plane, 4)
|
||||
for d in dragons:
|
||||
d.kill()
|
||||
|
||||
def remove_planes(self):
|
||||
for p in BubPlayer.PlayerList:
|
||||
for d in p.dragons[:]:
|
||||
d.kill()
|
||||
|
||||
def select_start_position(self):
|
||||
planes = [d for p in BubPlayer.PlayerList
|
||||
for d in p.dragons
|
||||
if isinstance(d, Plane)]
|
||||
distmin = 180
|
||||
while True:
|
||||
x = random.choice([x_min, x_max])
|
||||
y = random.randint(2*CELL, (curboard.height-4)*CELL - 36)
|
||||
for d in planes:
|
||||
dist = (x-d.x)*(x-d.x) + (y-d.y)*(y-d.y)
|
||||
if dist < distmin*distmin:
|
||||
break
|
||||
else:
|
||||
return x, y
|
||||
distmin = int(distmin * 0.94)
|
||||
|
||||
def frame(self, tc):
|
||||
y = curboard.height-1
|
||||
for x in range(2, curboard.width-2):
|
||||
if (y, x) not in curboard.walls_by_pos:
|
||||
curboard.putwall(x, y)
|
||||
curboard.reorder_walls()
|
||||
for y in range(0, curboard.height-1):
|
||||
yield None
|
||||
for x in range(2, curboard.width-2):
|
||||
if (y, x) in curboard.walls_by_pos:
|
||||
curboard.killwall(x, y)
|
||||
while tc.time != 0.0:
|
||||
yield None
|
||||
|
||||
# This game is suitable for at least min_players players
|
||||
min_players = 2
|
||||
|
||||
def run():
|
||||
global curboard, x_min, x_max, y_max
|
||||
from boards import curboard
|
||||
x_min = 2*CELL - 3
|
||||
x_max = (curboard.width-2)*CELL - 36 + 3
|
||||
y_max = (curboard.height-1)*CELL - 36 + 7
|
||||
boards.replace_boardgen(Camel().bgen())
|
||||
|
||||
def setup():
|
||||
for key, (filename, rect) in localmap.items():
|
||||
filename = os.path.join(LocalDir, filename)
|
||||
if filename.find('%d') >= 0:
|
||||
for p in BubPlayer.PlayerList:
|
||||
images.sprmap[key + (p.pn,)] = (filename % p.pn, rect)
|
||||
else:
|
||||
images.sprmap[key] = (filename, rect)
|
||||
setup()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import gamesrv, os
|
||||
from sprmap import sprmap as original_sprmap
|
||||
from patmap import patmap
|
||||
@ -69,7 +69,7 @@ class ActiveSprite(gamesrv.Sprite):
|
||||
# common generators
|
||||
def cyclic(self, nimages, speed=5):
|
||||
images = [sprget(n) for n in nimages]
|
||||
speed = range(speed)
|
||||
speed = list(range(speed))
|
||||
while 1:
|
||||
for img in images:
|
||||
self.seticon(img)
|
||||
@ -148,7 +148,7 @@ class ActiveSprite(gamesrv.Sprite):
|
||||
try:
|
||||
for g in glist:
|
||||
if self.alive:
|
||||
g.next()
|
||||
next(g)
|
||||
except StopIteration:
|
||||
try:
|
||||
self.gen.remove(g)
|
||||
@ -157,7 +157,7 @@ class ActiveSprite(gamesrv.Sprite):
|
||||
for g in glist[glist.index(g)+1:]:
|
||||
if self.alive:
|
||||
try:
|
||||
g.next()
|
||||
next(g)
|
||||
except StopIteration:
|
||||
pass
|
||||
yield None
|
||||
@ -166,7 +166,7 @@ def touching(x1, y1, w1, h1, margin=0):
|
||||
touch = {}
|
||||
x1 = int(x1)
|
||||
y1 = int(y1)
|
||||
xrange = range(x1>>5, (x1+w1+31)>>5)
|
||||
xrange = list(range(x1>>5, (x1+w1+31)>>5))
|
||||
for y in range(y1>>4, (y1+h1+15)>>4):
|
||||
for x in xrange:
|
||||
touch.update(SpritesByLoc.get((x,y), {}))
|
||||
@ -181,7 +181,7 @@ def action(sprlist, len=len):
|
||||
try:
|
||||
for g in glist:
|
||||
if self.alive:
|
||||
g.next()
|
||||
next(g)
|
||||
except StopIteration:
|
||||
try:
|
||||
self.gen.remove(g)
|
||||
@ -190,7 +190,7 @@ def action(sprlist, len=len):
|
||||
for g in glist[glist.index(g)+1:]:
|
||||
if self.alive:
|
||||
try:
|
||||
g.next()
|
||||
next(g)
|
||||
except StopIteration:
|
||||
pass
|
||||
if self.touchable and self.alive:
|
||||
@ -202,7 +202,7 @@ def action(sprlist, len=len):
|
||||
for key in self.ranges:
|
||||
del key[self]
|
||||
del self.ranges[:]
|
||||
xrange = range(x>>5, (x+self.ico.w+38)>>5)
|
||||
xrange = list(range(x>>5, (x+self.ico.w+38)>>5))
|
||||
for y in range(y>>4, (y+self.ico.h+22)>>4):
|
||||
for x in xrange:
|
||||
key = SpritesByLoc.setdefault((x,y), {})
|
||||
@ -303,7 +303,8 @@ def loadpattern(n, keycol=None):
|
||||
bitmap = gamesrv.getbitmap(filename, keycol)
|
||||
return bitmap, rect
|
||||
|
||||
def makebkgndpattern(bitmap, (x,y,w,h), darker={}):
|
||||
def makebkgndpattern(bitmap, xxx_todo_changeme, darker={}):
|
||||
(x,y,w,h) = xxx_todo_changeme
|
||||
from boards import CELL
|
||||
try:
|
||||
nbitmap, hscale, vscale = darker[bitmap]
|
||||
@ -329,7 +330,7 @@ def computebiggericon(ico, bigger={}):
|
||||
bigger[ico] = None, pixmap.imagezoomer(*ico.getimage())
|
||||
return None
|
||||
if computing is not None:
|
||||
result = computing.next() or computing.next() or computing.next()
|
||||
result = next(computing) or next(computing) or next(computing)
|
||||
if not result:
|
||||
return None # still computing
|
||||
w, h, data = result
|
||||
@ -456,12 +457,12 @@ def generate_sprmap():
|
||||
# check and maybe regenerate the colored image files
|
||||
file = os.path.join('images', 'buildcolors.py')
|
||||
g = {'__name__': '__auto__', '__file__': file}
|
||||
execfile(file, g)
|
||||
exec(compile(open(file, "rb").read(), file, 'exec'), g)
|
||||
# replace the entries 'filename_%d.ppm' by a family of entries,
|
||||
# one for each color
|
||||
sprmap = {}
|
||||
for n, (filename, rect) in (original_sprmap.items() +
|
||||
extramap.items() + hatmap.items()):
|
||||
for n, (filename, rect) in (list(original_sprmap.items()) +
|
||||
list(extramap.items()) + list(hatmap.items())):
|
||||
if filename.find('%d') >= 0:
|
||||
for i in range(MAX):
|
||||
sprmap[n+1000*i] = (os.path.join('images',filename % i), rect)
|
||||
|
542
bubbob/images.py.bak
Normal file
542
bubbob/images.py.bak
Normal file
@ -0,0 +1,542 @@
|
||||
from __future__ import generators
|
||||
import gamesrv, os
|
||||
from sprmap import sprmap as original_sprmap
|
||||
from patmap import patmap
|
||||
import mnstrmap
|
||||
import pixmap
|
||||
|
||||
KEYCOL = 0x010101
|
||||
MAX = 10
|
||||
|
||||
ActiveSprites = []
|
||||
SpritesByLoc = {}
|
||||
|
||||
|
||||
class ActiveSprite(gamesrv.Sprite):
|
||||
touchable = 0
|
||||
imgsetter = None
|
||||
angry = []
|
||||
priority = 0
|
||||
|
||||
def __init__(self, *args):
|
||||
gamesrv.Sprite.__init__(self, *args)
|
||||
if self.priority:
|
||||
ActiveSprites.insert(0, self)
|
||||
else:
|
||||
ActiveSprites.append(self)
|
||||
self.ranges = []
|
||||
self.gen = []
|
||||
|
||||
def kill(self):
|
||||
self.untouchable()
|
||||
del self.gen[:]
|
||||
ActiveSprites.remove(self)
|
||||
gamesrv.Sprite.kill(self)
|
||||
|
||||
def untouchable(self):
|
||||
self.touchable = 0
|
||||
for key in self.ranges:
|
||||
del key[self]
|
||||
del self.ranges[:]
|
||||
|
||||
def play(self, snd, volume=0.8):
|
||||
import boards
|
||||
xmin = 2*boards.CELL
|
||||
xmax = boards.bwidth-4*boards.CELL
|
||||
snd.play(volume, pad=float(self.x-xmin)/(xmax-xmin))
|
||||
|
||||
def setimages(self, gen):
|
||||
if self.imgsetter is not None:
|
||||
try:
|
||||
self.gen.remove(self.imgsetter)
|
||||
except ValueError:
|
||||
pass
|
||||
self.imgsetter = gen
|
||||
if gen is not None:
|
||||
self.gen.append(gen)
|
||||
|
||||
def vertical_warp(self):
|
||||
# short-cut this method to boards.py
|
||||
import boards
|
||||
ActiveSprite.vertical_warp = boards.vertical_warp_sprite
|
||||
self.vertical_warp()
|
||||
## if moebius:
|
||||
## self.moebius()
|
||||
## return moebius
|
||||
## def moebius(self):
|
||||
## pass
|
||||
|
||||
# common generators
|
||||
def cyclic(self, nimages, speed=5):
|
||||
images = [sprget(n) for n in nimages]
|
||||
speed = range(speed)
|
||||
while 1:
|
||||
for img in images:
|
||||
self.seticon(img)
|
||||
for i in speed:
|
||||
yield None
|
||||
|
||||
def imgseq(self, nimages, speed=5, repeat=1):
|
||||
images = [sprget(n) for n in nimages]
|
||||
for r in range(repeat):
|
||||
for img in images:
|
||||
self.seticon(img)
|
||||
for i in range(speed):
|
||||
yield None
|
||||
|
||||
def die(self, nimages, speed=1):
|
||||
for n in nimages:
|
||||
if n is not None:
|
||||
self.seticon(sprget(n))
|
||||
for i in range(speed):
|
||||
yield None
|
||||
self.kill()
|
||||
|
||||
def straightline(self, dx, dy):
|
||||
fx = self.x + 0.5
|
||||
fy = self.y + 0.5
|
||||
while 1:
|
||||
fx += dx
|
||||
fy += dy
|
||||
self.move(int(fx), int(fy))
|
||||
yield None
|
||||
|
||||
def parabolic(self, dxy, warp=0, gravity=0.3):
|
||||
import boards
|
||||
from boards import CELL
|
||||
nx = self.x
|
||||
ny = self.y
|
||||
dx, dy = dxy
|
||||
xmax = boards.bwidth - 2*CELL - self.ico.w
|
||||
while ny < boards.bheight:
|
||||
nx += dx
|
||||
ny += dy
|
||||
dy += gravity
|
||||
if nx < 2*CELL:
|
||||
nx = 2*CELL
|
||||
dx = abs(dx)
|
||||
elif nx >= xmax:
|
||||
nx = xmax
|
||||
dx = -abs(dx)
|
||||
if warp and (ny < -2*CELL or ny >= boards.bheight):
|
||||
nx, ny = boards.vertical_warp(nx, ny)
|
||||
## if moebius:
|
||||
## self.moebius()
|
||||
## dx = -dx
|
||||
self.move(int(nx), int(ny))
|
||||
dxy[:] = [dx, dy]
|
||||
yield None
|
||||
|
||||
def following(self, other, dx=0, dy=0):
|
||||
while other.alive:
|
||||
self.move(other.x + dx, other.y + dy)
|
||||
yield None
|
||||
self.kill()
|
||||
|
||||
def touchdelay(self, delay):
|
||||
for i in range(delay):
|
||||
yield None
|
||||
self.touchable = 1
|
||||
|
||||
def touching(self, margin=0):
|
||||
return touching(self.x, self.y, self.ico.w, self.ico.h, margin)
|
||||
|
||||
def genangry(self):
|
||||
# do one more step throught all generators of self.gen
|
||||
while 1:
|
||||
glist = self.gen[:]
|
||||
try:
|
||||
for g in glist:
|
||||
if self.alive:
|
||||
g.next()
|
||||
except StopIteration:
|
||||
try:
|
||||
self.gen.remove(g)
|
||||
except ValueError:
|
||||
pass
|
||||
for g in glist[glist.index(g)+1:]:
|
||||
if self.alive:
|
||||
try:
|
||||
g.next()
|
||||
except StopIteration:
|
||||
pass
|
||||
yield None
|
||||
|
||||
def touching(x1, y1, w1, h1, margin=0):
|
||||
touch = {}
|
||||
x1 = int(x1)
|
||||
y1 = int(y1)
|
||||
xrange = range(x1>>5, (x1+w1+31)>>5)
|
||||
for y in range(y1>>4, (y1+h1+15)>>4):
|
||||
for x in xrange:
|
||||
touch.update(SpritesByLoc.get((x,y), {}))
|
||||
return [s for s in touch
|
||||
if x1+margin < s.x+s.ico.w and y1+margin < s.y+s.ico.h and
|
||||
s.x+margin < x1+w1 and s.y+margin < y1+h1]
|
||||
|
||||
def action(sprlist, len=len):
|
||||
# Main generator dispatch loop
|
||||
for self in sprlist:
|
||||
glist = self.gen + self.angry
|
||||
try:
|
||||
for g in glist:
|
||||
if self.alive:
|
||||
g.next()
|
||||
except StopIteration:
|
||||
try:
|
||||
self.gen.remove(g)
|
||||
except ValueError:
|
||||
pass
|
||||
for g in glist[glist.index(g)+1:]:
|
||||
if self.alive:
|
||||
try:
|
||||
g.next()
|
||||
except StopIteration:
|
||||
pass
|
||||
if self.touchable and self.alive:
|
||||
# record position
|
||||
x = self.x & -8
|
||||
y = self.y & -8
|
||||
if self.touchable != (x, y):
|
||||
self.touchable = x, y
|
||||
for key in self.ranges:
|
||||
del key[self]
|
||||
del self.ranges[:]
|
||||
xrange = range(x>>5, (x+self.ico.w+38)>>5)
|
||||
for y in range(y>>4, (y+self.ico.h+22)>>4):
|
||||
for x in xrange:
|
||||
key = SpritesByLoc.setdefault((x,y), {})
|
||||
key[self] = 1
|
||||
self.ranges.append(key)
|
||||
|
||||
def sprget(n, spriconcache={}):
|
||||
try:
|
||||
return spriconcache[n]
|
||||
except KeyError:
|
||||
key = n
|
||||
if isinstance(key, tuple) and key[0] in Transformations:
|
||||
t, n = key
|
||||
transform = Transformations[t]
|
||||
else:
|
||||
transform = transform_noflip
|
||||
filename, rect = sprmap[n]
|
||||
bitmap, rect = transform(filename, rect)
|
||||
if isinstance(n, tuple):
|
||||
n1 = n[0]
|
||||
else:
|
||||
n1 = n
|
||||
if isinstance(n1, int):
|
||||
n1 = n1 % 1000
|
||||
alpha = transparency.get(n1, 255)
|
||||
ico = bitmap.geticon(alpha=alpha, *rect)
|
||||
spriconcache[key] = ico
|
||||
return ico
|
||||
|
||||
def transform_noflip(filename, rect):
|
||||
bitmap = gamesrv.getbitmap(filename, KEYCOL)
|
||||
return bitmap, rect
|
||||
|
||||
def make_transform(datamap, ptmap):
|
||||
def transform(filename, rect, datamap=datamap, ptmap=ptmap, cache={}):
|
||||
try:
|
||||
bitmap, width, height = cache[filename]
|
||||
except KeyError:
|
||||
f = open(filename, "rb")
|
||||
data = f.read()
|
||||
f.close()
|
||||
width, height, data = pixmap.decodepixmap(data)
|
||||
data = datamap(width, height, data)
|
||||
dummy, dummy, nwidth, nheight = ptmap(0, 0, width, height)
|
||||
data = pixmap.encodepixmap(nwidth, nheight, data)
|
||||
bitmap = gamesrv.newbitmap(data, KEYCOL)
|
||||
cache[filename] = bitmap, width, height
|
||||
#print 'transformed', filename, 'to', nwidth, nheight
|
||||
x, y, w, h = rect
|
||||
x1, y1, dummy, dummy = ptmap(x, y, width, height)
|
||||
x2, y2, dummy, dummy = ptmap(x+w, y+h, width, height)
|
||||
rect = min(x1,x2), min(y1,y2), abs(x2-x1), abs(y2-y1)
|
||||
#print filename, ':', (x,y,w,h), '->', rect
|
||||
return bitmap, rect
|
||||
return transform
|
||||
|
||||
Transformations = {
|
||||
'': transform_noflip,
|
||||
'vflip': make_transform(pixmap.vflip, lambda x,y,w,h: (x,h-y,w,h)),
|
||||
'hflip': make_transform(pixmap.hflip, lambda x,y,w,h: (w-x,y,w,h)),
|
||||
'cw': make_transform(pixmap.rotate_cw, lambda x,y,w,h: (h-y,x,h,w)),
|
||||
'ccw': make_transform(pixmap.rotate_ccw,lambda x,y,w,h: (y,w-x,h,w)),
|
||||
'rot180': make_transform(pixmap.rotate_180,lambda x,y,w,h: (w-x,h-y,w,h)),
|
||||
}
|
||||
|
||||
if 0: # disabled clipping
|
||||
def sprget_subrect(n, subrect):
|
||||
x, y, w, h = subrect
|
||||
filename, (x0, y0, w0, h0) = sprmap[n]
|
||||
key = (n, 'subrect', subrect)
|
||||
sprmap[key] = filename, (x0+x, y0+y, w, h)
|
||||
return sprget(key)
|
||||
|
||||
def make_darker(ico, is_dragon, bmpcache={}):
|
||||
bmp, rect = ico.getorigin()
|
||||
try:
|
||||
darkbmp = bmpcache[bmp, is_dragon]
|
||||
except KeyError:
|
||||
image = pixmap.decodepixmap(bmp.read())
|
||||
if is_dragon:
|
||||
translation = pixmap.translation_dragon
|
||||
else:
|
||||
translation = pixmap.translation_darker
|
||||
darkimage = pixmap.make_dark(image, translation)
|
||||
data = pixmap.encodepixmap(*darkimage)
|
||||
darkbmp = gamesrv.newbitmap(data, bmp.colorkey)
|
||||
bmpcache[bmp, is_dragon] = darkbmp
|
||||
return darkbmp.geticon(*rect)
|
||||
|
||||
def haspat(n):
|
||||
return n in patmap
|
||||
|
||||
def loadpattern(n, keycol=None):
|
||||
if not haspat(n):
|
||||
n = (n[0] % 100,) + n[1:]
|
||||
filename, rect = patmap[n]
|
||||
filename = os.path.join('tmp', filename)
|
||||
bitmap = gamesrv.getbitmap(filename, keycol)
|
||||
return bitmap, rect
|
||||
|
||||
def makebkgndpattern(bitmap, (x,y,w,h), darker={}):
|
||||
from boards import CELL
|
||||
try:
|
||||
nbitmap, hscale, vscale = darker[bitmap]
|
||||
except KeyError:
|
||||
data = bitmap.read()
|
||||
width, height, data = pixmap.decodepixmap(data)
|
||||
nwidth, nheight, data = pixmap.makebkgnd(width, height, data)
|
||||
hscale = float(nwidth) / width
|
||||
vscale = float(nheight) / height
|
||||
data = pixmap.encodepixmap(nwidth, nheight, data)
|
||||
nbitmap = gamesrv.newbitmap(data, None)
|
||||
darker[bitmap] = nbitmap, hscale, vscale
|
||||
x = int(x*hscale)
|
||||
y = int(y*vscale)
|
||||
w = int(CELL*hscale)
|
||||
h = int(CELL*vscale)
|
||||
return nbitmap, (x,y,w,h)
|
||||
|
||||
def computebiggericon(ico, bigger={}):
|
||||
try:
|
||||
result, computing = bigger[ico]
|
||||
except KeyError:
|
||||
bigger[ico] = None, pixmap.imagezoomer(*ico.getimage())
|
||||
return None
|
||||
if computing is not None:
|
||||
result = computing.next() or computing.next() or computing.next()
|
||||
if not result:
|
||||
return None # still computing
|
||||
w, h, data = result
|
||||
data = pixmap.encodepixmap(w, h, data)
|
||||
result = gamesrv.newbitmap(data, KEYCOL).geticon(0, 0, w, h)
|
||||
bigger[ico] = result, None
|
||||
return result
|
||||
|
||||
def biggericon(ico):
|
||||
result = None
|
||||
while result is None:
|
||||
result = computebiggericon(ico)
|
||||
return result
|
||||
|
||||
extramap = {
|
||||
'shield-left': ('extra1.ppm', (0, 0, 32, 32)),
|
||||
'shield-right': ('extra1.ppm', (0, 32, 32, 32)),
|
||||
'moebius': ('extra1.ppm', (0, 64, 32, 32)),
|
||||
'flower': ('extra1.ppm', (0, 96, 32, 32)),
|
||||
'flower2': ('extra1.ppm', (0, 128, 32, 32)),
|
||||
'potion4': ('extra1.ppm', (0, 160, 32, 32)),
|
||||
('glasses', -1):('extra1.ppm', (0, 192, 32, 16)),
|
||||
('glasses', +1):('extra1.ppm', (0, 208, 32, 16)),
|
||||
'cactus': ('extra1.ppm', (0, 224, 32, 32)),
|
||||
'questionmark3':('extra2.ppm', (0, 0, 16, 16)),
|
||||
'questionmark1':('extra2.ppm', (0, 16, 16, 16)),
|
||||
'questionmark5':('extra2.ppm', (0, 32, 16, 16)),
|
||||
'questionmark2':('extra2.ppm', (0, 48, 16, 16)),
|
||||
'questionmark4':('extra2.ppm', (0, 64, 16, 16)),
|
||||
'percent': ('extra2.ppm', (0, 80, 16, 16)),
|
||||
'colon': ('extra2.ppm', (0, 96, 16, 16)),
|
||||
'gameoverbkgnd':('extra2.ppm', (0, 112, 16, 16)),
|
||||
('eyes', 0,0): ('extra3.ppm', (0, 0, 32, 32)),
|
||||
('eyes', 0,-1): ('extra3.ppm', (0, 32, 32, 32)),
|
||||
('eyes', -1,0): ('extra3.ppm', (0, 64, 32, 32)),
|
||||
('eyes', -1,-1):('extra3.ppm', (0, 96, 32, 32)),
|
||||
('eyes', 1,0): ('extra3.ppm', (0, 128, 32, 32)),
|
||||
('eyes', 1,-1): ('extra3.ppm', (0, 160, 32, 32)),
|
||||
'eyes-blink': ('extra3.ppm', (0, 192, 32, 32)),
|
||||
('smstar','blue' ,0): ('extra4.ppm', ( 0, 0, 16, 16)),
|
||||
('smstar','blue' ,1): ('extra4.ppm', ( 0, 16, 16, 16)),
|
||||
('smstar','yellow' ,0): ('extra4.ppm', ( 0, 32, 16, 16)),
|
||||
('smstar','yellow' ,1): ('extra4.ppm', ( 0, 48, 16, 16)),
|
||||
('smstar','red' ,0): ('extra4.ppm', (16, 0, 16, 16)),
|
||||
('smstar','red' ,1): ('extra4.ppm', (16, 16, 16, 16)),
|
||||
('smstar','green' ,0): ('extra4.ppm', (16, 32, 16, 16)),
|
||||
('smstar','green' ,1): ('extra4.ppm', (16, 48, 16, 16)),
|
||||
('smstar','magenta',0): ('extra4.ppm', (32, 0, 16, 16)),
|
||||
('smstar','magenta',1): ('extra4.ppm', (32, 16, 16, 16)),
|
||||
('smstar','cyan' ,0): ('extra4.ppm', (32, 32, 16, 16)),
|
||||
('smstar','cyan' ,1): ('extra4.ppm', (32, 48, 16, 16)),
|
||||
('starbub','blue' ,0): ('extra5.ppm', (0, 0, 32, 32)),
|
||||
('starbub','blue' ,1): ('extra5.ppm', (0, 32, 32, 32)),
|
||||
('starbub','blue' ,2): ('extra5.ppm', (0, 64, 32, 32)),
|
||||
('starbub','yellow' ,0): ('extra5.ppm', (0, 96, 32, 32)),
|
||||
('starbub','yellow' ,1): ('extra5.ppm', (0,128, 32, 32)),
|
||||
('starbub','yellow' ,2): ('extra5.ppm', (0,160, 32, 32)),
|
||||
('starbub','red' ,0): ('extra5.ppm', (0,192, 32, 32)),
|
||||
('starbub','red' ,1): ('extra5.ppm', (0,224, 32, 32)),
|
||||
('starbub','red' ,2): ('extra5.ppm', (0,256, 32, 32)),
|
||||
('starbub','green' ,0): ('extra5.ppm', (0,288, 32, 32)),
|
||||
('starbub','green' ,1): ('extra5.ppm', (0,320, 32, 32)),
|
||||
('starbub','green' ,2): ('extra5.ppm', (0,352, 32, 32)),
|
||||
('starbub','magenta',0): ('extra5.ppm', (0,384, 32, 32)),
|
||||
('starbub','magenta',1): ('extra5.ppm', (0,416, 32, 32)),
|
||||
('starbub','magenta',2): ('extra5.ppm', (0,448, 32, 32)),
|
||||
('starbub','cyan' ,0): ('extra5.ppm', (0,480, 32, 32)),
|
||||
('starbub','cyan' ,1): ('extra5.ppm', (0,512, 32, 32)),
|
||||
('starbub','cyan' ,2): ('extra5.ppm', (0,544, 32, 32)),
|
||||
'sheep-sm': ('extra6.ppm', (0, 0, 32, 32)),
|
||||
'sheep-big': ('extra6.ppm', (0, 32, 46, 50)),
|
||||
('emotic', 0): ('extra7.ppm', (0, 0, 8, 8)),
|
||||
('emotic', 1): ('extra7.ppm', (0, 8, 8, 8)),
|
||||
('emotic', 2): ('extra7.ppm', (0, 16, 8, 8)),
|
||||
('emotic', 3): ('extra7.ppm', (0, 24, 8, 8)),
|
||||
('emotic', 4): ('extra7.ppm', (0, 32, 8, 8)),
|
||||
('emotic', 5): ('extra7.ppm', (0, 40, 8, 8)),
|
||||
('emotic', 6): ('extra7.ppm', (0, 48, 8, 8)),
|
||||
('butterfly', 'jailed', 0): ('butterfly.ppm', (0, 0, 32, 32)),
|
||||
('butterfly', 'jailed', 1): ('butterfly.ppm', (0, 32, 32, 32)),
|
||||
('butterfly', 'jailed', 2): ('butterfly.ppm', (0, 64, 32, 32)),
|
||||
('butterfly', 'dead', 0): ('butterfly.ppm', (0, 96, 32, 32)),
|
||||
('butterfly', 'dead', 1): ('butterfly.ppm', (0, 128, 32, 32)),
|
||||
('butterfly', 'dead', 2): ('butterfly.ppm', (0, 160, 32, 32)),
|
||||
('butterfly', 'dead', 3): ('butterfly.ppm', (0, 192, 32, 32)),
|
||||
('butterfly', 'fly', 0): ('butterfly.ppm', (0, 224, 32, 32)),
|
||||
('butterfly', 'fly', 1): ('butterfly.ppm', (0, 256, 32, 32)),
|
||||
'glue': ('glue.ppm', (0, 0, 32, 32)),
|
||||
'black': ('black.ppm', (0, 0, 32, 32)),
|
||||
('sheep',-1, 0): ('sheep.ppm', (0, 0, 32, 32)),
|
||||
('sheep',-1, 1): ('sheep.ppm', (0, 32, 32, 32)),
|
||||
('sheep',-1, 2): ('sheep.ppm', (0, 64, 32, 32)),
|
||||
('sheep',-1, 3): ('sheep.ppm', (0, 96, 32, 32)),
|
||||
('sheep', 1, 0): ('sheep.ppm', (0, 128, 32, 32)),
|
||||
('sheep', 1, 1): ('sheep.ppm', (0, 160, 32, 32)),
|
||||
('sheep', 1, 2): ('sheep.ppm', (0, 192, 32, 32)),
|
||||
('sheep', 1, 3): ('sheep.ppm', (0, 224, 32, 32)),
|
||||
('sheep', 'a'): ('sheep.ppm', (2, 263, 7, 8)),
|
||||
('sheep', 'b'): ('sheep.ppm', (11, 262, 6, 10)),
|
||||
('sheep', 'c'): ('sheep.ppm', (17, 264, 11, 8)),
|
||||
('sheep', 'd'): ('sheep.ppm', (18, 272, 11, 7)),
|
||||
('sheep', 'e'): ('sheep.ppm', (18, 279, 11, 8)),
|
||||
('sheep', 'f'): ('sheep.ppm', (4, 273, 10, 12)),
|
||||
('sheep', 'g'): ('sheep.ppm', (19, 257, 11, 8)),
|
||||
}
|
||||
hatmap = {
|
||||
('hat', 0, -1,1):('hat2.ppm',( 0, 0, 32, 48)),
|
||||
('hat', 0, -1,2):('hat2.ppm',( 32, 0, 32, 48)),
|
||||
('hat', 0, -1,3):('hat2.ppm',( 64, 0, 32, 48)),
|
||||
('hat', 0, 1,3):('hat2.ppm',( 96, 0, 32, 48)),
|
||||
('hat', 0, 1,2):('hat2.ppm',(128, 0, 32, 48)),
|
||||
('hat', 0, 1,1):('hat2.ppm',(160, 0, 32, 48)),
|
||||
('hat', 1, -1,1):('hat1.ppm',( 0, 0, 32, 48)),
|
||||
('hat', 1, -1,2):('hat1.ppm',( 32, 0, 32, 48)),
|
||||
('hat', 1, -1,3):('hat1.ppm',( 64, 0, 32, 48)),
|
||||
('hat', 1, 1,3):('hat1.ppm',( 96, 0, 32, 48)),
|
||||
('hat', 1, 1,2):('hat1.ppm',(128, 0, 32, 48)),
|
||||
('hat', 1, 1,1):('hat1.ppm',(160, 0, 32, 48)),
|
||||
('hat', 0) :('hat5.ppm',( 32, 0, 32, 48)),
|
||||
('hat', 1) :('hat5.ppm',( 0, 0, 32, 48)),
|
||||
}
|
||||
|
||||
def generate_sprmap():
|
||||
# check and maybe regenerate the colored image files
|
||||
file = os.path.join('images', 'buildcolors.py')
|
||||
g = {'__name__': '__auto__', '__file__': file}
|
||||
execfile(file, g)
|
||||
# replace the entries 'filename_%d.ppm' by a family of entries,
|
||||
# one for each color
|
||||
sprmap = {}
|
||||
for n, (filename, rect) in (original_sprmap.items() +
|
||||
extramap.items() + hatmap.items()):
|
||||
if filename.find('%d') >= 0:
|
||||
for i in range(MAX):
|
||||
sprmap[n+1000*i] = (os.path.join('images',filename % i), rect)
|
||||
else:
|
||||
sprmap[n] = (os.path.join('images', filename), rect)
|
||||
return sprmap
|
||||
sprmap = generate_sprmap()
|
||||
|
||||
transparency = {
|
||||
mnstrmap.GreenAndBlue.new_bubbles[0][0]: 0xA0,
|
||||
mnstrmap.GreenAndBlue.new_bubbles[0][1]: 0xB0,
|
||||
mnstrmap.GreenAndBlue.new_bubbles[0][2]: 0xC0,
|
||||
mnstrmap.GreenAndBlue.new_bubbles[0][3]: 0xD0,
|
||||
mnstrmap.GreenAndBlue.normal_bubbles[0][0]: 0xE0,
|
||||
mnstrmap.GreenAndBlue.normal_bubbles[0][1]: 0xE0,
|
||||
mnstrmap.GreenAndBlue.normal_bubbles[0][2]: 0xE0,
|
||||
mnstrmap.DyingBubble.first[0]: 0xD0,
|
||||
mnstrmap.DyingBubble.first[1]: 0xD0,
|
||||
mnstrmap.DyingBubble.first[2]: 0xD0,
|
||||
mnstrmap.DyingBubble.medium[0]: 0xC0,
|
||||
mnstrmap.DyingBubble.medium[1]: 0xC0,
|
||||
mnstrmap.DyingBubble.medium[2]: 0xC0,
|
||||
mnstrmap.DyingBubble.last[0]: 0xB0,
|
||||
mnstrmap.DyingBubble.last[1]: 0xB0,
|
||||
mnstrmap.DyingBubble.last[2]: 0xB0,
|
||||
'starbub': 0xE0,
|
||||
}
|
||||
|
||||
def sprcharacterget(c, filename=os.path.join('images', 'extra8.ppm')):
|
||||
n = ord(c) - 32
|
||||
if 0 <= n < 95:
|
||||
return gamesrv.getbitmap(filename, KEYCOL).geticon(n*8, 0, 8, 15)
|
||||
else:
|
||||
return None
|
||||
|
||||
def writestr(x, y, text):
|
||||
result = []
|
||||
for c in text:
|
||||
ico = sprcharacterget(c)
|
||||
if ico is not None:
|
||||
result.append(gamesrv.Sprite(ico, x, y))
|
||||
x += 7
|
||||
return result
|
||||
|
||||
def writestrlines(lines):
|
||||
import boards
|
||||
width = boards.bwidth + 9*boards.CELL
|
||||
y = 50
|
||||
for text in lines:
|
||||
if text:
|
||||
writestr((width - 7*len(text)) // 2, y, text)
|
||||
y += 28
|
||||
else:
|
||||
y += 14
|
||||
|
||||
|
||||
|
||||
def getsample(fn, freq):
|
||||
return gamesrv.getsample(os.path.join('sounds', fn), freq)
|
||||
|
||||
SoundList = ['Pop', 'Jump', 'Die', 'LetsGo', 'Extralife',
|
||||
'Fruit', 'Extra', 'Yippee', 'Hurry', 'Hell', 'Shh']
|
||||
|
||||
class Snd:
|
||||
pass
|
||||
|
||||
def loadsounds(freqfactor=1):
|
||||
for key in SoundList:
|
||||
setattr(Snd, key, getsample(key.lower()+'.wav', freqfactor))
|
||||
|
||||
loadsounds()
|
||||
music_intro = gamesrv.getmusic('music/Snd1-8.wav')
|
||||
music_game = gamesrv.getmusic('music/Snd2-8.wav')
|
||||
music_potion = gamesrv.getmusic('music/Snd3-8.wav')
|
||||
music_modern = gamesrv.getmusic('music/Snd4-8.wav')
|
||||
music_old = gamesrv.getmusic('music/Snd5-8.wav')
|
||||
music_game2 = gamesrv.getmusic('music/Snd6-8.wav')
|
||||
#gamesrv.set_musics([music_intro, music_game], 1)
|
@ -62,7 +62,7 @@ def initpalettelut ():
|
||||
s = "".join ([chr ((v >> shift) & 0xff) for shift in (0,8,16)])
|
||||
PaletteIndex[s] = i
|
||||
# invalidate COLORS, but match the length to the number of alt palettes.
|
||||
COLORS = range ((len (Palettes) / PALETTESIZE) - 1)
|
||||
COLORS = list(range((len (Palettes) / PALETTESIZE) - 1))
|
||||
#print 'COLORS',COLORS
|
||||
COLORMAPS = [{} for n in COLORS]
|
||||
#print 'COLORMAPS',COLORMAPS
|
||||
@ -95,12 +95,12 @@ def inputfiles ():
|
||||
os.path.join (ThisDir, os.pardir, 'ext7', 'image1-%d.ppm'): 1,
|
||||
}
|
||||
d = {}
|
||||
execfile (os.path.join(ThisDir, os.pardir, 'sprmap.py'), d)
|
||||
exec(compile(open(os.path.join(ThisDir, os.pardir, 'sprmap.py'), "rb").read(), os.path.join(ThisDir, os.pardir, 'sprmap.py'), 'exec'), d)
|
||||
sprmap = d['sprmap']
|
||||
for key, (filename, rect) in sprmap.items ():
|
||||
for key, (filename, rect) in list(sprmap.items ()):
|
||||
if filename.find('%d') >= 0:
|
||||
InputFiles[os.path.join (ThisDir, filename)] = 1
|
||||
return InputFiles.keys ()
|
||||
return list(InputFiles.keys ())
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
@ -143,7 +143,7 @@ def ppmbreak (f):
|
||||
if not line.startswith('#'):
|
||||
break
|
||||
wh = line.split ()
|
||||
w, h = map (int, wh)
|
||||
w, h = list(map (int, wh))
|
||||
sig = f.readline ().strip()
|
||||
assert sig == "255"
|
||||
data = f.read ()
|
||||
@ -226,15 +226,15 @@ def writeout (imglist, namepattern, paletted = False):
|
||||
w, h, data = imglist[i]
|
||||
fn = namepattern % i
|
||||
f = open (fn, 'wb')
|
||||
print >> f, 'P6'
|
||||
print >> f, w, h
|
||||
print >> f, 255
|
||||
print('P6', file=f)
|
||||
print(w, h, file=f)
|
||||
print(255, file=f)
|
||||
f.write (data)
|
||||
f.close ()
|
||||
|
||||
|
||||
def convert (name):
|
||||
print >> sys.stderr, 'generating colors for %s...' % name
|
||||
print('generating colors for %s...' % name, file=sys.stderr)
|
||||
imglist = [ppmbreak (open (name % 0, 'rb'))]
|
||||
paletted = False
|
||||
if Palettes:
|
||||
@ -285,7 +285,7 @@ else:
|
||||
|
||||
|
||||
if __name__ == '__auto__': # when execfile'd from images.py
|
||||
rebuild = updatecheck ().items ()
|
||||
rebuild = list(updatecheck ().items ())
|
||||
rebuild.sort ()
|
||||
for fn, r in rebuild:
|
||||
if r:
|
||||
@ -308,15 +308,15 @@ if __name__ == '__main__':
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
print 'rm', filename % n
|
||||
print('rm', filename % n)
|
||||
sys.exit()
|
||||
else:
|
||||
rebuild = updatecheck ()
|
||||
if 0 in rebuild.values ():
|
||||
print >> sys.stderr, ('%d images up-to-date. '
|
||||
if 0 in list(rebuild.values ()):
|
||||
print(('%d images up-to-date. '
|
||||
'Use -f to force a rebuild or -c to clean.' %
|
||||
rebuild.values ().count(0))
|
||||
files = [fn for fn, r in rebuild.items () if r]
|
||||
list(rebuild.values ()).count(0)), file=sys.stderr)
|
||||
files = [fn for fn, r in list(rebuild.items ()) if r]
|
||||
|
||||
files.sort ()
|
||||
for filename in files:
|
||||
|
324
bubbob/images/buildcolors.py.bak
Normal file
324
bubbob/images/buildcolors.py.bak
Normal file
@ -0,0 +1,324 @@
|
||||
#! /usr/bin/env python
|
||||
import sys, os
|
||||
|
||||
if __name__ == '__main__':
|
||||
ThisDir = sys.argv[0]
|
||||
else:
|
||||
ThisDir = __file__
|
||||
ThisDir = os.path.dirname(os.path.abspath(ThisDir))
|
||||
|
||||
### rotate colors
|
||||
import colorsys
|
||||
COLORS = [#(0, 0.0, 1.0, 1, 1), # vert
|
||||
#(1, 0.0, 1.0, 1, 1), # bleu
|
||||
(1, -0.7, 1.0, 1, 1), # rose
|
||||
(0, -0.2, 1.0, 1, 1), # brun
|
||||
(1, 0.72,1.0,-1, 1), # jaune
|
||||
(0, -0.35,0.85,1, 1), # rouge
|
||||
(0, 0, 0.0, 1, 1), # gris
|
||||
(0, -0.85, 0.9, 1, 1), # cyan (was mauve)
|
||||
#(0, 0.2, 1.0, 1, 1), # turquoise
|
||||
(0, 0.925, 0.95,-1, 1), # bleu fonce
|
||||
#(0, 0.45, 0.5, -0.5, 0.75), # hum
|
||||
(1, 'specialpixelmap'), # vert fonce
|
||||
]
|
||||
MAX = 2 + len (COLORS)
|
||||
|
||||
## By ION:
|
||||
#
|
||||
# Here's the new palette-based method.
|
||||
#
|
||||
# It's an array [N][320] of 24bit unsigned integers
|
||||
# (where N is the total number of color sets including the original one.)
|
||||
#
|
||||
# That is, you access it like
|
||||
#
|
||||
# Palettes[(PALETTESIZE * palettenumber)+paletteindex]
|
||||
#
|
||||
# Activate it by passing a palette file as a cmdline argument.
|
||||
#
|
||||
# The color mapping could be further sped up
|
||||
# by making Palettes an array of bytes rather than ints,
|
||||
# at the cost of increased complexity (Palettes [ (PALETTESIZE * 3 * palettenumber) + paletteindex + component])
|
||||
#
|
||||
|
||||
Palettes = None # currently there is no 'internal' palette since this is experimental.
|
||||
|
||||
PALETTESIZE = 960
|
||||
|
||||
PaletteIndex = None
|
||||
# generate the string:paletteindex lookup table
|
||||
def initpalettelut ():
|
||||
global PaletteIndex
|
||||
global COLORS, COLORMAPS
|
||||
# palette 0 is the base palette (green dragon, blue tiger)
|
||||
#
|
||||
# Palette 0 must contain NO duplicate colors.
|
||||
PaletteIndex = {}
|
||||
for i in range (PALETTESIZE):
|
||||
v = Palettes[i]
|
||||
#if v & 0xff == 0 and (v >> 8) & 0xff == 0x87 and (v >> 16) & 0xff == 0:
|
||||
# print 'FOUND'
|
||||
s = "".join ([chr ((v >> shift) & 0xff) for shift in (0,8,16)])
|
||||
PaletteIndex[s] = i
|
||||
# invalidate COLORS, but match the length to the number of alt palettes.
|
||||
COLORS = range ((len (Palettes) / PALETTESIZE) - 1)
|
||||
#print 'COLORS',COLORS
|
||||
COLORMAPS = [{} for n in COLORS]
|
||||
#print 'COLORMAPS',COLORMAPS
|
||||
|
||||
def loadpalettesets (filename):
|
||||
global Palettes
|
||||
#import array
|
||||
#Palettes = array.array ('I')
|
||||
Palettes = []
|
||||
assert ((os.path.getsize (filename) % (PALETTESIZE * 3)) == 0)
|
||||
#print os.path.getsize (filename)
|
||||
f = open (filename, 'rb')
|
||||
for i in range (os.path.getsize(filename) / (PALETTESIZE * 3)):
|
||||
for j in range (PALETTESIZE):
|
||||
tmp = f.read (3)
|
||||
val = ord (tmp[0]) | (ord (tmp[1]) << 8) | (ord (tmp[2]) << 16)
|
||||
Palettes.append (val)
|
||||
#debuggest
|
||||
#print len(Palettes)
|
||||
#print len(Palettes) % PALETTESIZE
|
||||
assert (len (Palettes) % PALETTESIZE) == 0
|
||||
#print "Palettes len:",len (Palettes)
|
||||
|
||||
def inputfiles ():
|
||||
InputFiles = {
|
||||
os.path.join (ThisDir, os.pardir, 'ext1', 'image1-%d.ppm'): 1,
|
||||
os.path.join (ThisDir, os.pardir, 'ext3', 'image1-%d.ppm'): 1,
|
||||
os.path.join (ThisDir, os.pardir, 'ext4', 'image1-%d.ppm'): 1,
|
||||
os.path.join (ThisDir, os.pardir, 'ext6', 'image1-%d.ppm'): 1,
|
||||
os.path.join (ThisDir, os.pardir, 'ext7', 'image1-%d.ppm'): 1,
|
||||
}
|
||||
d = {}
|
||||
execfile (os.path.join(ThisDir, os.pardir, 'sprmap.py'), d)
|
||||
sprmap = d['sprmap']
|
||||
for key, (filename, rect) in sprmap.items ():
|
||||
if filename.find('%d') >= 0:
|
||||
InputFiles[os.path.join (ThisDir, filename)] = 1
|
||||
return InputFiles.keys ()
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
def pixelmap (r, g, b):
|
||||
r /= 255.0
|
||||
g /= 255.0
|
||||
b /= 255.0
|
||||
h, s, v = colorsys.rgb_to_hsv(r, g, b)
|
||||
h = (h*sign + delta) % 1.0
|
||||
s *= sat
|
||||
v *= lumen
|
||||
r, g, b = colorsys.hsv_to_rgb(h, s, v)
|
||||
return r*255.1, g*255.1, b*255.1
|
||||
|
||||
def specialpixelmap (r, g, b):
|
||||
return r * 0.1, g * 0.7, r * 0.5
|
||||
|
||||
usingpalette = 0
|
||||
|
||||
def palettepixelmap (r, g, b):
|
||||
# print max(r,g,b)
|
||||
packed = chr(r) + chr(g) + chr(b)
|
||||
try:
|
||||
index = PaletteIndex[packed]
|
||||
#print 'index %r' % index
|
||||
# print 'USING', usingpalette
|
||||
v = thispalette[index] #Palettes[(PALETTESIZE * (usingpalette + 1)) + index]
|
||||
# print 'hit! %r' % packed
|
||||
# print '-> %r' % (chr(v & 0xff) + chr ((v >> 8) & 0xff) + chr((v >> 16) & 0xff))
|
||||
# print '%r : %r' % (Palettes[index], Palettes[PALETTESIZE + index])
|
||||
return v & 0xff, (v >> 8) & 0xff, (v >> 16) & 0xff
|
||||
except KeyError:
|
||||
return r,g,b
|
||||
|
||||
def ppmbreak (f):
|
||||
sig = f.readline ().strip ()
|
||||
assert sig == "P6"
|
||||
while 1:
|
||||
line = f.readline ().strip ()
|
||||
if not line.startswith('#'):
|
||||
break
|
||||
wh = line.split ()
|
||||
w, h = map (int, wh)
|
||||
sig = f.readline ().strip()
|
||||
assert sig == "255"
|
||||
data = f.read ()
|
||||
return w, h, data
|
||||
|
||||
COLORMAPS = [{} for n in COLORS]
|
||||
del n
|
||||
|
||||
def paletterotate (imglist, chr=chr, int=int, ord=ord):
|
||||
global thispalette
|
||||
gw, gh, green = imglist[0]
|
||||
# assert bw == gw and bh == gh
|
||||
n = 0
|
||||
(_, _, fromimage) = imglist[0]
|
||||
for reserved in COLORS:
|
||||
# is not being entered, the fool.
|
||||
# lut = {}
|
||||
# for
|
||||
thispalette = Palettes[(PALETTESIZE * (reserved + 1)):(PALETTESIZE * (reserved + 2))]
|
||||
# wot is this? _ means unused?
|
||||
# (_, _, otherimage) = imglist[1-n]
|
||||
image = []
|
||||
colormap = COLORMAPS[reserved]
|
||||
append = image.append
|
||||
|
||||
for i in range (0, len(fromimage), 3):
|
||||
rgb1 = fromimage[i:i+3]
|
||||
# rgb2 = otherimage[i:i+3]
|
||||
# if rgb1 == rgb2:
|
||||
# append (rgb1)
|
||||
if rgb1 in colormap:
|
||||
append (colormap[rgb1])
|
||||
else:
|
||||
# print 'HI!'
|
||||
r, g, b = ord(rgb1[0]), ord(rgb1[1]), ord(rgb1[2])
|
||||
# print '%d,%d,%d ->' % (r,g,b)
|
||||
r, g, b = palettepixelmap (r, g, b)
|
||||
# print '%d,%d,%d.' % (r,g,b)
|
||||
newrgb = chr (int (r))+chr (int (g))+chr (int (b))
|
||||
append (newrgb)
|
||||
colormap[rgb1] = newrgb
|
||||
imglist.append((gw, gh, ''.join (image)))
|
||||
|
||||
|
||||
def rotate (imglist, chr=chr, int=int, ord=ord):
|
||||
global delta, sat, sign, lumen
|
||||
(bw, bh, blue), (gw, gh, green) = imglist
|
||||
assert bw == gw and bh == gh
|
||||
for reserved in range (len (COLORS)):
|
||||
if len (COLORS[reserved]) == 2:
|
||||
n, fn = COLORS[reserved]
|
||||
fn = globals ()[fn]
|
||||
else:
|
||||
n, delta, sat, sign, lumen = COLORS[reserved]
|
||||
fn = pixelmap
|
||||
(_, _, fromimage) = imglist[n]
|
||||
(_, _, otherimage) = imglist[1-n]
|
||||
image = []
|
||||
colormap = COLORMAPS[reserved]
|
||||
append = image.append
|
||||
for i in range (0, len(fromimage), 3):
|
||||
rgb1 = fromimage[i:i+3]
|
||||
rgb2 = otherimage[i:i+3]
|
||||
if rgb1 == rgb2:
|
||||
append (rgb1)
|
||||
elif rgb1 in colormap:
|
||||
append (colormap[rgb1])
|
||||
else:
|
||||
r, g, b = fn(ord(rgb1[0]), ord(rgb1[1]), ord(rgb1[2]))
|
||||
newrgb = chr(int(r))+chr(int(g))+chr(int(b))
|
||||
append(newrgb)
|
||||
colormap[rgb1] = newrgb
|
||||
imglist.append((bw, bh, ''.join(image)))
|
||||
|
||||
def writeout (imglist, namepattern, paletted = False):
|
||||
start = 2
|
||||
if paletted:
|
||||
start = 1
|
||||
for i in range (start, len (imglist)):
|
||||
w, h, data = imglist[i]
|
||||
fn = namepattern % i
|
||||
f = open (fn, 'wb')
|
||||
print >> f, 'P6'
|
||||
print >> f, w, h
|
||||
print >> f, 255
|
||||
f.write (data)
|
||||
f.close ()
|
||||
|
||||
|
||||
def convert (name):
|
||||
print >> sys.stderr, 'generating colors for %s...' % name
|
||||
imglist = [ppmbreak (open (name % 0, 'rb'))]
|
||||
paletted = False
|
||||
if Palettes:
|
||||
paletterotate (imglist)
|
||||
paletted = True
|
||||
else:
|
||||
imglist.append(ppmbreak (open (name % 1, 'rb')))
|
||||
rotate (imglist)
|
||||
writeout (imglist, name, paletted)
|
||||
|
||||
def updatecheck ():
|
||||
myself = os.path.join (ThisDir, 'buildcolors.py')
|
||||
|
||||
def older (list1, list2):
|
||||
def mtime (name):
|
||||
try:
|
||||
st = os.stat (name)
|
||||
except OSError:
|
||||
return None
|
||||
else:
|
||||
return st.st_mtime
|
||||
list2 = [mtime (name) for name in list2]
|
||||
if None in list2:
|
||||
return 0
|
||||
else:
|
||||
list1 = [mtime(name) for name in list1]
|
||||
list1 = [t for t in list1 if t is not None]
|
||||
return list1 and list2 and max (list1) < min (list2)
|
||||
|
||||
rebuild = {}
|
||||
for filename in inputfiles ():
|
||||
distfiles = [myself, filename % 0]
|
||||
genfiles = [filename % n for n in range (1, MAX)]
|
||||
rebuild[filename] = not older (distfiles, genfiles)
|
||||
return rebuild
|
||||
|
||||
|
||||
#try to load palettes first
|
||||
tmp = os.path.join (ThisDir, os.pardir, 'images', 'palettes.dat')
|
||||
if os.path.exists (tmp):
|
||||
#print 'loading palettes'
|
||||
loadpalettesets (tmp)
|
||||
initpalettelut ()
|
||||
else:
|
||||
# from now on we should always use the palette approach;
|
||||
# comment out the following line to restore the old color-rotation code.
|
||||
raise IOError("cannot find the palette file %r" % (tmp,))
|
||||
|
||||
|
||||
if __name__ == '__auto__': # when execfile'd from images.py
|
||||
rebuild = updatecheck ().items ()
|
||||
rebuild.sort ()
|
||||
for fn, r in rebuild:
|
||||
if r:
|
||||
convert(fn)
|
||||
|
||||
#try:
|
||||
# import psyco
|
||||
# psyco.bind(rotate)
|
||||
#except:
|
||||
# pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[1:2] == ['-f']:
|
||||
files = inputfiles ()
|
||||
elif sys.argv[1:2] == ['-c']:
|
||||
for filename in inputfiles ():
|
||||
for n in range (1, MAX):
|
||||
try:
|
||||
os.unlink (filename % n)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
print 'rm', filename % n
|
||||
sys.exit()
|
||||
else:
|
||||
rebuild = updatecheck ()
|
||||
if 0 in rebuild.values ():
|
||||
print >> sys.stderr, ('%d images up-to-date. '
|
||||
'Use -f to force a rebuild or -c to clean.' %
|
||||
rebuild.values ().count(0))
|
||||
files = [fn for fn, r in rebuild.items () if r]
|
||||
|
||||
files.sort ()
|
||||
for filename in files:
|
||||
convert (filename)
|
||||
|
@ -3,7 +3,7 @@
|
||||
# a bit more related to each other instead of being completely independent.
|
||||
#
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
import sys, random, math
|
||||
from random import uniform, choice, randrange
|
||||
|
||||
@ -50,7 +50,7 @@ MnstrCategory = {
|
||||
"Orcy": 0,
|
||||
"Gramy": 0,
|
||||
"Blitzy": 2}
|
||||
MnstrNames = MnstrCategory.keys()
|
||||
MnstrNames = list(MnstrCategory.keys())
|
||||
Bonuses = ['letter', 'fire', 'lightning', 'water', 'top']
|
||||
|
||||
def mnstrclslist(name):
|
||||
@ -61,7 +61,7 @@ def mnstrclslist(name):
|
||||
|
||||
class Shape:
|
||||
basemnstr = ChoiceParameter('basemnstr', MnstrNames)
|
||||
extramnstr = ChoiceParameter('extramnstr', range(4))
|
||||
extramnstr = ChoiceParameter('extramnstr', list(range(4)))
|
||||
samemnstr = BoolParameter('samemnstr')
|
||||
baseshape = ChoiceParameter('baseshape', ' ODBGMPRWZS')
|
||||
rooms = BoolParameter('rooms')
|
||||
@ -72,15 +72,15 @@ class Shape:
|
||||
platfull = BoolParameter('platfull')
|
||||
mess = ChoiceParameter('mess', ' ....!')
|
||||
closed = BoolParameter('closed', 0.95)
|
||||
bonuses = ChoiceParameter('bonuses', xrange(3**len(Bonuses)))
|
||||
smooth = ChoiceParameter('smooth', range(4))
|
||||
bonuses = ChoiceParameter('bonuses', range(3**len(Bonuses)))
|
||||
smooth = ChoiceParameter('smooth', list(range(4)))
|
||||
startplats = BoolParameter('startplats', 0.98)
|
||||
makespace = BoolParameter('makespace', 0.8)
|
||||
straightfall = BoolParameter('straightfall', 0.8)
|
||||
mirrored = BoolParameter('mirrored', 0.4)
|
||||
enlargeholes = BoolParameter('enlargeholes', 0.9)
|
||||
|
||||
all_parameters = [name for name in locals().keys()
|
||||
all_parameters = [name for name in list(locals().keys())
|
||||
if not name.startswith('_')]
|
||||
|
||||
def __init__(self, shape=None):
|
||||
@ -141,7 +141,7 @@ class Shape:
|
||||
if self.mess == '!':
|
||||
self.holes = 1
|
||||
|
||||
all_tests = [value for (name, value) in locals().items()
|
||||
all_tests = [value for (name, value) in list(locals().items())
|
||||
if name.startswith('test_')]
|
||||
|
||||
def accept(self, lvl):
|
||||
@ -327,7 +327,7 @@ def GenerateLevels():
|
||||
HEIGHT = 23
|
||||
def enter(self, *args, **kw):
|
||||
result = RandomLevel.enter(self, *args, **kw)
|
||||
params = self.autogen_shape.__dict__.items()
|
||||
params = list(self.autogen_shape.__dict__.items())
|
||||
params.sort()
|
||||
# for keyvalue in params:
|
||||
# print '%20s: %s' % keyvalue
|
||||
@ -355,8 +355,8 @@ def GenerateSingleLevel(width, height):
|
||||
|
||||
if __name__ == '__main__':
|
||||
for s in makeshapes():
|
||||
print s.__dict__
|
||||
print(s.__dict__)
|
||||
else:
|
||||
rnglevel = {}
|
||||
execfile('levels/rnglevel', rnglevel)
|
||||
exec(compile(open('levels/rnglevel', "rb").read(), 'levels/rnglevel', 'exec'), rnglevel)
|
||||
RandomLevel = rnglevel['RandomLevel']
|
||||
|
362
bubbob/levels/RandomLevels.py.bak
Normal file
362
bubbob/levels/RandomLevels.py.bak
Normal file
@ -0,0 +1,362 @@
|
||||
#
|
||||
# Second try at automatically generating levels that are
|
||||
# a bit more related to each other instead of being completely independent.
|
||||
#
|
||||
|
||||
from __future__ import generators
|
||||
import sys, random, math
|
||||
from random import uniform, choice, randrange
|
||||
|
||||
|
||||
class Parameter(object):
|
||||
def __init__(self, name, rng):
|
||||
self.name = name
|
||||
self.rng = rng
|
||||
def __get__(self, instance, cls):
|
||||
assert self.name not in instance.__dict__
|
||||
value = self.rng()
|
||||
setattr(instance, self.name, value)
|
||||
return value
|
||||
|
||||
class ChoiceParameter(Parameter):
|
||||
def __init__(self, name, list):
|
||||
Parameter.__init__(self, name, lambda : choice(list))
|
||||
|
||||
class BoolParameter(Parameter):
|
||||
def __init__(self, name, prob=0.5):
|
||||
Parameter.__init__(self, name, lambda : random.random() < prob)
|
||||
|
||||
def flat(mean,var):
|
||||
return randrange(mean-var,mean+var+1)
|
||||
|
||||
def dice(n,sides,orig=1):
|
||||
result = 0
|
||||
for i in range(n):
|
||||
result += orig+randrange(sides)
|
||||
return result
|
||||
|
||||
def fork(choice1, prob, choice2):
|
||||
if random.random() < prob:
|
||||
return choice1()
|
||||
else:
|
||||
return choice2()
|
||||
|
||||
MnstrCategory = {
|
||||
"Nasty": 0,
|
||||
"Monky": 0,
|
||||
"Ghosty": 1,
|
||||
"Flappy": 1,
|
||||
"Springy": 2,
|
||||
"Orcy": 0,
|
||||
"Gramy": 0,
|
||||
"Blitzy": 2}
|
||||
MnstrNames = MnstrCategory.keys()
|
||||
Bonuses = ['letter', 'fire', 'lightning', 'water', 'top']
|
||||
|
||||
def mnstrclslist(name):
|
||||
import boarddef
|
||||
classname1 = 'L' + name
|
||||
classname2 = 'R' + name
|
||||
return [getattr(boarddef, classname1), getattr(boarddef, classname2)]
|
||||
|
||||
class Shape:
|
||||
basemnstr = ChoiceParameter('basemnstr', MnstrNames)
|
||||
extramnstr = ChoiceParameter('extramnstr', range(4))
|
||||
samemnstr = BoolParameter('samemnstr')
|
||||
baseshape = ChoiceParameter('baseshape', ' ODBGMPRWZS')
|
||||
rooms = BoolParameter('rooms')
|
||||
holes = BoolParameter('holes')
|
||||
lines = ChoiceParameter('lines', ' -/|')
|
||||
platforms = BoolParameter('platforms')
|
||||
platholes = BoolParameter('platholes')
|
||||
platfull = BoolParameter('platfull')
|
||||
mess = ChoiceParameter('mess', ' ....!')
|
||||
closed = BoolParameter('closed', 0.95)
|
||||
bonuses = ChoiceParameter('bonuses', xrange(3**len(Bonuses)))
|
||||
smooth = ChoiceParameter('smooth', range(4))
|
||||
startplats = BoolParameter('startplats', 0.98)
|
||||
makespace = BoolParameter('makespace', 0.8)
|
||||
straightfall = BoolParameter('straightfall', 0.8)
|
||||
mirrored = BoolParameter('mirrored', 0.4)
|
||||
enlargeholes = BoolParameter('enlargeholes', 0.9)
|
||||
|
||||
all_parameters = [name for name in locals().keys()
|
||||
if not name.startswith('_')]
|
||||
|
||||
def __init__(self, shape=None):
|
||||
if shape:
|
||||
self.__dict__.update(shape.__dict__)
|
||||
self.modified = 0
|
||||
|
||||
def set_gens(self, rooms=0, platforms=0, holes=0, smooth=0, mess=' ', lines=' '):
|
||||
self.rooms = rooms
|
||||
self.platforms = platforms
|
||||
self.holes = holes
|
||||
self.smooth = smooth
|
||||
self.mess = mess
|
||||
self.lines = lines
|
||||
|
||||
def reset(self, attrname=None):
|
||||
if attrname:
|
||||
try:
|
||||
del self.__dict__[attrname]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.__dict__.clear()
|
||||
self.modified = 1
|
||||
|
||||
def __eq__(self, other):
|
||||
return (self.__class__ is other.__class__ and
|
||||
self.__dict__ == other.__dict__)
|
||||
|
||||
def test_similar_parameters(self, prevlist):
|
||||
similarity = 0
|
||||
rprevlist = prevlist[:]
|
||||
rprevlist.reverse()
|
||||
for param in Shape.all_parameters:
|
||||
accum = 0
|
||||
for prev in rprevlist:
|
||||
if getattr(self, param) != getattr(prev, param):
|
||||
break
|
||||
else:
|
||||
accum += 1
|
||||
similarity += accum
|
||||
minimum = min(4*len(prevlist), 7)
|
||||
if not (minimum <= similarity <= 17):
|
||||
self.reset()
|
||||
|
||||
def test_not_too_often(self, prevlist):
|
||||
for param, bad_value, delay in [
|
||||
('mess', '.', 2),
|
||||
('mess', '!', 11),
|
||||
('holes', 1, 1),
|
||||
]:
|
||||
if getattr(self, param) == bad_value:
|
||||
for prev in prevlist[-delay:]:
|
||||
if getattr(prev, param) == bad_value:
|
||||
self.reset(param)
|
||||
|
||||
def test_mess_hole(self, prevlist):
|
||||
if self.mess == '!':
|
||||
self.holes = 1
|
||||
|
||||
all_tests = [value for (name, value) in locals().items()
|
||||
if name.startswith('test_')]
|
||||
|
||||
def accept(self, lvl):
|
||||
f = lambda d=self.difficulty : randrange(3, 4+int(9*d))
|
||||
lvl.mlist = [(mnstrclslist(self.basemnstr), f)]
|
||||
repeat = choice([2,2,3]) - self.extramnstr
|
||||
if repeat > 1:
|
||||
lvl.mlist *= repeat
|
||||
if self.extramnstr:
|
||||
othermnstr = [name for name in MnstrNames if name!=self.basemnstr]
|
||||
if self.samemnstr:
|
||||
othermnstr = [name for name in othermnstr
|
||||
if MnstrCategory[name]==MnstrCategory[self.basemnstr]]
|
||||
random.shuffle(othermnstr)
|
||||
for name in othermnstr[:self.extramnstr]:
|
||||
lvl.mlist.append((mnstrclslist(name), f))
|
||||
|
||||
lvl.genwalls = []
|
||||
|
||||
if self.baseshape == 'G':
|
||||
lvl.genwalls.append((RandomLevel.grids,
|
||||
uniform(0.7,0.8),
|
||||
uniform(0.7,0.8)))
|
||||
self.set_gens()
|
||||
if self.baseshape == 'P':
|
||||
lvl.genwalls.append((RandomLevel.pegs,
|
||||
uniform(0.1,0.2),
|
||||
uniform(0.45,0.7),
|
||||
choice([0,1,1,1])))
|
||||
self.set_gens(smooth=3)
|
||||
self.closed = random.random() < 0.80
|
||||
if self.baseshape == 'B':
|
||||
nr = choice([0,0,1])
|
||||
lvl.genwalls.append((RandomLevel.bouncers,
|
||||
dice(1, 100) + 250 - nr*200, # length
|
||||
uniform(0.7, 1.7),
|
||||
nr))
|
||||
self.set_gens(smooth=3)
|
||||
if self.baseshape == 'W':
|
||||
nr = dice(1, 3) + 2
|
||||
lvl.genwalls.append((RandomLevel.walkers,
|
||||
dice(2, 100) + 100, # length
|
||||
nr, nr + dice(2, 3),
|
||||
choice([0,1])))
|
||||
self.set_gens()
|
||||
if self.baseshape == 'R':
|
||||
lvl.genwalls.append((RandomLevel.rivers,
|
||||
randrange(3,(lvl.WIDTH-4)/4), # the number of rivers
|
||||
uniform(0.3, 1.4), # the side stepping threshold
|
||||
10)) # the max side stepping size
|
||||
self.set_gens()
|
||||
if self.baseshape == 'Z':
|
||||
lvl.genwalls.append((RandomLevel.zigzag,))
|
||||
self.set_gens()
|
||||
if self.baseshape == 'M':
|
||||
lvl.genwalls.append((RandomLevel.mondrian,))
|
||||
self.set_gens()
|
||||
if self.baseshape == 'O':
|
||||
lvl.genwalls.append((RandomLevel.remove_joined_blocks,))
|
||||
self.set_gens()
|
||||
if self.baseshape == 'S':
|
||||
lvl.genwalls.append((RandomLevel.platforms_reg,))
|
||||
self.set_gens()
|
||||
self.makespace = random.random() < 0.1
|
||||
if self.closed:
|
||||
self.startplats = 0
|
||||
if self.baseshape == 'D':
|
||||
lvl.genwalls.append((RandomLevel.discrete_blocks,))
|
||||
self.set_gens()
|
||||
self.makespace = random.random() < 0.1
|
||||
if self.closed:
|
||||
self.startplats = 0
|
||||
|
||||
if self.rooms:
|
||||
nr = dice(2, 6)
|
||||
lvl.genwalls.append((RandomLevel.rooms,
|
||||
lambda : flat(9-nr,2), # the half size of the room
|
||||
lambda : uniform(0.8,1.2), # the excentricity of the room
|
||||
nr)) # the number of rooms
|
||||
if self.lines != ' ':
|
||||
rng_angle = {
|
||||
'-': lambda : 0,
|
||||
'/': None, # default
|
||||
'|': lambda : math.pi/2,
|
||||
}
|
||||
lvl.genwalls.append((RandomLevel.lines,
|
||||
lambda : dice(8,3), # line length
|
||||
dice(2,4), # number of lines
|
||||
rng_angle[self.lines]))
|
||||
if self.platforms:
|
||||
nplat = dice(2,4,0)
|
||||
if nplat: space = flat((lvl.HEIGHT-1)/nplat/2,(lvl.HEIGHT-1)/nplat/2-1)
|
||||
else: space = 1
|
||||
if self.platholes:
|
||||
nholes = lambda : dice(1,3)
|
||||
else:
|
||||
nholes = lambda : 0
|
||||
wholes = lambda : dice(2,3)
|
||||
full = self.platfull
|
||||
lvl.genwalls.append((RandomLevel.platforms,
|
||||
(nplat,space), # number of platform and spacing
|
||||
(nholes,wholes), # number of holes and width
|
||||
full)) # full width platform
|
||||
if self.mess != ' ':
|
||||
threshold = {
|
||||
'.': 0.02 + 0.08*random.random(), # normal
|
||||
'!': 0.25 + 0.2 *random.random(), # super-filled
|
||||
}
|
||||
lvl.genwalls.append((RandomLevel.mess, threshold[self.mess]))
|
||||
if self.holes:
|
||||
nh = choice([1,1,2,2,2,3,3,3,4,5])
|
||||
lvl.genwalls.append((RandomLevel.holes,
|
||||
lambda : flat(9-nh,2), # radius of the holes
|
||||
lambda : uniform(0.9,1.1), # excentricity
|
||||
nh, # number of holes
|
||||
lambda : choice([0,0,0,1]))) # circle or rectangle
|
||||
if self.closed:
|
||||
lvl.genwalls.append((RandomLevel.close,))
|
||||
if self.smooth > 0:
|
||||
# smooth away all lone empty spaces
|
||||
lvl.genwalls.append((RandomLevel.smooth, 1.0, 1))
|
||||
# possibly smooth away some lone bricks
|
||||
if self.smooth == 2:
|
||||
lvl.genwalls.append((RandomLevel.smooth, 0.25, 0))
|
||||
elif self.smooth == 3:
|
||||
lvl.genwalls.append((RandomLevel.smooth, 0.75, 0))
|
||||
if self.startplats:
|
||||
lvl.genwalls.append((RandomLevel.startplatform, ))
|
||||
lvl.genwalls.append((RandomLevel.openstartway, ))
|
||||
|
||||
if self.makespace:
|
||||
lvl.genwalls.append((RandomLevel.make_space, ))
|
||||
|
||||
if self.straightfall:
|
||||
lvl.genwalls.append((RandomLevel.prevent_straight_fall, ))
|
||||
|
||||
if self.mirrored:
|
||||
lvl.genwalls.append((RandomLevel.mirror, ))
|
||||
|
||||
if self.enlargeholes:
|
||||
lvl.genwalls.append((RandomLevel.enlarge_tiny_holes, ))
|
||||
|
||||
lvl.genwalls.append((RandomLevel.generate_wind, ))
|
||||
b = self.bonuses
|
||||
for name in Bonuses:
|
||||
setattr(lvl, name, (b % 3) == 1)
|
||||
b = b // 3
|
||||
lvl.autogen_shape = self
|
||||
|
||||
|
||||
def generate_shape(prevlist):
|
||||
tests = Shape.all_tests
|
||||
s = Shape()
|
||||
for i in range(100):
|
||||
s1 = Shape(s)
|
||||
random.shuffle(tests)
|
||||
for test in tests:
|
||||
test(s1, prevlist)
|
||||
if not s1.modified and s1 == s:
|
||||
break
|
||||
s = s1
|
||||
# else:
|
||||
# sys.stdout.write('*')
|
||||
del s.modified
|
||||
return s
|
||||
|
||||
def makeshapes(nblevels=25):
|
||||
shapelist = []
|
||||
for i in range(nblevels):
|
||||
s = generate_shape(shapelist)
|
||||
s.difficulty = float(i+1)/nblevels
|
||||
yield s
|
||||
shapelist.append(s)
|
||||
if len(shapelist) == 10:
|
||||
del shapelist[:]
|
||||
|
||||
def GenerateLevels():
|
||||
# print 'generating levels',
|
||||
Levels = []
|
||||
for s in makeshapes():
|
||||
class level(RandomLevel):
|
||||
WIDTH = 28
|
||||
HEIGHT = 23
|
||||
def enter(self, *args, **kw):
|
||||
result = RandomLevel.enter(self, *args, **kw)
|
||||
params = self.autogen_shape.__dict__.items()
|
||||
params.sort()
|
||||
# for keyvalue in params:
|
||||
# print '%20s: %s' % keyvalue
|
||||
return result
|
||||
s.accept(level)
|
||||
Levels.append(level)
|
||||
# sys.stdout.write('.')
|
||||
# sys.stdout.flush()
|
||||
# print
|
||||
class levelfinal(RandomLevel):
|
||||
WIDTH = level.WIDTH
|
||||
HEIGHT = level.HEIGHT
|
||||
genwalls = [(RandomLevel.platforms,(5,3),(lambda:flat(2,1),lambda:flat(6,2)),1),
|
||||
(RandomLevel.close,)]
|
||||
Levels.append(levelfinal)
|
||||
return Levels
|
||||
|
||||
def GenerateSingleLevel(width, height):
|
||||
[s] = makeshapes(1)
|
||||
class level(RandomLevel):
|
||||
WIDTH = width
|
||||
HEIGHT = height
|
||||
s.accept(level)
|
||||
return level
|
||||
|
||||
if __name__ == '__main__':
|
||||
for s in makeshapes():
|
||||
print s.__dict__
|
||||
else:
|
||||
rnglevel = {}
|
||||
execfile('levels/rnglevel', rnglevel)
|
||||
RandomLevel = rnglevel['RandomLevel']
|
@ -43,16 +43,16 @@ class TypeList:
|
||||
return self.resources()[id]
|
||||
|
||||
def keys(self):
|
||||
return self.resources().keys()
|
||||
return list(self.resources().keys())
|
||||
|
||||
def values(self):
|
||||
return self.resources().values()
|
||||
return list(self.resources().values())
|
||||
|
||||
def items(self):
|
||||
return self.resources().items()
|
||||
return list(self.resources().items())
|
||||
|
||||
def namedict(self):
|
||||
return dict([(r.name, r) for r in self.resources().values() if r.name is not None])
|
||||
return dict([(r.name, r) for r in list(self.resources().values()) if r.name is not None])
|
||||
|
||||
|
||||
class MacBinary:
|
||||
@ -93,22 +93,22 @@ class MacBinary:
|
||||
return self.dtypes
|
||||
|
||||
def keys(self):
|
||||
return self.dtypes.keys()
|
||||
return list(self.dtypes.keys())
|
||||
|
||||
def values(self):
|
||||
return self.dtypes.values()
|
||||
return list(self.dtypes.values())
|
||||
|
||||
def items(self):
|
||||
return self.dtypes.items()
|
||||
return list(self.dtypes.items())
|
||||
|
||||
|
||||
class Subfile:
|
||||
def __init__(self, f, start, length):
|
||||
if start < 0:
|
||||
raise ValueError, 'negative position'
|
||||
raise ValueError('negative position')
|
||||
if isinstance(f, Subfile):
|
||||
if start + length > f.length:
|
||||
raise ValueError, 'subfile out of bounds'
|
||||
raise ValueError('subfile out of bounds')
|
||||
f, start = f.f, f.start+start
|
||||
self.f = f
|
||||
self.start = start
|
||||
@ -124,7 +124,7 @@ class Subfile:
|
||||
return self.f.read(size)
|
||||
def seek(self, npos):
|
||||
if npos < 0:
|
||||
raise ValueError, 'negative position'
|
||||
raise ValueError('negative position')
|
||||
self.position = npos
|
||||
|
||||
|
||||
@ -186,7 +186,7 @@ class ppatResource(Resource):
|
||||
f = self.subfile()
|
||||
pattype, patmap, patdata = struct.unpack(">Hll", f.read(10))
|
||||
if pattype != 1:
|
||||
raise ValueError, 'Pattern type not supported'
|
||||
raise ValueError('Pattern type not supported')
|
||||
f.seek(patmap)
|
||||
(rowBytes, h, w, packType, packSize,
|
||||
pixelType, pixelSize, cmpCount, cmpSize, pmTable) = (
|
||||
@ -194,9 +194,9 @@ class ppatResource(Resource):
|
||||
isBitmap = (rowBytes & 0x8000) != 0
|
||||
rowBytes &= 0x3FFF
|
||||
if packType != 0:
|
||||
raise ValueError, 'packed image not supported'
|
||||
raise ValueError('packed image not supported')
|
||||
if pixelType != 0 or cmpCount != 1:
|
||||
raise ValueError, 'direct RGB image not supported'
|
||||
raise ValueError('direct RGB image not supported')
|
||||
assert cmpSize == pixelSize and pixelSize in [1,2,4,8]
|
||||
f.seek(pmTable)
|
||||
colormap = loadcolormap(f)
|
||||
|
260
bubbob/macbinary.py.bak
Normal file
260
bubbob/macbinary.py.bak
Normal file
@ -0,0 +1,260 @@
|
||||
import struct
|
||||
|
||||
|
||||
def padto(n, m):
|
||||
return (n+m-1) & ~(m-1)
|
||||
|
||||
def resourceclass(rtype):
|
||||
return globals().get(rtype.strip() + 'Resource', Resource)
|
||||
|
||||
|
||||
class TypeList:
|
||||
|
||||
def __init__(self, type, fmap, fdata, namebase, start, count):
|
||||
self.type = type
|
||||
self.fmap = fmap
|
||||
self.fdata = fdata
|
||||
self.namebase = namebase
|
||||
self.start = start
|
||||
self.count = count
|
||||
self.ids = None
|
||||
|
||||
def resources(self):
|
||||
if self.ids is None:
|
||||
ResourceCls = resourceclass(self.type)
|
||||
d = {}
|
||||
self.fmap.seek(self.start)
|
||||
for resid, resname, resattr, resofshi, resofslo in [
|
||||
struct.unpack(">HHBBHxxxx", self.fmap.read(12))
|
||||
for i in range(self.count)]:
|
||||
if resname == 0xffff:
|
||||
name = None
|
||||
else:
|
||||
self.fmap.seek(self.namebase + resname)
|
||||
namelen, = struct.unpack(">B", self.fmap.read(1))
|
||||
name = self.fmap.read(namelen)
|
||||
assert resid not in d
|
||||
d[resid] = ResourceCls(self.type, resid, name, resattr,
|
||||
self.fdata, resofslo + (resofshi<<16))
|
||||
self.ids = d
|
||||
return self.ids
|
||||
|
||||
def __getitem__(self, id):
|
||||
return self.resources()[id]
|
||||
|
||||
def keys(self):
|
||||
return self.resources().keys()
|
||||
|
||||
def values(self):
|
||||
return self.resources().values()
|
||||
|
||||
def items(self):
|
||||
return self.resources().items()
|
||||
|
||||
def namedict(self):
|
||||
return dict([(r.name, r) for r in self.resources().values() if r.name is not None])
|
||||
|
||||
|
||||
class MacBinary:
|
||||
|
||||
def __init__(self, f):
|
||||
if type(f) is type(''):
|
||||
f = open(f, 'rb')
|
||||
self.f = f
|
||||
self.f.seek(0x53)
|
||||
self.dataforksize, self.resforksize = struct.unpack(">ll", self.f.read(8))
|
||||
self.loadresources()
|
||||
|
||||
def getdata(self):
|
||||
self.f.seek(0x80)
|
||||
return self.f.read(self.dataforksize)
|
||||
|
||||
def loadresources(self):
|
||||
f = Subfile(self.f, padto(0x80 + self.dataforksize, 0x80), self.resforksize)
|
||||
ofsdata, ofsmap, lendata, lenmap = struct.unpack(">llll", f.read(16))
|
||||
fdata = Subfile(f, ofsdata, lendata)
|
||||
fmap = Subfile(f, ofsmap, lenmap)
|
||||
fmap.seek(24)
|
||||
ofstype, ofsname = struct.unpack(">HH", fmap.read(4))
|
||||
self.dtypes = {}
|
||||
fmap.seek(ofstype)
|
||||
numtypes, = struct.unpack(">H", fmap.read(2))
|
||||
numtypes = numtypes + 1
|
||||
for rtype, num, ofsref in [struct.unpack(">4sHH", fmap.read(8))
|
||||
for i in range(numtypes)]:
|
||||
assert rtype not in self.dtypes
|
||||
self.dtypes[rtype] = TypeList(rtype, fmap, fdata, ofsname,
|
||||
ofstype + ofsref, num + 1)
|
||||
|
||||
def __getitem__(self, rtype):
|
||||
return self.dtypes[rtype]
|
||||
|
||||
def types(self):
|
||||
return self.dtypes
|
||||
|
||||
def keys(self):
|
||||
return self.dtypes.keys()
|
||||
|
||||
def values(self):
|
||||
return self.dtypes.values()
|
||||
|
||||
def items(self):
|
||||
return self.dtypes.items()
|
||||
|
||||
|
||||
class Subfile:
|
||||
def __init__(self, f, start, length):
|
||||
if start < 0:
|
||||
raise ValueError, 'negative position'
|
||||
if isinstance(f, Subfile):
|
||||
if start + length > f.length:
|
||||
raise ValueError, 'subfile out of bounds'
|
||||
f, start = f.f, f.start+start
|
||||
self.f = f
|
||||
self.start = start
|
||||
self.length = length
|
||||
self.position = 0
|
||||
def read(self, size=None):
|
||||
if size is None or self.position + size > self.length:
|
||||
size = self.length - self.position
|
||||
if size <= 0:
|
||||
return ''
|
||||
self.f.seek(self.start + self.position)
|
||||
self.position = self.position + size
|
||||
return self.f.read(size)
|
||||
def seek(self, npos):
|
||||
if npos < 0:
|
||||
raise ValueError, 'negative position'
|
||||
self.position = npos
|
||||
|
||||
|
||||
class Resource:
|
||||
|
||||
def __init__(self, type, id, name, attr, srcfile, srcofs):
|
||||
self.type = type
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.attr = attr
|
||||
self.srcfile = srcfile
|
||||
self.srcofs = srcofs
|
||||
|
||||
def subfile(self):
|
||||
self.srcfile.seek(self.srcofs)
|
||||
length, = struct.unpack(">l", self.srcfile.read(4))
|
||||
return Subfile(self.srcfile, self.srcofs + 4, length)
|
||||
|
||||
def load(self):
|
||||
return self.subfile().read()
|
||||
|
||||
|
||||
class RGBImage:
|
||||
def __init__(self, w, h, data):
|
||||
assert len(data) == 3*w*h
|
||||
self.w = w
|
||||
self.h = h
|
||||
self.data = data
|
||||
|
||||
|
||||
def loadcolormap(f):
|
||||
size, = struct.unpack(">xxxxxxH", f.read(8))
|
||||
size = size + 1
|
||||
d = {}
|
||||
for index, r, g, b in [struct.unpack(">HHHH", f.read(8)) for i in range(size)]:
|
||||
assert index not in d, 'duplicate color index'
|
||||
d[index] = r/256.0, g/256.0, b/256.0
|
||||
return d
|
||||
|
||||
def image2rgb(image):
|
||||
# returns (w, h, data)
|
||||
h = len(image)
|
||||
result1 = []
|
||||
for line in image:
|
||||
for r, g, b in line:
|
||||
result1.append(chr(int(r)) + chr(int(g)) + chr(int(b)))
|
||||
return len(image[0]), len(image), ''.join(result1)
|
||||
|
||||
|
||||
class clutResource(Resource):
|
||||
# a color table
|
||||
def gettable(self):
|
||||
return loadcolormap(self.subfile())
|
||||
|
||||
|
||||
class ppatResource(Resource):
|
||||
# a pattern
|
||||
def getimage(self):
|
||||
f = self.subfile()
|
||||
pattype, patmap, patdata = struct.unpack(">Hll", f.read(10))
|
||||
if pattype != 1:
|
||||
raise ValueError, 'Pattern type not supported'
|
||||
f.seek(patmap)
|
||||
(rowBytes, h, w, packType, packSize,
|
||||
pixelType, pixelSize, cmpCount, cmpSize, pmTable) = (
|
||||
struct.unpack(">xxxxHxxxxHHxxHlxxxxxxxxHHHHxxxxlxxxx", f.read(50)))
|
||||
isBitmap = (rowBytes & 0x8000) != 0
|
||||
rowBytes &= 0x3FFF
|
||||
if packType != 0:
|
||||
raise ValueError, 'packed image not supported'
|
||||
if pixelType != 0 or cmpCount != 1:
|
||||
raise ValueError, 'direct RGB image not supported'
|
||||
assert cmpSize == pixelSize and pixelSize in [1,2,4,8]
|
||||
f.seek(pmTable)
|
||||
colormap = loadcolormap(f)
|
||||
bits_per_pixel = pixelSize
|
||||
pixels_per_byte = 8 // bits_per_pixel
|
||||
image = []
|
||||
f.seek(patdata)
|
||||
for y in range(h):
|
||||
line = f.read(rowBytes)
|
||||
imgline = []
|
||||
for x in range(w):
|
||||
n = x//pixels_per_byte
|
||||
idx = ((ord(line[n]) >> ((pixels_per_byte - 1 - x%pixels_per_byte) * bits_per_pixel))
|
||||
& ((1<<bits_per_pixel)-1))
|
||||
imgline.append(colormap[idx])
|
||||
image.append(imgline)
|
||||
return image
|
||||
|
||||
|
||||
class LEVLResource(Resource):
|
||||
# bub & bob level
|
||||
WIDTH = 32
|
||||
HEIGHT = 25
|
||||
MONSTERS = 30
|
||||
WALLS = { 1:'#', 0:' '}
|
||||
WINDS = { 0:' ', 1:'>', 2:'<', 3:'v', 4:'^', 5:'x', 0x66:' '}
|
||||
FLAGS = ['flag0', 'letter', 'fire', 'lightning', 'water', 'top', 'flag6', 'flag7']
|
||||
|
||||
def getlevel(self, mnstrlist):
|
||||
f = self.subfile()
|
||||
result = {}
|
||||
|
||||
walls = []
|
||||
for y in range(self.HEIGHT):
|
||||
line = f.read(self.WIDTH//8)
|
||||
line = [self.WALLS[(ord(line[x//8]) >> (x%8)) & 1]
|
||||
for x in range(self.WIDTH)]
|
||||
walls.append(''.join(line))
|
||||
result['walls'] = '\n'.join(walls)
|
||||
|
||||
winds = []
|
||||
for y in range(self.HEIGHT):
|
||||
line = f.read(self.WIDTH)
|
||||
line = [self.WINDS[ord(v)] for v in line]
|
||||
winds.append(''.join(line))
|
||||
result['winds'] = '\n'.join(winds)
|
||||
|
||||
monsters = []
|
||||
for i in range(self.MONSTERS):
|
||||
x,y,monster_type,f1,f2,f3 = struct.unpack(">BBBBBB", f.read(6))
|
||||
if monster_type != 0:
|
||||
assert f1 == 0, f1
|
||||
cls = mnstrlist[monster_type-1]
|
||||
monsters.append(cls(x=x, y=y, dir=f2, player=f3))
|
||||
result['monsters'] = monsters
|
||||
|
||||
result['level'], = struct.unpack('>H', f.read(2))
|
||||
for i in range(8):
|
||||
result[self.FLAGS[i]] = ord(f.read(1))
|
||||
|
||||
return result
|
@ -7,7 +7,7 @@ class Monster1:
|
||||
self.player = player
|
||||
|
||||
def nrange(start,n):
|
||||
return range(start,start+n)
|
||||
return list(range(start,start+n))
|
||||
|
||||
class Nasty(Monster1):
|
||||
right = nrange(239,4)
|
||||
@ -289,11 +289,11 @@ class birange:
|
||||
self.a = a
|
||||
self.n = n
|
||||
def __getitem__(self, pn):
|
||||
return range(self.a + 1000*pn, self.a + 1000*pn + self.n)
|
||||
return list(range(self.a + 1000*pn, self.a + 1000*pn + self.n))
|
||||
|
||||
class bidict:
|
||||
def __init__(self, a,b):
|
||||
self.a = a.items()
|
||||
self.a = list(a.items())
|
||||
def __getitem__(self, pn):
|
||||
pn *= 1000
|
||||
d = {}
|
||||
|
397
bubbob/mnstrmap.py.bak
Normal file
397
bubbob/mnstrmap.py.bak
Normal file
@ -0,0 +1,397 @@
|
||||
|
||||
class Monster1:
|
||||
def __init__(self, x, y, dir, player=0):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.dir = (1, -1)[dir]
|
||||
self.player = player
|
||||
|
||||
def nrange(start,n):
|
||||
return range(start,start+n)
|
||||
|
||||
class Nasty(Monster1):
|
||||
right = nrange(239,4)
|
||||
left = nrange(243,4)
|
||||
jailed = nrange(247,3)
|
||||
dead = nrange(253,4)
|
||||
right_angry = nrange(800,4)
|
||||
left_angry = nrange(804,4)
|
||||
|
||||
class Monky(Monster1):
|
||||
right = nrange(265,4)
|
||||
left = nrange(269,4)
|
||||
jailed = nrange(273,3)
|
||||
dead = nrange(279,4)
|
||||
left_weapon = right_weapon = nrange(451,1) # FIXME
|
||||
decay_weapon = nrange(452,4) # FIXME
|
||||
right_angry = nrange(808,4)
|
||||
left_angry = nrange(812,4)
|
||||
|
||||
class Ghosty(Monster1):
|
||||
right = nrange(291,4)
|
||||
left = nrange(295,4)
|
||||
jailed = nrange(299,3)
|
||||
dead = nrange(305,4)
|
||||
right_angry = nrange(816,4)
|
||||
left_angry = nrange(820,4)
|
||||
|
||||
class Flappy(Monster1):
|
||||
right = nrange(317,4)
|
||||
left = nrange(321,4)
|
||||
jailed = nrange(325,3)
|
||||
dead = nrange(331,4)
|
||||
right_angry = nrange(824,4)
|
||||
left_angry = nrange(828,4)
|
||||
|
||||
class Springy(Monster1):
|
||||
right = nrange(343,4)
|
||||
left = nrange(347,4)
|
||||
jailed = nrange(351,3)
|
||||
dead = nrange(357,4)
|
||||
right_jump = nrange(369,2)
|
||||
left_jump = nrange(371,2)
|
||||
right_angry = nrange(832,4)
|
||||
left_angry = nrange(836,4)
|
||||
right_jump_angry = nrange(840,2)
|
||||
left_jump_angry = nrange(842,2)
|
||||
|
||||
class Orcy(Monster1):
|
||||
right = nrange(373,4)
|
||||
left = nrange(377,4)
|
||||
jailed = nrange(381,3)
|
||||
dead = nrange(387,4)
|
||||
left_weapon = nrange(456,4)
|
||||
right_weapon = nrange(460,4)
|
||||
decay_weapon = nrange(456,0) # FIXME
|
||||
right_angry = nrange(844,4)
|
||||
left_angry = nrange(848,4)
|
||||
|
||||
class Gramy(Monster1):
|
||||
right = nrange(399,4)
|
||||
left = nrange(403,4)
|
||||
jailed = nrange(407,3)
|
||||
dead = nrange(413,4)
|
||||
left_weapon = right_weapon = nrange(472,4) # FIXME
|
||||
right_angry = nrange(852,4)
|
||||
left_angry = nrange(856,4)
|
||||
|
||||
class Blitzy(Monster1):
|
||||
right = left = nrange(425,4)
|
||||
jailed = nrange(429,3)
|
||||
dead = nrange(435,4)
|
||||
right_angry = left_angry = nrange(860,4)
|
||||
left_weapon = right_weapon = nrange(476,1) # FIXME
|
||||
|
||||
class Ghost:
|
||||
left = nrange(443,4)
|
||||
right = nrange(447,4)
|
||||
|
||||
class PlayerBubbles:
|
||||
appearing = nrange(952,5)
|
||||
bubble = nrange(910,3)
|
||||
explosion = nrange(913,3)
|
||||
left_weapon = nrange(464,4)
|
||||
right_weapon = nrange(468,4)
|
||||
decay_weapon = []
|
||||
|
||||
class LetterBubbles:
|
||||
Extend = nrange(128,3) # FIXME
|
||||
eXtend = nrange(136,3)
|
||||
exTend = nrange(144,3)
|
||||
extEnd = nrange(152,3)
|
||||
exteNd = nrange(160,3)
|
||||
extenD = nrange(168,3)
|
||||
|
||||
class DyingBubble:
|
||||
first = nrange(163,3)
|
||||
medium = nrange(171,3)
|
||||
last = nrange(155,3)
|
||||
|
||||
class Fire:
|
||||
ground = nrange(490,4)
|
||||
drop = 489
|
||||
|
||||
class Lightning:
|
||||
fired = 488
|
||||
|
||||
class Water:
|
||||
h_flow = 900
|
||||
v_flow = 901
|
||||
start_right = 902
|
||||
start_left = 904
|
||||
bottom = 903
|
||||
top = 905
|
||||
tl_corner = 906
|
||||
bl_corner = 907
|
||||
br_corner = 908
|
||||
tr_corner = 909
|
||||
|
||||
class Flood:
|
||||
waves = nrange(140,4)
|
||||
fill = 495
|
||||
|
||||
class MiscPoints:
|
||||
pink_100 = 496
|
||||
|
||||
class DigitsMisc:
|
||||
digits_mask = nrange(519,10)
|
||||
digits_border = nrange(920,10)
|
||||
digits_white = nrange(930,10)
|
||||
|
||||
class PotionBonuses:
|
||||
coin = 477
|
||||
flower = 478
|
||||
trefle = 479
|
||||
rainbow = 480
|
||||
green_note = 481
|
||||
blue_note = 692
|
||||
|
||||
|
||||
class Bonuses:
|
||||
monster_bonuses = [
|
||||
(593,1000), # banana
|
||||
(594,2000), # peach
|
||||
(595,3000), # quince
|
||||
(596,4000), # pastec
|
||||
(597,5000), # wine
|
||||
(598,6000), # ananas
|
||||
(599,8000) # diamond
|
||||
]
|
||||
|
||||
door = 139 # Lots of diamonds
|
||||
|
||||
red_potion = 637 #\ .
|
||||
green_potion = 638 # > Clean the level and fill the top 5 lines with one of the PotionBonuses.
|
||||
yellow_potion = 639 #/
|
||||
|
||||
kirsh = 600
|
||||
icecream1 = 601 # NOT_USED
|
||||
erdbeer = 602
|
||||
fish1 = 603
|
||||
tomato = 604
|
||||
donut = 605
|
||||
apple = 606
|
||||
corn = 607
|
||||
icecream2 = 608 # NOT_USED
|
||||
radish = 609
|
||||
|
||||
cyan_ice = 610 #\ .
|
||||
violet_ice = 611 #|
|
||||
peach2 = 612 # > Produced from the bubbles after a wand.
|
||||
pastec2 = 613 #|
|
||||
cream_pie = 614 #|
|
||||
sugar_pie = 615 #/
|
||||
|
||||
brown_wand = 620 #\ .
|
||||
yellow_wand = 621 #|
|
||||
green_wand = 622 # > Bubbles turn into bonus of the previous set after
|
||||
violet_wand = 623 # > the death of the last enemy plus a mega-bonus.
|
||||
blue_wand = 624 #|
|
||||
red_wand = 625 #/
|
||||
|
||||
violet_chest = 626 #\ .
|
||||
blue_chest = 627 # > Bubbles turn into diamonds plus after the death
|
||||
red_chest = 628 # > of the last enemy plus a mega-diamond
|
||||
yellow_chest = 629 #/
|
||||
|
||||
shoe = 631 # speed player movements
|
||||
grenade = 632 # put fire everywhere
|
||||
|
||||
brown_umbrella = 633 # fire rain
|
||||
grey_umbrella = 634 # water rain
|
||||
violet_umbrella = 635 # spinning balls rain
|
||||
|
||||
clock = 636 # time travel
|
||||
coffee = 641 # Speed player's movements and fire rate.
|
||||
book = 642 # Produces stars the middle-top going in any direction which kill the enemy upon contact.
|
||||
heart_poison = 643 # Froze the enemy and they are now killed on contact.
|
||||
gold_crux = 644 # become a bubble
|
||||
red_crux = 645 # become a monster
|
||||
blue_crux = 646 # become a monster
|
||||
extend = 647 # Give 100'000 Points to the player and finish the level.
|
||||
|
||||
ring = 640 # lord of the ring
|
||||
green_pepper = 648 # hot stuff!
|
||||
orange_thing = 649 # slippy
|
||||
aubergine = 650 # rear gear
|
||||
carrot = 651 # angry monsters
|
||||
rape = 652 # auto-fire
|
||||
white_carrot = 653 # fly
|
||||
chickpea = 654 # shield
|
||||
mushroom = 655 # pinball mode
|
||||
egg = 656 # players permutation
|
||||
chestnut = 657 # variation of frames per second
|
||||
green_thing = 658 # sugar bomb
|
||||
icecream3 = 659 # \ each icecream becomes two of the
|
||||
icecream4 = 660 # \ next kind, which scores more points
|
||||
icecream5 = 661 # / that's a lot of points in total
|
||||
icecream6 = 662 # /
|
||||
softice1 = 663 # shoot farther
|
||||
softice2 = 665 # shoot nearer1
|
||||
french_fries = 664 # shoot 10 lightning bubbles
|
||||
custard_pie = 666 # shoot faster
|
||||
lollipop = 667 # invert left and right
|
||||
cocktail = 668 # short-lived bubbles
|
||||
ham = 669 # wall builder
|
||||
bomb = 670 # explodes the structure of the level
|
||||
beer = 671 # shoot 10 water bubbles
|
||||
emerald = 672 # mega points
|
||||
fish2 = 673 # mega blitz
|
||||
sapphire = 681 # mega points
|
||||
ruby = 682 # mega points
|
||||
tin = 674 # angry (double-speed) player
|
||||
hamburger = 675 # shoot 10 fire bubbles
|
||||
insect = 676 # walls fall down
|
||||
blue_necklace = 677 # player ubiquity
|
||||
violet_necklace = 679 # monster ubiquity
|
||||
butterfly = 678 # lunar gravity
|
||||
conch = 680 # complete water flood
|
||||
yellow_sugar = 630 # from a bonbon bomb
|
||||
blue_sugar = 691 # from a bonbon bomb
|
||||
|
||||
class Diamonds:
|
||||
# Produced from the bubbles after last enemy is killed and a chest or wand has been caught.
|
||||
violet = 616
|
||||
blue = 617
|
||||
red = 618
|
||||
yellow = 619
|
||||
|
||||
class Stars:
|
||||
# Effect of the book. Kill monsters on contact.
|
||||
blue = nrange(940,2)
|
||||
yellow = nrange(942,2)
|
||||
red = nrange(944,2)
|
||||
green = nrange(946,2)
|
||||
magenta = nrange(948,2)
|
||||
cyan = nrange(950,2)
|
||||
COLORS = ['blue', 'yellow', 'red', 'green', 'magenta', 'cyan']
|
||||
|
||||
class SpinningBalls:
|
||||
free = nrange(482,4)
|
||||
bubbled = nrange(486,2) # NOT_USED
|
||||
|
||||
class BigImages:
|
||||
cyan_ice = 10 # Megabonus produced after a wand
|
||||
violet_ice = 11
|
||||
peach2 = 12
|
||||
pastec2 = 13
|
||||
cream_pie = 14
|
||||
sugar_pie = 15
|
||||
violet = 16
|
||||
blue = 17
|
||||
red = 18
|
||||
yellow = 19
|
||||
blitz = 30
|
||||
hurryup = nrange(31,2)
|
||||
|
||||
class birange:
|
||||
def __init__(self, a,b,n):
|
||||
self.a = a
|
||||
self.n = n
|
||||
def __getitem__(self, pn):
|
||||
return range(self.a + 1000*pn, self.a + 1000*pn + self.n)
|
||||
|
||||
class bidict:
|
||||
def __init__(self, a,b):
|
||||
self.a = a.items()
|
||||
def __getitem__(self, pn):
|
||||
pn *= 1000
|
||||
d = {}
|
||||
for key, value in self.a:
|
||||
d[key] = value + pn
|
||||
return d
|
||||
|
||||
class GreenAndBlue:
|
||||
water_bubbles = birange(182,185,3)
|
||||
fire_bubbles = birange(176,554,3)
|
||||
light_bubbles = birange(179,557,3)
|
||||
normal_bubbles = birange(188,195,3)
|
||||
new_bubbles = birange(191,203,4)
|
||||
players = birange(210,226,13)
|
||||
jumping_players = birange(683,687,4)
|
||||
new_players = birange(693,696,3)
|
||||
numbers = birange(499,509,10) # FIXME: already seen below
|
||||
comming = birange(693,696,3)
|
||||
points = bidict({
|
||||
100: 529,
|
||||
150: 530,
|
||||
200: 531,
|
||||
250: 532,
|
||||
300: 533,
|
||||
350: 534,
|
||||
500: 535,
|
||||
550: 536,
|
||||
600: 537,
|
||||
650: 538,
|
||||
700: 539,
|
||||
750: 540,
|
||||
800: 541,
|
||||
850: 542,
|
||||
900: 543,
|
||||
950: 544,
|
||||
1000: 545,
|
||||
2000: 546,
|
||||
3000: 547,
|
||||
4000: 548,
|
||||
5000: 549,
|
||||
6000: 550,
|
||||
7000: 551,
|
||||
8000: 552,
|
||||
9000: 553,
|
||||
10000: 20,
|
||||
20000: 21,
|
||||
30000: 22,
|
||||
40000: 23,
|
||||
50000: 24,
|
||||
60000: 25,
|
||||
70000: 26,
|
||||
},{
|
||||
100: 561,
|
||||
150: 562,
|
||||
200: 563,
|
||||
250: 564,
|
||||
300: 565,
|
||||
350: 566,
|
||||
500: 567,
|
||||
550: 568,
|
||||
600: 569,
|
||||
650: 570,
|
||||
700: 571,
|
||||
750: 572,
|
||||
800: 573,
|
||||
850: 574,
|
||||
900: 575,
|
||||
950: 576,
|
||||
1000: 577,
|
||||
2000: 578,
|
||||
3000: 579,
|
||||
4000: 580,
|
||||
5000: 581,
|
||||
6000: 582,
|
||||
7000: 583,
|
||||
8000: 584,
|
||||
9000: 585,
|
||||
10000: 90,
|
||||
20000: 91,
|
||||
30000: 92,
|
||||
40000: 93,
|
||||
50000: 94,
|
||||
60000: 95,
|
||||
70000: 96,
|
||||
})
|
||||
gameover = birange(497,498,1)
|
||||
digits = birange(499,509,10)
|
||||
fish = birange(700,707,7)
|
||||
|
||||
class Butterfly(Monster1):
|
||||
right = [('butterfly', 'fly', n) for n in range(2)]
|
||||
left = [Bonuses.insect, Bonuses.butterfly]
|
||||
jailed = [('butterfly', 'jailed', n) for n in range(3)]
|
||||
dead = [('butterfly', 'dead', n) for n in range(4)]
|
||||
|
||||
class Sheep(Monster1):
|
||||
right = [('sheep', 1, n) for n in range(4)]
|
||||
left = [('sheep',-1, n) for n in range(4)]
|
||||
right_angry = right
|
||||
left_angry = left
|
||||
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import random
|
||||
import gamesrv
|
||||
import images
|
||||
@ -780,7 +780,7 @@ class Blitzy(Monster):
|
||||
self.no_shoot_before = BubPlayer.FrameCounter + 29
|
||||
return 0
|
||||
|
||||
MonsterClasses = [c for c in globals().values()
|
||||
MonsterClasses = [c for c in list(globals().values())
|
||||
if type(c)==type(Monster) and issubclass(c, Monster)]
|
||||
MonsterClasses.remove(Monster)
|
||||
|
||||
|
937
bubbob/monsters.py.bak
Normal file
937
bubbob/monsters.py.bak
Normal file
@ -0,0 +1,937 @@
|
||||
from __future__ import generators
|
||||
import random
|
||||
import gamesrv
|
||||
import images
|
||||
import boards
|
||||
from boards import *
|
||||
from images import ActiveSprite
|
||||
from mnstrmap import GreenAndBlue, Bonuses, Ghost
|
||||
from player import BubPlayer
|
||||
import bonuses
|
||||
|
||||
|
||||
class Monster(ActiveSprite):
|
||||
touchable = 1
|
||||
special_prob = 0.2
|
||||
shootcls = None
|
||||
vx = 2
|
||||
vy = 0
|
||||
vdir = -1
|
||||
is_ghost = 0
|
||||
MonsterBonus = bonuses.MonsterBonus
|
||||
|
||||
def __init__(self, mnstrdef, x=None, y=None, dir=None, in_list=None):
|
||||
self.mdef = mnstrdef
|
||||
self.ptag = None
|
||||
if dir is None: dir = mnstrdef.dir
|
||||
if x is None: x = mnstrdef.x*CELL
|
||||
if y is None: y = mnstrdef.y*CELL
|
||||
self.dir = dir
|
||||
ActiveSprite.__init__(self, images.sprget(self.imgrange()[0]), x, y)
|
||||
self.gen.append(self.waiting())
|
||||
if in_list is None:
|
||||
in_list = BubPlayer.MonsterList
|
||||
self.in_list = in_list
|
||||
self.in_list.append(self)
|
||||
self.no_shoot_before = 0
|
||||
#images.ActiveSprites.remove(self)
|
||||
|
||||
def unlist(self):
|
||||
try:
|
||||
self.in_list.remove(self)
|
||||
return 1
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
def kill(self):
|
||||
self.unlist()
|
||||
ActiveSprite.kill(self)
|
||||
|
||||
def tagdragon(self):
|
||||
lst = bonuses.getvisibledragonlist()
|
||||
if lst:
|
||||
return random.choice(lst)
|
||||
else:
|
||||
return None
|
||||
|
||||
def imgrange(self):
|
||||
if self.is_ghost:
|
||||
if self.dir > 0:
|
||||
return Ghost.right
|
||||
else:
|
||||
return Ghost.left
|
||||
elif self.angry:
|
||||
if self.dir > 0:
|
||||
return self.mdef.right_angry
|
||||
else:
|
||||
return self.mdef.left_angry
|
||||
else:
|
||||
if self.dir > 0:
|
||||
return self.mdef.right
|
||||
else:
|
||||
return self.mdef.left
|
||||
|
||||
def imgrange1(self):
|
||||
# normally this is self.imgrange()[1]
|
||||
lst = self.imgrange()
|
||||
return lst[len(lst) > 1]
|
||||
|
||||
def resetimages(self, is_ghost=0):
|
||||
self.is_ghost = is_ghost
|
||||
if self.gen:
|
||||
self.setimages(self.cyclic(self.imgrange(), 3))
|
||||
else: # frozen monster
|
||||
self.seticon(images.sprget(self.imgrange()[0]))
|
||||
|
||||
def blocked(self):
|
||||
if self.dir < 0:
|
||||
x0 = (self.x-1)//16
|
||||
else:
|
||||
x0 = (self.x+33)//16
|
||||
y0 = self.y // 16 + 1
|
||||
y1 = (self.y + 31) // 16
|
||||
return bget(x0,y0) == '#' or bget(x0,y1) == '#'
|
||||
|
||||
def tryhstep(self):
|
||||
if self.blocked():
|
||||
self.dir = -self.dir
|
||||
self.resetimages()
|
||||
return 0
|
||||
else:
|
||||
self.step(self.vx*self.dir, 0)
|
||||
return 1
|
||||
|
||||
def vblocked(self):
|
||||
if self.vdir < 0:
|
||||
y0 = self.y//16
|
||||
else:
|
||||
y0 = (self.y+1)//16 + 2
|
||||
x0 = self.x // 16
|
||||
x1 = self.x // 16 + 1
|
||||
x2 = (self.x+31) // 16
|
||||
return bget(x0,y0) == '#' or bget(x1,y0) == '#' or bget(x2,y0) == '#'
|
||||
|
||||
def tryvstep(self):
|
||||
if self.vblocked():
|
||||
self.vdir = -self.vdir
|
||||
return 0
|
||||
else:
|
||||
self.step(0, self.vy*self.vdir)
|
||||
self.vertical_warp()
|
||||
return 1
|
||||
|
||||
def waiting(self, delay=20):
|
||||
for i in range(delay):
|
||||
yield None
|
||||
self.resetimages()
|
||||
self.gen.append(self.default_mode())
|
||||
|
||||
def overlapping(self):
|
||||
if self.in_list is BubPlayer.MonsterList:
|
||||
for s in self.in_list:
|
||||
if (-6 <= s.x-self.x <= 6 and -6 <= s.y-self.y < 6 and
|
||||
#s.dir == self.dir and s.vdir == self.vdir and
|
||||
s.vx == self.vx and s.vy == self.vy and
|
||||
(not s.angry) == (not self.angry)):
|
||||
return s is not self
|
||||
return 0
|
||||
|
||||
def walking(self):
|
||||
while onground(self.x, self.y):
|
||||
yield None
|
||||
if random.random() < 0.2 and self.overlapping():
|
||||
yield None
|
||||
x1 = self.x
|
||||
if self.dir > 0:
|
||||
x1 += self.vx
|
||||
if (x1 & 15) < self.vx and random.random() < self.special_prob:
|
||||
self.move(x1 & -16, self.y)
|
||||
if self.special():
|
||||
return
|
||||
self.tryhstep()
|
||||
if self.seedragon():
|
||||
self.gen.append(self.hjumping())
|
||||
else:
|
||||
self.gen.append(self.falling())
|
||||
|
||||
def seedragon(self, dragon=None):
|
||||
dragon = dragon or self.tagdragon()
|
||||
if dragon is None:
|
||||
return False
|
||||
return abs(dragon.y - self.y) < 16 and self.dir*(dragon.x-self.x) > 0
|
||||
|
||||
def special(self):
|
||||
dragon = self.tagdragon()
|
||||
if dragon is None:
|
||||
return 0
|
||||
if self.seedragon(dragon) and self.shoot():
|
||||
return 1
|
||||
if dragon.y < self.y-CELL:
|
||||
#and abs(dragon.x-self.x) < 2*(self.y-dragon.y):
|
||||
for testy in range(self.y-2*CELL, self.y-6*CELL, -CELL):
|
||||
if onground(self.x, testy):
|
||||
if random.random() < 0.5:
|
||||
ndir = self.dir
|
||||
elif dragon.x < self.x:
|
||||
ndir = -1
|
||||
else:
|
||||
ndir = 1
|
||||
self.gen.append(self.vjumping(testy, ndir))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def shooting(self, pause):
|
||||
for i in range(pause):
|
||||
yield None
|
||||
self.shootcls(self)
|
||||
yield None
|
||||
self.gen.append(self.default_mode())
|
||||
|
||||
def shoot(self, pause=10):
|
||||
if (self.shootcls is None or
|
||||
self.no_shoot_before > BubPlayer.FrameCounter):
|
||||
return 0
|
||||
else:
|
||||
self.gen.append(self.shooting(pause))
|
||||
self.no_shoot_before = BubPlayer.FrameCounter + 29
|
||||
return 1
|
||||
|
||||
def falling(self):
|
||||
bubber = getattr(self, 'bubber', None)
|
||||
while not onground(self.x, self.y):
|
||||
yield None
|
||||
ny = self.y + 3
|
||||
if (ny & 15) > 14:
|
||||
ny = (ny//16+1)*16
|
||||
elif (ny & 15) < 3:
|
||||
ny = (ny//16)*16
|
||||
nx = self.x
|
||||
if nx < 32:
|
||||
nx += 1 + (self.vx-1) * (bubber is not None)
|
||||
elif nx > boards.bwidth - 64:
|
||||
nx -= 1 + (self.vx-1) * (bubber is not None)
|
||||
elif bubber:
|
||||
dx = bubber.wannago(self.dcap)
|
||||
if dx and dx != self.dir:
|
||||
self.dir = dx
|
||||
self.resetimages()
|
||||
self.setimages(None)
|
||||
if dx and not self.blocked():
|
||||
nx += self.vx*dx
|
||||
self.seticon(images.sprget(self.imgrange1()))
|
||||
self.move(nx, ny)
|
||||
if self.y >= boards.bheight:
|
||||
self.vertical_warp()
|
||||
if bubber:
|
||||
nextgen = self.playing_monster
|
||||
else:
|
||||
nextgen = self.walking
|
||||
self.gen.append(nextgen())
|
||||
|
||||
## def moebius(self):
|
||||
## self.dir = -self.dir
|
||||
## self.resetimages()
|
||||
## if hasattr(self, 'dcap'):
|
||||
## self.dcap['left2right'] *= -1
|
||||
|
||||
def hjumping(self):
|
||||
y0 = self.y
|
||||
vspeed = -2.2
|
||||
ny = y0-1
|
||||
while ny <= y0 and not self.blocked():
|
||||
self.move(self.x+2*self.dir, int(ny))
|
||||
yield None
|
||||
vspeed += 0.19
|
||||
ny = self.y + vspeed
|
||||
self.gen.append(self.default_mode())
|
||||
|
||||
def vjumping(self, limity, ndir):
|
||||
self.setimages(None)
|
||||
yield None
|
||||
self.dir = -self.dir
|
||||
self.seticon(images.sprget(self.imgrange()[0]))
|
||||
for i in range(9):
|
||||
yield None
|
||||
self.dir = -self.dir
|
||||
self.seticon(images.sprget(self.imgrange()[0]))
|
||||
for i in range(4):
|
||||
yield None
|
||||
self.dir = ndir
|
||||
self.seticon(images.sprget(self.imgrange1()))
|
||||
for ny in range(self.y-4, limity-4, -4):
|
||||
self.move(self.x, ny)
|
||||
if ny < -32:
|
||||
self.vertical_warp()
|
||||
yield None
|
||||
self.resetimages()
|
||||
self.gen.append(self.default_mode())
|
||||
|
||||
def regular(self):
|
||||
return self.still_playing() and self.touchable and not self.is_ghost
|
||||
|
||||
def still_playing(self):
|
||||
return (self.in_list is BubPlayer.MonsterList and
|
||||
self in self.in_list)
|
||||
|
||||
def touched(self, dragon):
|
||||
if self.gen:
|
||||
self.killdragon(dragon)
|
||||
if self.is_ghost and not hasattr(self, 'bubber'):
|
||||
self.gen = [self.default_mode()]
|
||||
self.resetimages()
|
||||
else:
|
||||
self.argh(getattr(self, 'poplist', None)) # frozen monster
|
||||
|
||||
def killdragon(self, dragon):
|
||||
dragon.die()
|
||||
|
||||
def in_bubble(self, bubble):
|
||||
if not hasattr(self.mdef, 'jailed'):
|
||||
return
|
||||
self.untouchable()
|
||||
self.angry = []
|
||||
bubble.move(self.x, self.y)
|
||||
if not hasattr(bubble, 'withmonster'):
|
||||
bubble.to_front()
|
||||
self.to_front()
|
||||
img = self.mdef.jailed
|
||||
self.gen = [self.bubbling(bubble)]
|
||||
self.setimages(self.cyclic([img[1], img[2], img[1], img[0]], 4))
|
||||
|
||||
def bubbling(self, bubble):
|
||||
counter = 0
|
||||
while not hasattr(bubble, 'poplist'):
|
||||
self.move(bubble.x, bubble.y)
|
||||
yield None
|
||||
counter += 1
|
||||
if counter == 50 and hasattr(self, 'bubber'):
|
||||
bubble.setimages(bubble.bubble_red())
|
||||
if bubble.poplist is None:
|
||||
self.touchable = 1
|
||||
self.angry = [self.genangry()]
|
||||
self.resetimages()
|
||||
self.gen.append(self.default_mode())
|
||||
else:
|
||||
previous_len = len(BubPlayer.MonsterList)
|
||||
self.argh(bubble.poplist)
|
||||
dragon = bubble.poplist[0]
|
||||
if dragon is not None:
|
||||
if previous_len and not BubPlayer.MonsterList:
|
||||
points = 990
|
||||
else:
|
||||
points = 90
|
||||
dragon.bubber.givepoints(points)
|
||||
|
||||
def argh(self, poplist=None, onplace=0):
|
||||
if self not in self.in_list:
|
||||
return
|
||||
if not poplist:
|
||||
poplist = [None]
|
||||
poplist.append(self)
|
||||
level = len(poplist) - 2
|
||||
bonuses.BonusMaker(self.x, self.y, self.mdef.dead, onplace=onplace,
|
||||
outcome=(self.MonsterBonus, level))
|
||||
self.kill()
|
||||
|
||||
def freeze(self, poplist):
|
||||
# don't freeze monsters largely out of screen, or they'll never come in
|
||||
if self.regular() and -self.ico.h < self.y < boards.bheight:
|
||||
self.gen = []
|
||||
self.poplist = poplist
|
||||
|
||||
def flying(self):
|
||||
blocked = 0
|
||||
while 1:
|
||||
if random.random() < 0.2 and self.overlapping():
|
||||
yield None
|
||||
hstep = self.tryhstep()
|
||||
vstep = self.tryvstep()
|
||||
if hstep or vstep:
|
||||
blocked = 0
|
||||
elif blocked:
|
||||
# blocked! go up or back to the play area
|
||||
if self.x < 32:
|
||||
self.step(self.vy, 0)
|
||||
elif self.x > boards.bwidth - 64:
|
||||
self.step(-self.vy, 0)
|
||||
else:
|
||||
self.step(0, -self.vy)
|
||||
self.vertical_warp()
|
||||
else:
|
||||
blocked = 1
|
||||
yield None
|
||||
|
||||
def becoming_monster(self, big=0, immed=0):
|
||||
if big:
|
||||
self.is_ghost = 1
|
||||
self.seticon(images.sprget(self.imgrange()[0]))
|
||||
images.Snd.Hell.play()
|
||||
for i in range(5):
|
||||
ico = self.ico
|
||||
self.seticon(self.bubber.icons[11 + immed, self.dir])
|
||||
yield None
|
||||
yield None
|
||||
self.seticon(ico)
|
||||
yield None
|
||||
yield None
|
||||
self.resetimages(is_ghost=big)
|
||||
self.gen.append(self.playing_monster())
|
||||
|
||||
def become_monster(self, bubber, saved_caps, big=0, immed=0):
|
||||
self.timeoutgen = self.back_to_dragon()
|
||||
self.default_mode = self.playing_monster
|
||||
self.bubber = bubber
|
||||
self.dcap = saved_caps
|
||||
self.gen = [self.becoming_monster(big, immed)]
|
||||
|
||||
def back_to_dragon(self):
|
||||
for t in range(259):
|
||||
yield None
|
||||
if bonuses.getdragonlist():
|
||||
yield None
|
||||
yield None
|
||||
yield None
|
||||
from player import Dragon
|
||||
d = Dragon(self.bubber, self.x, self.y, self.dir, self.dcap)
|
||||
d.dcap['shield'] = 50
|
||||
self.bubber.dragons.append(d)
|
||||
self.kill()
|
||||
|
||||
def playing_monster(self):
|
||||
if self.timeoutgen not in self.gen:
|
||||
self.gen.append(self.timeoutgen)
|
||||
bubber = self.bubber
|
||||
while self.is_ghost:
|
||||
# ghost
|
||||
self.angry = []
|
||||
key, dx, dy = max([(bubber.key_left, -1, 0),
|
||||
(bubber.key_right, 1, 0),
|
||||
(bubber.key_jump, 0, -1),
|
||||
(bubber.key_fire, 0, 1)])
|
||||
if key:
|
||||
if dx and self.dir != dx:
|
||||
self.dir = dx
|
||||
self.resetimages(is_ghost=1)
|
||||
nx = self.x + 10*dx
|
||||
ny = self.y + 9*dy
|
||||
if nx < 0: nx = 0
|
||||
if nx > boards.bwidth-2*CELL: nx = boards.bwidth-2*CELL
|
||||
if ny < -CELL: ny = -CELL
|
||||
if ny > boards.bheight-CELL: ny = boards.bheight-CELL
|
||||
self.move(nx, ny)
|
||||
yield None
|
||||
if self.vy:
|
||||
# flying monster
|
||||
while 1:
|
||||
dx = bubber.wannago(self.dcap)
|
||||
if dx and dx != self.dir:
|
||||
self.dir = dx
|
||||
self.resetimages()
|
||||
if bubber.key_jump and bubber.key_jump > bubber.key_fire:
|
||||
dy = self.vdir = -1
|
||||
elif bubber.key_fire:
|
||||
dy = self.vdir = 1
|
||||
else:
|
||||
dy = 0
|
||||
hstep = dx and self.tryhstep()
|
||||
vstep = dy and self.tryvstep()
|
||||
if dx and dy and not (hstep or vstep):
|
||||
# blocked?
|
||||
self.dir = -self.dir
|
||||
self.vdir = -self.vdir
|
||||
blocked = self.blocked() and self.vblocked()
|
||||
self.dir = -self.dir
|
||||
self.vdir = -self.vdir
|
||||
if blocked:
|
||||
# completely blocked! accept move or force back to
|
||||
# play area
|
||||
if self.x < 32:
|
||||
self.step(self.vy, 0)
|
||||
elif self.x > boards.bwidth - 64:
|
||||
self.step(-self.vy, 0)
|
||||
else:
|
||||
self.step(self.vx*dx, self.vy*dy)
|
||||
self.vertical_warp()
|
||||
yield None
|
||||
elif not isinstance(self, Springy):
|
||||
# walking monster
|
||||
jumping_y = 0
|
||||
imgsetter = self.imgsetter
|
||||
while onground(self.x, self.y) or jumping_y:
|
||||
dx = bubber.wannago(self.dcap)
|
||||
if dx and dx != self.dir:
|
||||
self.dir = dx
|
||||
self.resetimages()
|
||||
imgsetter = self.imgsetter
|
||||
if dx and not self.blocked():
|
||||
self.step(self.vx*dx, 0)
|
||||
if not jumping_y:
|
||||
self.setimages(imgsetter)
|
||||
else:
|
||||
self.seticon(images.sprget(self.imgrange1()))
|
||||
self.setimages(None)
|
||||
else:
|
||||
self.setimages(None)
|
||||
dx = 0
|
||||
yield None
|
||||
if not jumping_y:
|
||||
wannafire = bubber.key_fire
|
||||
wannajump = bubber.key_jump
|
||||
if wannafire and self.shoot(1):
|
||||
return
|
||||
if wannajump:
|
||||
jumping_y = CELL
|
||||
if jumping_y:
|
||||
self.step(0, -4)
|
||||
if self.y < -32:
|
||||
self.vertical_warp()
|
||||
if onground(self.x, self.y):
|
||||
jumping_y = 0
|
||||
else:
|
||||
jumping_y -= 1
|
||||
self.gen.append(self.falling())
|
||||
else:
|
||||
# springy
|
||||
if not onground(self.x, self.y):
|
||||
self.gen.append(self.falling())
|
||||
return
|
||||
prevx = self.x
|
||||
for t in self.walking():
|
||||
dx = bubber.wannago(self.dcap)
|
||||
if dx:
|
||||
if dx != self.dir:
|
||||
self.dir = dx
|
||||
self.resetimages()
|
||||
if self.blocked() and (self.x-prevx)*dx <= 0:
|
||||
dx = 0
|
||||
self.move(prevx + self.vx*dx, self.y)
|
||||
yield None
|
||||
prevx = self.x
|
||||
|
||||
def become_ghost(self):
|
||||
self.gen = [self.ghosting()]
|
||||
self.resetimages(is_ghost=1)
|
||||
|
||||
def ghosting(self):
|
||||
counter = 0
|
||||
while counter < 5:
|
||||
for i in range(50):
|
||||
yield None
|
||||
dragon = self.tagdragon()
|
||||
if dragon is None:
|
||||
counter += 1
|
||||
else:
|
||||
counter = 0
|
||||
px, py = dragon.x, dragon.y
|
||||
if abs(px-self.x) < abs(py-self.y):
|
||||
dx = 0
|
||||
if py > self.y:
|
||||
dy = 1
|
||||
else:
|
||||
dy = -1
|
||||
else:
|
||||
dy = 0
|
||||
if px > self.x:
|
||||
dx = 1
|
||||
else:
|
||||
dx = -1
|
||||
self.dir = dx
|
||||
self.resetimages(is_ghost=1)
|
||||
dx *= 10
|
||||
dy *= 9
|
||||
distance = 1E10
|
||||
while 1:
|
||||
self.angry = []
|
||||
self.step(dx, dy)
|
||||
yield None
|
||||
dist1 = (px-self.x)*(px-self.x)+(py-self.y)*(py-self.y)
|
||||
if dist1 > distance:
|
||||
break
|
||||
distance = dist1
|
||||
self.angry = []
|
||||
self.gen = [self.default_mode()]
|
||||
self.resetimages()
|
||||
|
||||
default_mode = falling
|
||||
|
||||
|
||||
def argh_em_all():
|
||||
poplist = [None]
|
||||
for s in images.ActiveSprites[:]:
|
||||
if isinstance(s, Monster):
|
||||
s.argh(poplist)
|
||||
|
||||
def freeze_em_all():
|
||||
poplist = [None]
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Monster):
|
||||
s.freeze(poplist)
|
||||
|
||||
|
||||
class MonsterShot(ActiveSprite):
|
||||
speed = 6
|
||||
touchable = 1
|
||||
|
||||
def __init__(self, owner, dx=CELL, dy=0):
|
||||
self.owner = owner
|
||||
self.speed = owner.dir * self.speed
|
||||
if owner.dir < 0:
|
||||
nimages = owner.mdef.left_weapon
|
||||
else:
|
||||
nimages = owner.mdef.right_weapon
|
||||
ActiveSprite.__init__(self, images.sprget(nimages[0]),
|
||||
owner.x, owner.y + dy)
|
||||
self.step((owner.ico.w - self.ico.w) // 2,
|
||||
(owner.ico.h - self.ico.h) // 2)
|
||||
if not self.blocked():
|
||||
self.step(dx*owner.dir, 0)
|
||||
if len(nimages) > 1:
|
||||
self.setimages(self.cyclic(nimages, 3))
|
||||
self.gen.append(self.moving())
|
||||
|
||||
def blocked(self):
|
||||
if self.speed < 0:
|
||||
x0 = (self.x-self.speed-8)//16
|
||||
else:
|
||||
x0 = (self.x+self.ico.w+self.speed-8)//16
|
||||
y0 = (self.y+8) // 16 + 1
|
||||
return not (' ' == bget(x0,y0) == bget(x0+1,y0))
|
||||
|
||||
def moving(self):
|
||||
while not self.blocked():
|
||||
yield None
|
||||
self.step(self.speed, 0)
|
||||
self.hitwall()
|
||||
|
||||
def hitwall(self):
|
||||
self.untouchable()
|
||||
self.gen.append(self.die(self.owner.mdef.decay_weapon, 2))
|
||||
|
||||
def touched(self, dragon):
|
||||
dragon.die()
|
||||
|
||||
|
||||
class BoomerangShot(MonsterShot):
|
||||
speed = 8
|
||||
|
||||
def hitwall(self):
|
||||
self.gen.append(self.moveback())
|
||||
|
||||
def moveback(self):
|
||||
owner = self.owner
|
||||
if self.speed > 0:
|
||||
nimages = owner.mdef.left_weapon
|
||||
else:
|
||||
nimages = owner.mdef.right_weapon
|
||||
self.setimages(self.cyclic(nimages, 3))
|
||||
while (owner.x-self.x) * self.speed < 0:
|
||||
yield None
|
||||
self.step(-self.speed, 0)
|
||||
if self.blocked():
|
||||
break
|
||||
self.kill()
|
||||
|
||||
class FastShot(MonsterShot):
|
||||
speed = 15
|
||||
|
||||
|
||||
class DownShot(MonsterShot):
|
||||
|
||||
def __init__(self, owner):
|
||||
MonsterShot.__init__(self, owner, 0, CELL)
|
||||
|
||||
def moving(self):
|
||||
while self.y < boards.bheight:
|
||||
yield None
|
||||
self.step(0, 7)
|
||||
self.kill()
|
||||
|
||||
|
||||
##class DragonShot(MonsterShot):
|
||||
## speed = 8
|
||||
|
||||
## def __init__(self, owner):
|
||||
## MonsterShot.__init__(self, owner)
|
||||
## self.untouchable()
|
||||
## self.gen.append(self.touchdelay(4))
|
||||
|
||||
## def touched(self, dragon):
|
||||
## if dragon is not self.owner:
|
||||
## if dragon.bubber.bonbons == 0:
|
||||
## dragon.die()
|
||||
## else:
|
||||
## from player import scoreboard
|
||||
## from bonuses import Sugar1, Sugar2
|
||||
## from bonuses import BonusMaker
|
||||
## if random.random() < 0.2345:
|
||||
## start = 1
|
||||
## else:
|
||||
## start = 0
|
||||
## loose = min(2, dragon.bubber.bonbons)
|
||||
## for i in range(start, loose):
|
||||
## cls = random.choice([Sugar1, Sugar2])
|
||||
## BonusMaker(self.x, self.y, [cls.nimage],
|
||||
## outcome=(cls,))
|
||||
## dragon.bubber.bonbons -= loose
|
||||
## scoreboard()
|
||||
## dragon.dcap['shield'] = 25
|
||||
## self.owner.play(images.Snd.Yippee)
|
||||
## self.kill()
|
||||
|
||||
## def blocked(self):
|
||||
## return self.x < -self.ico.w or self.x >= gamesrv.game.width
|
||||
## #return self.x < CELL or self.x >= boards.bwidth - 3*CELL
|
||||
|
||||
|
||||
class Nasty(Monster):
|
||||
pass
|
||||
|
||||
class Monky(Monster):
|
||||
shootcls = MonsterShot
|
||||
|
||||
class Ghosty(Monster):
|
||||
default_mode = Monster.flying
|
||||
vy = 2
|
||||
|
||||
class Flappy(Monster):
|
||||
default_mode = Monster.flying
|
||||
vy = 1
|
||||
|
||||
class Springy(Monster):
|
||||
spring_down = 0
|
||||
def imgrange(self):
|
||||
if self.spring_down and not self.is_ghost:
|
||||
if self.angry:
|
||||
if self.dir > 0:
|
||||
r = self.mdef.right_jump_angry
|
||||
else:
|
||||
r = self.mdef.left_jump_angry
|
||||
else:
|
||||
if self.dir > 0:
|
||||
r = self.mdef.right_jump
|
||||
else:
|
||||
r = self.mdef.left_jump
|
||||
return [r[self.spring_down-1]]
|
||||
else:
|
||||
return Monster.imgrange(self)
|
||||
def walking(self):
|
||||
self.spring_down = 1
|
||||
self.resetimages()
|
||||
for t in range(2+self.overlapping()):
|
||||
yield None
|
||||
self.spring_down = 2
|
||||
self.resetimages()
|
||||
for t in range(4+2*self.overlapping()):
|
||||
yield None
|
||||
self.spring_down = 1
|
||||
self.resetimages()
|
||||
for t in range(2+self.overlapping()):
|
||||
yield None
|
||||
self.spring_down = 0
|
||||
self.resetimages()
|
||||
g = 10.0/43
|
||||
vy = -20*g
|
||||
yf = self.y
|
||||
for t in range(40):
|
||||
yf += vy
|
||||
vy += g
|
||||
if self.blocked():
|
||||
self.dir = -self.dir
|
||||
self.resetimages()
|
||||
nx = self.x + self.dir*self.vx
|
||||
if self.y//16 < int(yf)//16:
|
||||
if onground(self.x, (self.y//16+1)*16):
|
||||
break
|
||||
if onground(nx, (self.y//16+1)*16):
|
||||
self.move(nx, self.y)
|
||||
break
|
||||
nx, yf = vertical_warp(nx, yf)
|
||||
self.move(nx, int(yf))
|
||||
## if moebius:
|
||||
## self.moebius()
|
||||
yield None
|
||||
self.gen.append(self.falling())
|
||||
|
||||
class Orcy(Monster):
|
||||
shootcls = FastShot
|
||||
|
||||
class Gramy(Monster):
|
||||
shootcls = BoomerangShot
|
||||
vx = 3
|
||||
|
||||
class Blitzy(Monster):
|
||||
shootcls = DownShot
|
||||
vx = 3
|
||||
|
||||
def seedragon(self, dragon=None):
|
||||
return 0
|
||||
|
||||
def special(self):
|
||||
if random.random() < 0.3:
|
||||
self.shootcls(self)
|
||||
return 0
|
||||
|
||||
def shoot(self, pause=0):
|
||||
# no pause (only used when controlled by the player)
|
||||
if self.no_shoot_before > BubPlayer.FrameCounter:
|
||||
pass
|
||||
else:
|
||||
self.shootcls(self)
|
||||
self.no_shoot_before = BubPlayer.FrameCounter + 29
|
||||
return 0
|
||||
|
||||
MonsterClasses = [c for c in globals().values()
|
||||
if type(c)==type(Monster) and issubclass(c, Monster)]
|
||||
MonsterClasses.remove(Monster)
|
||||
|
||||
|
||||
class Butterfly(Monster):
|
||||
MonsterBonus = bonuses.IceMonsterBonus
|
||||
fly_away = False
|
||||
|
||||
def waiting(self, delay=0):
|
||||
return Monster.waiting(self, delay)
|
||||
|
||||
def imgrange(self):
|
||||
self.angry = []
|
||||
return Monster.imgrange(self)
|
||||
|
||||
def killdragon(self, dragon):
|
||||
if self.is_ghost:
|
||||
Monster.killdragon(self, dragon)
|
||||
else:
|
||||
self.fly_away = True, dragon.x
|
||||
|
||||
def flying(self):
|
||||
repeat = 0
|
||||
while 1:
|
||||
r = random.random()
|
||||
if self.x < 64:
|
||||
bump = self.dir < 0
|
||||
elif self.x > boards.bwidth - 64:
|
||||
bump = self.dir > 0
|
||||
elif self.fly_away:
|
||||
wannago = self.x - self.fly_away[1]
|
||||
if self.x < 100:
|
||||
wannago = 1
|
||||
elif self.x > boards.bwidth - 100:
|
||||
wannago = -1
|
||||
bump = self.dir * wannago < 0
|
||||
if repeat:
|
||||
self.fly_away = False
|
||||
repeat = 0
|
||||
else:
|
||||
repeat = 1
|
||||
else:
|
||||
bump = r < 0.07
|
||||
if bump:
|
||||
self.dir = -self.dir
|
||||
self.resetimages()
|
||||
elif r > 0.92:
|
||||
self.vdir = -self.vdir
|
||||
self.step(self.dir * (2 + (r < 0.5)), self.vdir * 2)
|
||||
self.vertical_warp()
|
||||
if not repeat:
|
||||
yield None
|
||||
|
||||
default_mode = flying
|
||||
|
||||
|
||||
class Sheep(Monster):
|
||||
|
||||
def playing_monster(self):
|
||||
from bonuses import Bonus
|
||||
bubber = self.bubber
|
||||
vy = None
|
||||
imgsetter = self.imgsetter
|
||||
poplist = [None]
|
||||
while 1:
|
||||
dx = bubber.wannago(self.dcap)
|
||||
if dx and dx != self.dir:
|
||||
self.dir = dx
|
||||
self.resetimages()
|
||||
imgsetter = self.imgsetter
|
||||
if dx and vy is None:
|
||||
self.setimages(imgsetter)
|
||||
else:
|
||||
self.setimages(None)
|
||||
if vy is not None:
|
||||
if vy < 0:
|
||||
n = 1
|
||||
else:
|
||||
n = 3
|
||||
self.seticon(images.sprget(self.imgrange()[n]))
|
||||
if dx and not self.blocked():
|
||||
self.step(self.vx*dx, 0)
|
||||
yield None
|
||||
impulse = 0.0
|
||||
wannajump = bubber.key_jump
|
||||
if vy is not None:
|
||||
vy += 0.33
|
||||
if vy > 12.0:
|
||||
vy = 12.0
|
||||
yf = self.y + yfp + vy
|
||||
yfp = yf - int(yf)
|
||||
delta = int(yf) - self.y
|
||||
if delta > 0:
|
||||
by_y = {}
|
||||
for s in images.ActiveSprites:
|
||||
if isinstance(s, Bonus) and s.touchable:
|
||||
if abs(s.x - self.x) <= 22:
|
||||
by_y[s.y] = s
|
||||
for monster in BubPlayer.MonsterList:
|
||||
if abs(monster.x - self.x) <= 22:
|
||||
if monster.regular():
|
||||
by_y[monster.y] = monster
|
||||
for ny in range(self.y - 1, self.y + delta + 1):
|
||||
self.move(self.x, ny)
|
||||
self.vertical_warp()
|
||||
if onground(self.x, self.y):
|
||||
poplist = [None]
|
||||
impulse = vy
|
||||
vy = None
|
||||
break
|
||||
key = self.y + 29
|
||||
if key in by_y:
|
||||
s = by_y[key]
|
||||
if isinstance(s, Monster):
|
||||
self.play(images.Snd.Extra)
|
||||
s.argh(poplist)
|
||||
elif isinstance(s, Bonus):
|
||||
s.reallytouched(self)
|
||||
yfp = 0.0
|
||||
vy = -3.3
|
||||
break
|
||||
else:
|
||||
self.step(0, delta)
|
||||
self.vertical_warp()
|
||||
if vy is None:
|
||||
if onground(self.x, self.y):
|
||||
if wannajump:
|
||||
yfp = 0.0
|
||||
vy = - max(1.0, impulse) - 2.02
|
||||
impulse = 0.0
|
||||
self.play(images.Snd.Jump)
|
||||
else:
|
||||
yfp = vy = 0.0
|
||||
if impulse > 8.1:
|
||||
break
|
||||
self.play(images.Snd.Pop)
|
||||
for n in range(2):
|
||||
for letter in 'abcdefg':
|
||||
ico = images.sprget(('sheep', letter))
|
||||
nx = self.x + random.randrange(-1, self.ico.w - ico.w + 2)
|
||||
ny = self.y + random.randrange(0, self.ico.h - ico.h + 2)
|
||||
dxy = [random.random() * 5.3 - 2.65, random.random() * 4 - 4.4]
|
||||
s = images.ActiveSprite(ico, nx, ny)
|
||||
s.gen.append(s.parabolic(dxy))
|
||||
s.gen.append(s.die([None], random.randrange(35, 54)))
|
||||
self.move(-99, 0)
|
||||
for t in range(68):
|
||||
yield None
|
||||
self.kill()
|
||||
|
||||
default_mode = falling = playing_monster
|
||||
|
||||
def argh(self, *args, **kwds):
|
||||
pass
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import random, math, time
|
||||
import gamesrv
|
||||
import images
|
||||
@ -123,7 +123,7 @@ class Dragon(ActiveSprite):
|
||||
outcome=bonus.buildoutcome())
|
||||
elif self.bubber.letters and random.random() > 0.59 and can_loose_letter:
|
||||
# loose a letter
|
||||
lst = range(6)
|
||||
lst = list(range(6))
|
||||
random.shuffle(lst)
|
||||
for l in lst:
|
||||
lettername = bubbles.extend_name(l)
|
||||
@ -758,7 +758,7 @@ class BubPlayer(gamesrv.Player):
|
||||
icons = self.transformedicons[flip]
|
||||
if flip == 'fish':
|
||||
for dir in (-1, 1):
|
||||
for key, value in self.FISH_MODE_MAP.items():
|
||||
for key, value in list(self.FISH_MODE_MAP.items()):
|
||||
if value == 'black':
|
||||
flip = ''
|
||||
else:
|
||||
@ -768,7 +768,7 @@ class BubPlayer(gamesrv.Player):
|
||||
flip = flip or 'hflip'
|
||||
icons[key, dir] = images.sprget((flip, value))
|
||||
else:
|
||||
for key, value in self.iconnames.items():
|
||||
for key, value in list(self.iconnames.items()):
|
||||
icons[key] = images.sprget((flip, value))
|
||||
|
||||
def setplayername(self, name):
|
||||
@ -793,9 +793,9 @@ class BubPlayer(gamesrv.Player):
|
||||
self.loadicons(flip='')
|
||||
self.keepalive = None
|
||||
if self.points or self.letters:
|
||||
print 'New player continues at position #%d.' % n
|
||||
print('New player continues at position #%d.' % n)
|
||||
else:
|
||||
print 'New player is at position #%d.' % n
|
||||
print('New player is at position #%d.' % n)
|
||||
self.reset()
|
||||
self.key_left = 0
|
||||
self.key_right = 0
|
||||
@ -810,7 +810,7 @@ class BubPlayer(gamesrv.Player):
|
||||
#BubPlayer.LatestLetsGo = BubPlayer.FrameCounter
|
||||
|
||||
def playerleaves(self):
|
||||
print 'Closing position #%d.' % self.pn
|
||||
print('Closing position #%d.' % self.pn)
|
||||
self.savecaps()
|
||||
self.zarkoff()
|
||||
self.keepalive = time.time() + KEEPALIVE
|
||||
@ -831,7 +831,7 @@ class BubPlayer(gamesrv.Player):
|
||||
self.pcap = {}
|
||||
dragons = self.dragons
|
||||
if dragons:
|
||||
for key, minimum in Dragon.SAVE_CAP.items():
|
||||
for key, minimum in list(Dragon.SAVE_CAP.items()):
|
||||
self.pcap[key] = max(minimum,
|
||||
max([d.dcap[key] for d in dragons]))
|
||||
|
||||
@ -874,7 +874,7 @@ class BubPlayer(gamesrv.Player):
|
||||
else:
|
||||
break
|
||||
self.dragons.append(Dragon(self, x, y, dir))
|
||||
for key in self.pcap.keys():
|
||||
for key in list(self.pcap.keys()):
|
||||
if key not in ('teleport', 'jumpdown'):
|
||||
del self.pcap[key]
|
||||
|
||||
@ -1022,7 +1022,7 @@ def scoreboard(reset=0, inplace=0, compresslimittime=0):
|
||||
if reset:
|
||||
for p in BubPlayer.PlayerList:
|
||||
if inplace:
|
||||
for s in p.letters.values():
|
||||
for s in list(p.letters.values()):
|
||||
if isinstance(s, ActiveSprite):
|
||||
s.kill()
|
||||
if len(p.letters) == 6:
|
||||
@ -1155,7 +1155,7 @@ def scoreboard(reset=0, inplace=0, compresslimittime=0):
|
||||
lst.append((x0+9*CELL-ico.w, y0-ico.h+16, ico))
|
||||
y0 -= 5*HALFCELL
|
||||
for p in BubPlayer.PlayerList:
|
||||
for name, s in p.letters.items():
|
||||
for name, s in list(p.letters.items()):
|
||||
if isinstance(s, ActiveSprite) and s not in bubblesshown:
|
||||
p.letters[name] = 2
|
||||
s.kill()
|
||||
@ -1208,6 +1208,6 @@ def scoreboard(reset=0, inplace=0, compresslimittime=0):
|
||||
|
||||
# initialize global board data
|
||||
def reset_global_board_state():
|
||||
for key, value in BubPlayer.INIT_BOARD_CAP.items():
|
||||
for key, value in list(BubPlayer.INIT_BOARD_CAP.items()):
|
||||
setattr(BubPlayer, key, value)
|
||||
reset_global_board_state()
|
||||
|
1213
bubbob/player.py.bak
Normal file
1213
bubbob/player.py.bak
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import random
|
||||
import boards, images, gamesrv
|
||||
from boards import CELL, HALFCELL
|
||||
@ -168,7 +168,7 @@ def display(lines, timeleft, bgen=None, black=0):
|
||||
t = boards.normal_frame()
|
||||
else:
|
||||
try:
|
||||
t = bgen.next()
|
||||
t = next(bgen)
|
||||
except StopIteration:
|
||||
timeleft = 0.0
|
||||
break
|
||||
@ -180,13 +180,13 @@ def display(lines, timeleft, bgen=None, black=0):
|
||||
def ranking_picture(results, maximum, givepoints):
|
||||
if maximum is None:
|
||||
maximum = 0
|
||||
for n in results.values():
|
||||
for n in list(results.values()):
|
||||
maximum += n
|
||||
maximum = maximum or 1
|
||||
ranking = []
|
||||
teamrank = [0, 0]
|
||||
teamplayers = [[], []]
|
||||
for p, n in results.items():
|
||||
for p, n in list(results.items()):
|
||||
if p.team != -1:
|
||||
teamrank[p.team] += n
|
||||
teamplayers[p.team].append((n,p))
|
||||
@ -205,7 +205,7 @@ def ranking_picture(results, maximum, givepoints):
|
||||
|
||||
nbpoints = givepoints and ((len(ranking)+1)//2)*10000
|
||||
lines = []
|
||||
for (n, dummy, bubber), i in zip(ranking, range(len(ranking))):
|
||||
for (n, dummy, bubber), i in zip(ranking, list(range(len(ranking)))):
|
||||
pic = RPicture()
|
||||
if isinstance(bubber, list):
|
||||
fraction = (nbpoints//(10*len(bubber))) * 10
|
||||
@ -253,7 +253,7 @@ def screen_monster():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
catch = p.stats.get('monster', {})
|
||||
for p2, count in catch.items():
|
||||
for p2, count in list(catch.items()):
|
||||
if count:
|
||||
pairs.append((count, p, p2))
|
||||
random.shuffle(pairs)
|
||||
@ -277,7 +277,7 @@ def screen_catch():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
catch = p.stats.get('catch', {})
|
||||
for p2, count in catch.items():
|
||||
for p2, count in list(catch.items()):
|
||||
if count:
|
||||
pairs.append((count, p, p2))
|
||||
random.shuffle(pairs)
|
||||
@ -301,7 +301,7 @@ def screen_bonus():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
catch = p.stats.get('bonus', {})
|
||||
for p2, count in catch.items():
|
||||
for p2, count in list(catch.items()):
|
||||
if count > 1:
|
||||
pairs.append((count, p, p2))
|
||||
random.shuffle(pairs)
|
||||
|
391
bubbob/ranking.py.bak
Normal file
391
bubbob/ranking.py.bak
Normal file
@ -0,0 +1,391 @@
|
||||
from __future__ import generators
|
||||
import random
|
||||
import boards, images, gamesrv
|
||||
from boards import CELL, HALFCELL
|
||||
from mnstrmap import DigitsMisc, Flood, GreenAndBlue
|
||||
from bubbles import Bubble
|
||||
from bonuses import Points
|
||||
from player import BubPlayer
|
||||
|
||||
MARGIN = 22
|
||||
VMARGIN = 12
|
||||
|
||||
class RPicture:
|
||||
def __init__(self):
|
||||
self.icons = []
|
||||
def put(self, ico, dx=0, dy=0):
|
||||
self.icons.append((dx, dy, ico))
|
||||
def getsize(self):
|
||||
if self.icons:
|
||||
return (max([dx+ico.w for dx, dy, ico in self.icons]) + MARGIN,
|
||||
max([dy+ico.h for dx, dy, ico in self.icons]))
|
||||
else:
|
||||
return 0, 0
|
||||
def render(self, x, y):
|
||||
return [gamesrv.Sprite(ico, x+dx, y+dy) for dx, dy, ico in self.icons]
|
||||
|
||||
class RPoints:
|
||||
def __init__(self, bubber, nbpoints):
|
||||
self.bubber = bubber
|
||||
self.nbpoints = nbpoints
|
||||
def getsize(self):
|
||||
return 0, 0
|
||||
def render(self, x, y):
|
||||
Points(x, y, self.bubber.pn, self.nbpoints)
|
||||
return []
|
||||
|
||||
class RNumber(RPicture):
|
||||
map = {'%': 'percent'}
|
||||
for digit in range(10):
|
||||
map[str(digit)] = DigitsMisc.digits_white[digit]
|
||||
|
||||
def __init__(self, text):
|
||||
RPicture.__init__(self)
|
||||
x = 0
|
||||
for c in text:
|
||||
ico = images.sprget(self.map[c])
|
||||
self.put(ico, dx=x)
|
||||
x += ico.w+1
|
||||
|
||||
class RText(RPicture):
|
||||
def __init__(self, text, margin=VMARGIN):
|
||||
RPicture.__init__(self)
|
||||
x = 0
|
||||
for c in text:
|
||||
ico = images.sprcharacterget(c)
|
||||
if ico is not None:
|
||||
self.put(ico, dx=x)
|
||||
x += 7
|
||||
self.margin = margin
|
||||
def getsize(self):
|
||||
w, h = RPicture.getsize(self)
|
||||
h -= (VMARGIN-self.margin)
|
||||
return w, h
|
||||
|
||||
|
||||
def linesize(line):
|
||||
width = MARGIN
|
||||
height = 0
|
||||
for item in line:
|
||||
w, h = item.getsize()
|
||||
width += w
|
||||
if h > height:
|
||||
height = h
|
||||
return width, height
|
||||
|
||||
def display(lines, timeleft, bgen=None, black=0):
|
||||
waves = []
|
||||
if lines:
|
||||
totalwidth = 0
|
||||
totalheight = 0
|
||||
for line in lines:
|
||||
w, h = linesize(line)
|
||||
if w > totalwidth:
|
||||
totalwidth = w
|
||||
totalheight += h
|
||||
heightmargin = (boards.bheight-2*CELL - totalheight) // (len(lines)+1)
|
||||
if heightmargin > VMARGIN:
|
||||
heightmargin = VMARGIN
|
||||
totalheight += heightmargin * (len(lines)+1)
|
||||
|
||||
# size in number of CELLs
|
||||
cwidth = (totalwidth+CELL-1) // CELL
|
||||
cheight = (totalheight+CELL-1) // CELL
|
||||
|
||||
x0 = ((boards.width - cwidth) // 2) * CELL + HALFCELL
|
||||
y0 = ((boards.height - cheight) // 2) * CELL + HALFCELL
|
||||
extras = boards.curboard.sprites.setdefault('ranking', [])
|
||||
#while extras:
|
||||
# extras.pop().kill()
|
||||
# yield 0.12
|
||||
vspeed = -4
|
||||
while extras:
|
||||
nextras = []
|
||||
for s in extras:
|
||||
s.step(0, vspeed)
|
||||
if s.y + s.ico.h <= 0:
|
||||
s.kill()
|
||||
else:
|
||||
nextras.append(s)
|
||||
extras[:] = nextras
|
||||
yield 1
|
||||
vspeed -= 1
|
||||
|
||||
# draw the box filled with water
|
||||
original_y0 = y0
|
||||
wallicon = boards.patget((boards.curboard.num, 0, 0), images.KEYCOL)
|
||||
if black:
|
||||
fillicon = images.sprget('gameoverbkgnd')
|
||||
waveicons = [wallicon]
|
||||
y0 = boards.bheight+CELL
|
||||
else:
|
||||
fillicon = images.sprget(Flood.fill)
|
||||
waveicons = [images.sprget(n) for n in Flood.waves]
|
||||
for y in range(y0-CELL, y0+cheight*CELL+CELL, CELL):
|
||||
w = gamesrv.Sprite(wallicon, x0-CELL, y)
|
||||
extras.append(w)
|
||||
for x in range(x0, x0+cwidth*CELL, CELL):
|
||||
w = gamesrv.Sprite(wallicon, x, y0+cheight*CELL)
|
||||
extras.append(w)
|
||||
w = gamesrv.Sprite(waveicons[-1], x, y0-CELL)
|
||||
extras.append(w)
|
||||
waves.append(w)
|
||||
for y in range(y0, y0+cheight*CELL, CELL):
|
||||
w = gamesrv.Sprite(fillicon, x, y)
|
||||
extras.append(w)
|
||||
for y in range(y0-CELL, y0+cheight*CELL+CELL, CELL):
|
||||
w = gamesrv.Sprite(wallicon, x0+cwidth*CELL, y)
|
||||
extras.append(w)
|
||||
|
||||
# draw the individual items inside
|
||||
y = y0 + totalheight
|
||||
lines.reverse()
|
||||
for line in lines:
|
||||
linew, lineh = linesize(line)
|
||||
x = x0 + MARGIN
|
||||
y -= (lineh + heightmargin)
|
||||
for item in line:
|
||||
w, h = item.getsize()
|
||||
extras += item.render(x, y+(lineh-h)//2)
|
||||
x += w
|
||||
|
||||
vspeed = 0
|
||||
while y0 > original_y0:
|
||||
vspeed = max(vspeed-1, original_y0 - y0)
|
||||
y0 += vspeed
|
||||
for s in extras:
|
||||
s.step(0, vspeed)
|
||||
yield 1
|
||||
|
||||
while timeleft > 0.0:
|
||||
if waves:
|
||||
ico = waveicons.pop(0)
|
||||
waveicons.append(ico)
|
||||
for w in waves:
|
||||
w.seticon(ico)
|
||||
for i in range(2):
|
||||
if bgen is None:
|
||||
t = boards.normal_frame()
|
||||
else:
|
||||
try:
|
||||
t = bgen.next()
|
||||
except StopIteration:
|
||||
timeleft = 0.0
|
||||
break
|
||||
timeleft -= t
|
||||
yield t
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
def ranking_picture(results, maximum, givepoints):
|
||||
if maximum is None:
|
||||
maximum = 0
|
||||
for n in results.values():
|
||||
maximum += n
|
||||
maximum = maximum or 1
|
||||
ranking = []
|
||||
teamrank = [0, 0]
|
||||
teamplayers = [[], []]
|
||||
for p, n in results.items():
|
||||
if p.team != -1:
|
||||
teamrank[p.team] += n
|
||||
teamplayers[p.team].append((n,p))
|
||||
else:
|
||||
ranking.append((n, random.random(), p))
|
||||
teamplayers[0].sort()
|
||||
teamplayers[0].reverse()
|
||||
teamplayers[1].sort()
|
||||
teamplayers[1].reverse()
|
||||
if teamplayers[0] != []:
|
||||
ranking.append((teamrank[0], random.random(), teamplayers[0]))
|
||||
if teamplayers[1] != []:
|
||||
ranking.append((teamrank[1], random.random(), teamplayers[1]))
|
||||
ranking.sort()
|
||||
ranking.reverse()
|
||||
|
||||
nbpoints = givepoints and ((len(ranking)+1)//2)*10000
|
||||
lines = []
|
||||
for (n, dummy, bubber), i in zip(ranking, range(len(ranking))):
|
||||
pic = RPicture()
|
||||
if isinstance(bubber, list):
|
||||
fraction = (nbpoints//(10*len(bubber))) * 10
|
||||
total = fraction * len(bubber)
|
||||
for n, bub in bubber:
|
||||
bub.givepoints(fraction)
|
||||
bubber = bubber[0][1]
|
||||
pic.put(images.sprget(('hat', bubber.team)))
|
||||
else:
|
||||
if len(ranking) == 1:
|
||||
icon = 0
|
||||
elif i == 0:
|
||||
icon = 10
|
||||
elif i == len(ranking) - 1:
|
||||
icon = 9
|
||||
else:
|
||||
icon = 0
|
||||
pic.put(bubber.icons[icon, +1])
|
||||
total = 0
|
||||
line = []
|
||||
if nbpoints > 0:
|
||||
line.append(RPoints(bubber, nbpoints))
|
||||
bubber.givepoints(nbpoints - total)
|
||||
nbpoints -= 10000
|
||||
line.append(pic)
|
||||
line.append(RNumber(str(int(n*100.00001/maximum)) + '%'))
|
||||
lines.append(line)
|
||||
return lines
|
||||
|
||||
|
||||
def just_wait():
|
||||
while 1:
|
||||
yield 2
|
||||
|
||||
def screen_scores():
|
||||
results = {}
|
||||
for p in BubPlayer.PlayerList:
|
||||
if p.points:
|
||||
results[p] = p.points
|
||||
lines = ranking_picture(results, None, 0)
|
||||
lines.insert(0, [RText(" THE END")])
|
||||
return lines
|
||||
|
||||
def screen_monster():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
catch = p.stats.get('monster', {})
|
||||
for p2, count in catch.items():
|
||||
if count:
|
||||
pairs.append((count, p, p2))
|
||||
random.shuffle(pairs)
|
||||
pairs.sort()
|
||||
pairs.reverse()
|
||||
del pairs[5:]
|
||||
lines = []
|
||||
if pairs:
|
||||
lines.append([RText('Best Monster Bubblers')])
|
||||
for count, p, p2 in pairs:
|
||||
pic = RPicture()
|
||||
pic.put(p.icons[4,+1], 0, 6)
|
||||
pic.put(images.sprget(GreenAndBlue.new_bubbles[p.pn][1]), 31, 6)
|
||||
pic.put(images.sprget(GreenAndBlue.new_bubbles[p.pn][3]), 69, 6)
|
||||
pic.put(images.sprget(GreenAndBlue.normal_bubbles[p.pn][0]), 101)
|
||||
pic.put(images.sprget(p2), 101)
|
||||
lines.append([pic, RNumber(str(count))])
|
||||
return lines
|
||||
|
||||
def screen_catch():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
catch = p.stats.get('catch', {})
|
||||
for p2, count in catch.items():
|
||||
if count:
|
||||
pairs.append((count, p, p2))
|
||||
random.shuffle(pairs)
|
||||
pairs.sort()
|
||||
pairs.reverse()
|
||||
del pairs[5:]
|
||||
lines = []
|
||||
if pairs:
|
||||
lines.append([RText('Best Dragon Bubblers')])
|
||||
for count, p, p2 in pairs:
|
||||
pic = RPicture()
|
||||
pic.put(p.icons[4,+1], 0, 6)
|
||||
pic.put(images.sprget(GreenAndBlue.new_bubbles[p.pn][1]), 31, 6)
|
||||
pic.put(images.sprget(GreenAndBlue.new_bubbles[p.pn][3]), 69, 6)
|
||||
pic.put(images.sprget(GreenAndBlue.normal_bubbles[p2.pn][0]), 101)
|
||||
pic.put(images.sprget(('eyes', 0,0)), 101)
|
||||
lines.append([pic, RNumber(str(count))])
|
||||
return lines
|
||||
|
||||
def screen_bonus():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
catch = p.stats.get('bonus', {})
|
||||
for p2, count in catch.items():
|
||||
if count > 1:
|
||||
pairs.append((count, p, p2))
|
||||
random.shuffle(pairs)
|
||||
pairs.sort()
|
||||
pairs.reverse()
|
||||
seen = {}
|
||||
npairs = []
|
||||
for count, p, p2 in pairs:
|
||||
if p2 not in seen:
|
||||
npairs.append((count, p, p2))
|
||||
seen[p2] = 1
|
||||
pairs = npairs
|
||||
del pairs[5:]
|
||||
lines = []
|
||||
if pairs:
|
||||
lines.append([RText('Best Bonus Catchers')])
|
||||
for count, p, p2 in pairs:
|
||||
pic = RPicture()
|
||||
pic.put(p.icons[1,+1], 0)
|
||||
pic.put(images.sprget(p2), 44)
|
||||
lines.append([pic, RNumber(str(count))])
|
||||
return lines
|
||||
|
||||
def screen_bubble():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
count = p.stats['bubble']
|
||||
if count:
|
||||
pairs.append((count, p))
|
||||
random.shuffle(pairs)
|
||||
pairs.sort()
|
||||
pairs.reverse()
|
||||
del pairs[5:]
|
||||
lines = []
|
||||
if pairs:
|
||||
lines.append([RText('Best Bubble Exploders')])
|
||||
for count, p in pairs:
|
||||
pic = RPicture()
|
||||
pic.put(p.icons[1,+1], 0)
|
||||
pic.put(images.sprget(Bubble.exploding_bubbles[1]), 27)
|
||||
lines.append([pic, RNumber(str(count))])
|
||||
return lines
|
||||
|
||||
def screen_die():
|
||||
pairs = []
|
||||
for p in BubPlayer.PlayerList:
|
||||
count = p.stats['die']
|
||||
if count:
|
||||
pairs.append((count, p))
|
||||
random.shuffle(pairs)
|
||||
pairs.sort()
|
||||
pairs.reverse()
|
||||
del pairs[5:]
|
||||
lines = []
|
||||
if pairs:
|
||||
lines.append([RText('Top Deaths')])
|
||||
n = 0
|
||||
for count, p in pairs:
|
||||
pic = RPicture()
|
||||
pic.put(p.icons[6+(n%3),+1], 0)
|
||||
lines.append([pic, RNumber(str(count))])
|
||||
n += 1
|
||||
return lines
|
||||
|
||||
def screen_authors():
|
||||
return [
|
||||
[RText('programming', 6)],
|
||||
[RText(' Armin & Odie')],
|
||||
[RText('art', 6)],
|
||||
[RText(' David Gowers, based on McSebi')],
|
||||
[RText('levels', 6)],
|
||||
[RText(' Gio & Odie & MS & Armin')],
|
||||
[RText('special thanks', 6)],
|
||||
[RText(' Odie & Brachamutanda')],
|
||||
[RText('beta-testers', 6)],
|
||||
[RText(' IMA Connection')],
|
||||
]
|
||||
|
||||
def game_over():
|
||||
while 1:
|
||||
for screen in [screen_scores, screen_monster, screen_catch,
|
||||
screen_bonus, screen_bubble, screen_die,
|
||||
screen_authors]:
|
||||
lines = screen()
|
||||
if lines:
|
||||
for t in display(lines, 300, just_wait(), 1):
|
||||
yield t
|
@ -22,7 +22,7 @@ while idx < len(sys.argv):
|
||||
if arg == '-seed':
|
||||
arg = sys.argv[idx]
|
||||
idx += 1
|
||||
print "# Using seed: " + arg + "\n"
|
||||
print("# Using seed: " + arg + "\n")
|
||||
random.seed(arg)
|
||||
|
||||
def printlvl(level):
|
||||
@ -41,7 +41,7 @@ def printlvl(level):
|
||||
else:
|
||||
dir = 'R'
|
||||
s = dir + m.cls.__name__
|
||||
if tmpmons.has_key(s):
|
||||
if s in tmpmons:
|
||||
tmpmons[s].append(wm)
|
||||
else:
|
||||
tmpmons[s] = [wm]
|
||||
@ -61,7 +61,7 @@ def printlvl(level):
|
||||
for x in range(0,level.WIDTH):
|
||||
wm = level.wmap[y][x]
|
||||
if wm >= 'a':
|
||||
if monconv.has_key(wm):
|
||||
if wm in monconv:
|
||||
walls += monconv[wm]
|
||||
else:
|
||||
walls += '?'
|
||||
@ -84,42 +84,42 @@ def printlvl(level):
|
||||
winds += "\n"
|
||||
|
||||
for m in mons:
|
||||
print " " + m + " = " + mons[m]
|
||||
print(" " + m + " = " + mons[m])
|
||||
|
||||
if level.letter:
|
||||
print " letter = 1"
|
||||
print(" letter = 1")
|
||||
if level.fire:
|
||||
print " fire = 1"
|
||||
print(" fire = 1")
|
||||
if level.lightning:
|
||||
print " lightning = 1"
|
||||
print(" lightning = 1")
|
||||
if level.water:
|
||||
print " water = 1"
|
||||
print(" water = 1")
|
||||
if level.top:
|
||||
print " top = 1"
|
||||
print(" top = 1")
|
||||
|
||||
print " walls = \"\"\"\n" + walls + "\"\"\""
|
||||
print " winds = \"\"\"\n" + winds + "\"\"\""
|
||||
print(" walls = \"\"\"\n" + walls + "\"\"\"")
|
||||
print(" winds = \"\"\"\n" + winds + "\"\"\"")
|
||||
|
||||
|
||||
for i in range(n_lvls):
|
||||
print """
|
||||
print("""
|
||||
import boarddef, mnstrmap, random
|
||||
from boarddef import LNasty, LMonky, LGhosty, LFlappy
|
||||
from boarddef import LSpringy, LOrcy, LGramy, LBlitzy
|
||||
from boarddef import RNasty, RMonky, RGhosty, RFlappy
|
||||
from boarddef import RSpringy, ROrcy, RGramy, RBlitzy
|
||||
"""
|
||||
""")
|
||||
|
||||
d = {'__name__': 'RandomLevels'}
|
||||
execfile('levels/RandomLevels.py', d)
|
||||
exec(compile(open('levels/RandomLevels.py', "rb").read(), 'levels/RandomLevels.py', 'exec'), d)
|
||||
|
||||
for i, Lvl in enumerate(d['GenerateLevels']()):
|
||||
level = Lvl(i)
|
||||
|
||||
if level.monsters:
|
||||
print "\n\nclass level%02d(boarddef.Level):" % (i+1)
|
||||
print("\n\nclass level%02d(boarddef.Level):" % (i+1))
|
||||
else:
|
||||
print "\n\nclass levelFinal(boarddef.Level):"
|
||||
print("\n\nclass levelFinal(boarddef.Level):")
|
||||
|
||||
printlvl(level)
|
||||
print
|
||||
print()
|
||||
|
125
bubbob/save_rnglevel.py.bak
Normal file
125
bubbob/save_rnglevel.py.bak
Normal file
@ -0,0 +1,125 @@
|
||||
#
|
||||
# This script outputs the random levels in a format you can
|
||||
# save into a file in the levels-directory and bub'n'bros
|
||||
# will be able to use it.
|
||||
#
|
||||
# this accepts the following parameters:
|
||||
# -seed N use random seed N for the generation
|
||||
#
|
||||
|
||||
import sys
|
||||
import random
|
||||
import string
|
||||
sys.path.append('..')
|
||||
sys.path.append('../common')
|
||||
|
||||
n_lvls = 1
|
||||
|
||||
idx = 0
|
||||
while idx < len(sys.argv):
|
||||
arg = sys.argv[idx]
|
||||
idx += 1
|
||||
if arg == '-seed':
|
||||
arg = sys.argv[idx]
|
||||
idx += 1
|
||||
print "# Using seed: " + arg + "\n"
|
||||
random.seed(arg)
|
||||
|
||||
def printlvl(level):
|
||||
mons = {}
|
||||
monconv = {}
|
||||
tmpmons = {}
|
||||
|
||||
# Populate monster tables
|
||||
for y in range(0,level.HEIGHT):
|
||||
for x in range(0,level.WIDTH):
|
||||
wm = level.wmap[y][x]
|
||||
if wm >= 'a':
|
||||
m = getattr(level, wm)
|
||||
if m.dir == 1:
|
||||
dir = 'L'
|
||||
else:
|
||||
dir = 'R'
|
||||
s = dir + m.cls.__name__
|
||||
if tmpmons.has_key(s):
|
||||
tmpmons[s].append(wm)
|
||||
else:
|
||||
tmpmons[s] = [wm]
|
||||
# Build monster character conversion tables
|
||||
lettr = 'a'
|
||||
for m in tmpmons:
|
||||
for n in tmpmons[m]:
|
||||
monconv[n] = lettr
|
||||
mons[lettr] = m
|
||||
lettr = chr(ord(lettr) + 1)
|
||||
|
||||
# Build walls, replacing monsters from mons[]
|
||||
walls = ""
|
||||
|
||||
for y in range(0,level.HEIGHT-1):
|
||||
walls += "##"
|
||||
for x in range(0,level.WIDTH):
|
||||
wm = level.wmap[y][x]
|
||||
if wm >= 'a':
|
||||
if monconv.has_key(wm):
|
||||
walls += monconv[wm]
|
||||
else:
|
||||
walls += '?'
|
||||
else:
|
||||
walls += wm
|
||||
walls += "##\n"
|
||||
walls += "##"
|
||||
for x in range(0,level.WIDTH):
|
||||
if level.wmap[0][x] == '#' or level.wmap[level.HEIGHT-1][x] == '#':
|
||||
walls += "#"
|
||||
else:
|
||||
walls += " "
|
||||
walls += "##\n"
|
||||
|
||||
# Build winds
|
||||
winds = ""
|
||||
for y in range(0,level.HEIGHT):
|
||||
for x in range(0,level.WIDTH+4):
|
||||
winds += level.winds[y][x]
|
||||
winds += "\n"
|
||||
|
||||
for m in mons:
|
||||
print " " + m + " = " + mons[m]
|
||||
|
||||
if level.letter:
|
||||
print " letter = 1"
|
||||
if level.fire:
|
||||
print " fire = 1"
|
||||
if level.lightning:
|
||||
print " lightning = 1"
|
||||
if level.water:
|
||||
print " water = 1"
|
||||
if level.top:
|
||||
print " top = 1"
|
||||
|
||||
print " walls = \"\"\"\n" + walls + "\"\"\""
|
||||
print " winds = \"\"\"\n" + winds + "\"\"\""
|
||||
|
||||
|
||||
for i in range(n_lvls):
|
||||
print """
|
||||
import boarddef, mnstrmap, random
|
||||
from boarddef import LNasty, LMonky, LGhosty, LFlappy
|
||||
from boarddef import LSpringy, LOrcy, LGramy, LBlitzy
|
||||
from boarddef import RNasty, RMonky, RGhosty, RFlappy
|
||||
from boarddef import RSpringy, ROrcy, RGramy, RBlitzy
|
||||
"""
|
||||
|
||||
d = {'__name__': 'RandomLevels'}
|
||||
execfile('levels/RandomLevels.py', d)
|
||||
|
||||
for i, Lvl in enumerate(d['GenerateLevels']()):
|
||||
level = Lvl(i)
|
||||
|
||||
if level.monsters:
|
||||
print "\n\nclass level%02d(boarddef.Level):" % (i+1)
|
||||
else:
|
||||
print "\n\nclass levelFinal(boarddef.Level):"
|
||||
|
||||
printlvl(level)
|
||||
print
|
@ -27,7 +27,7 @@ def copy_custom_instance(x, memo):
|
||||
except KeyError:
|
||||
y = x.inst_build()
|
||||
memo[id(x)] = y
|
||||
for key, value in x.__dict__.items():
|
||||
for key, value in list(x.__dict__.items()):
|
||||
y.__dict__[key] = copyrec(value, memo)
|
||||
return y
|
||||
|
||||
@ -50,25 +50,25 @@ def copy_dict(x, memo):
|
||||
except KeyError:
|
||||
y = {}
|
||||
memo[id(x)] = y
|
||||
for key, value in x.items():
|
||||
for key, value in list(x.items()):
|
||||
y[copyrec(key, memo)] = copyrec(value, memo)
|
||||
return y
|
||||
|
||||
def copy_function(x, memo):
|
||||
if not x.func_defaults:
|
||||
if not x.__defaults__:
|
||||
return x # not copied
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
y = types.FunctionType(x.func_code, x.func_globals, x.func_name)
|
||||
y = types.FunctionType(x.__code__, x.__globals__, x.__name__)
|
||||
memo[id(x)] = y
|
||||
y.func_defaults = copyrec(x.func_defaults, memo)
|
||||
y.__defaults__ = copyrec(x.__defaults__, memo)
|
||||
return y
|
||||
|
||||
def copy_method(x, memo):
|
||||
return types.MethodType(copyrec(x.im_func, memo),
|
||||
copyrec(x.im_self, memo),
|
||||
x.im_class)
|
||||
return types.MethodType(copyrec(x.__func__, memo),
|
||||
copyrec(x.__self__, memo),
|
||||
x.__self__.__class__)
|
||||
|
||||
def copy_generator(x, memo):
|
||||
try:
|
||||
|
135
bubbob/statesaver.py.bak
Normal file
135
bubbob/statesaver.py.bak
Normal file
@ -0,0 +1,135 @@
|
||||
"""
|
||||
A pure Python implementation of statesaver.c that runs on top of PyPy.
|
||||
See description in statesaver.c.
|
||||
Difference: this supports new-style instances too.
|
||||
Use statesaver.standard_build() as the inst_build() if you want.
|
||||
"""
|
||||
|
||||
from _pickle_support import generator_new
|
||||
import types
|
||||
|
||||
def standard_build(self):
|
||||
if type(self) is types.InstanceType:
|
||||
# old-style instance
|
||||
return types.InstanceType(self.__class__)
|
||||
else:
|
||||
# new-style instance
|
||||
return type(self).__new__(type(self))
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
def not_copied(x, memo):
|
||||
return x
|
||||
|
||||
def copy_custom_instance(x, memo):
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
y = x.inst_build()
|
||||
memo[id(x)] = y
|
||||
for key, value in x.__dict__.items():
|
||||
y.__dict__[key] = copyrec(value, memo)
|
||||
return y
|
||||
|
||||
def copy_tuple(x, memo):
|
||||
return tuple([copyrec(item, memo) for item in x])
|
||||
|
||||
def copy_list(x, memo):
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
y = []
|
||||
memo[id(x)] = y
|
||||
for item in x:
|
||||
y.append(copyrec(item, memo))
|
||||
return y
|
||||
|
||||
def copy_dict(x, memo):
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
y = {}
|
||||
memo[id(x)] = y
|
||||
for key, value in x.items():
|
||||
y[copyrec(key, memo)] = copyrec(value, memo)
|
||||
return y
|
||||
|
||||
def copy_function(x, memo):
|
||||
if not x.func_defaults:
|
||||
return x # not copied
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
y = types.FunctionType(x.func_code, x.func_globals, x.func_name)
|
||||
memo[id(x)] = y
|
||||
y.func_defaults = copyrec(x.func_defaults, memo)
|
||||
return y
|
||||
|
||||
def copy_method(x, memo):
|
||||
return types.MethodType(copyrec(x.im_func, memo),
|
||||
copyrec(x.im_self, memo),
|
||||
x.im_class)
|
||||
|
||||
def copy_generator(x, memo):
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
y = generator_new(copyrec(x.gi_frame, memo), x.gi_running)
|
||||
memo[id(x)] = y
|
||||
return y
|
||||
|
||||
def copy_frame(x, memo):
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
frame_new, args, state = x.__reduce__()
|
||||
y = frame_new(*args)
|
||||
memo[id(x)] = y
|
||||
newstate = []
|
||||
for item in state:
|
||||
if not (item is x.f_globals or item is x.f_builtins):
|
||||
item = copyrec(item, memo)
|
||||
newstate.append(item)
|
||||
y.__setstate__(newstate)
|
||||
return y
|
||||
|
||||
def copy_seqiter(x, memo):
|
||||
try:
|
||||
return memo[id(x)]
|
||||
except KeyError:
|
||||
# XXX self-recursion is not correctly handled here
|
||||
seqiter_new, args = x.__reduce__()
|
||||
args = [copyrec(item, memo) for item in args]
|
||||
y = seqiter_new(*args)
|
||||
memo[id(x)] = y
|
||||
return y
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
type_handlers = {tuple: copy_tuple,
|
||||
list: copy_list,
|
||||
dict: copy_dict,
|
||||
types.FunctionType: copy_function,
|
||||
types.MethodType: copy_method,
|
||||
types.GeneratorType: copy_generator,
|
||||
types.FrameType: copy_frame,
|
||||
type(iter([])): copy_seqiter,
|
||||
}
|
||||
|
||||
def no_handler_found(x, memo):
|
||||
if hasattr(x, '__dict__') and hasattr(x.__class__, 'inst_build'):
|
||||
handler = copy_custom_instance
|
||||
else:
|
||||
handler = not_copied
|
||||
type_handlers[x.__class__] = handler
|
||||
return handler(x, memo)
|
||||
|
||||
def copyrec(x, memo):
|
||||
try:
|
||||
cls = x.__class__
|
||||
except AttributeError:
|
||||
return x # 'cls' is likely an old-style class object
|
||||
return type_handlers.get(cls, no_handler_found)(x, memo)
|
||||
|
||||
def copy(x):
|
||||
return copyrec(x, {})
|
@ -31,12 +31,12 @@ while idx < len(sys.argv):
|
||||
if arg == '-seed':
|
||||
arg = sys.argv[idx]
|
||||
idx += 1
|
||||
print "Using seed: " + arg + "\n"
|
||||
print("Using seed: " + arg + "\n")
|
||||
random.seed(arg)
|
||||
|
||||
def printlvl(level):
|
||||
if show_lvl:
|
||||
print "\n\n"
|
||||
print("\n\n")
|
||||
for y in range(level.HEIGHT):
|
||||
str = ""
|
||||
if show_lvl & 1:
|
||||
@ -45,12 +45,12 @@ def printlvl(level):
|
||||
if str:
|
||||
str += " | "
|
||||
str += level.winds[y]
|
||||
print str
|
||||
print(str)
|
||||
|
||||
for i in range(n_lvls):
|
||||
print '%4d:' % i,
|
||||
print('%4d:' % i, end=' ')
|
||||
d = {'__name__': 'RandomLevels'}
|
||||
execfile('levels/RandomLevels.py', d)
|
||||
exec(compile(open('levels/RandomLevels.py', "rb").read(), 'levels/RandomLevels.py', 'exec'), d)
|
||||
for i, Lvl in enumerate(d['GenerateLevels']()):
|
||||
level = Lvl(i)
|
||||
printlvl(level)
|
||||
@ -60,5 +60,5 @@ for i in range(n_lvls):
|
||||
break
|
||||
else:
|
||||
for line in level.walls:
|
||||
print line
|
||||
print(line)
|
||||
raise AssertionError("full height wall in column %d" % x)
|
||||
|
64
bubbob/test_rnglevel.py.bak
Normal file
64
bubbob/test_rnglevel.py.bak
Normal file
@ -0,0 +1,64 @@
|
||||
#
|
||||
# This test generates 100 times 25 random levels and checks
|
||||
# that it doesn't crash, and that it gives levels that are
|
||||
# possible (in the limited sense of not having any full-
|
||||
# column walls)
|
||||
#
|
||||
# this test accepts the following parameters:
|
||||
# -wall show the level layout
|
||||
# -wind show the level wind pattern
|
||||
# -seed N use random seed N for the generation
|
||||
#
|
||||
|
||||
import sys
|
||||
import random
|
||||
sys.path.append('..')
|
||||
sys.path.append('../common')
|
||||
|
||||
n_lvls = 100
|
||||
show_lvl = 0
|
||||
|
||||
idx = 0
|
||||
while idx < len(sys.argv):
|
||||
arg = sys.argv[idx]
|
||||
idx += 1
|
||||
if arg == '-wall':
|
||||
show_lvl |= 1
|
||||
n_lvls = 2
|
||||
if arg == '-wind':
|
||||
show_lvl |= 2
|
||||
n_lvls = 2
|
||||
if arg == '-seed':
|
||||
arg = sys.argv[idx]
|
||||
idx += 1
|
||||
print "Using seed: " + arg + "\n"
|
||||
random.seed(arg)
|
||||
|
||||
def printlvl(level):
|
||||
if show_lvl:
|
||||
print "\n\n"
|
||||
for y in range(level.HEIGHT):
|
||||
str = ""
|
||||
if show_lvl & 1:
|
||||
str = level.walls[y]
|
||||
if show_lvl & 2:
|
||||
if str:
|
||||
str += " | "
|
||||
str += level.winds[y]
|
||||
print str
|
||||
|
||||
for i in range(n_lvls):
|
||||
print '%4d:' % i,
|
||||
d = {'__name__': 'RandomLevels'}
|
||||
execfile('levels/RandomLevels.py', d)
|
||||
for i, Lvl in enumerate(d['GenerateLevels']()):
|
||||
level = Lvl(i)
|
||||
printlvl(level)
|
||||
for x in range(2, level.width-2):
|
||||
for y in range(0, level.height):
|
||||
if level.walls[y][x] == ' ':
|
||||
break
|
||||
else:
|
||||
for line in level.walls:
|
||||
print line
|
||||
raise AssertionError("full height wall in column %d" % x)
|
@ -68,32 +68,32 @@ def test_generator():
|
||||
yield lst.pop()
|
||||
yield lst.pop()
|
||||
g = gfunc()
|
||||
assert g.next() == 6
|
||||
assert next(g) == 6
|
||||
g1 = statesaver.copy(g)
|
||||
assert g.next() == 5
|
||||
py.test.raises(StopIteration, g.next)
|
||||
assert g1.next() == 5
|
||||
py.test.raises(StopIteration, g1.next)
|
||||
assert next(g) == 5
|
||||
py.test.raises(StopIteration, g.__next__)
|
||||
assert next(g1) == 5
|
||||
py.test.raises(StopIteration, g1.__next__)
|
||||
|
||||
def test_exhausted_gen():
|
||||
def gfunc():
|
||||
yield 5
|
||||
g = gfunc()
|
||||
for i in g:
|
||||
print i
|
||||
print(i)
|
||||
g1 = statesaver.copy(g)
|
||||
assert iter(g1) is g1
|
||||
py.test.raises(StopIteration, g1.next)
|
||||
py.test.raises(StopIteration, g1.__next__)
|
||||
g2 = statesaver.copy(g1)
|
||||
assert iter(g2) is g2
|
||||
py.test.raises(StopIteration, g2.next)
|
||||
py.test.raises(StopIteration, g2.__next__)
|
||||
|
||||
def test_seqiter():
|
||||
from UserList import UserList
|
||||
from collections import UserList
|
||||
seq = UserList([2, 4, 6, 8])
|
||||
it = iter(seq)
|
||||
assert it.next() == 2
|
||||
assert it.next() == 4
|
||||
assert next(it) == 2
|
||||
assert next(it) == 4
|
||||
it1 = statesaver.copy(it)
|
||||
assert list(it) == [6, 8]
|
||||
assert list(it1) == [6, 8]
|
||||
@ -101,8 +101,8 @@ def test_seqiter():
|
||||
def test_tupleiter():
|
||||
tup = (2, 4, 6, 8)
|
||||
it = iter(tup)
|
||||
assert it.next() == 2
|
||||
assert it.next() == 4
|
||||
assert next(it) == 2
|
||||
assert next(it) == 4
|
||||
it1 = statesaver.copy(it)
|
||||
assert list(it) == [6, 8]
|
||||
assert list(it1) == [6, 8]
|
||||
@ -110,8 +110,8 @@ def test_tupleiter():
|
||||
def test_listiter():
|
||||
lst = [2, 4, 6, 8]
|
||||
it = iter(lst)
|
||||
assert it.next() == 2
|
||||
assert it.next() == 4
|
||||
assert next(it) == 2
|
||||
assert next(it) == 4
|
||||
it1 = statesaver.copy(it)
|
||||
lst.append(10)
|
||||
assert list(it) == [6, 8, 10]
|
||||
@ -120,8 +120,8 @@ def test_listiter():
|
||||
def test_stringiter():
|
||||
s = "hello"
|
||||
it = iter(s)
|
||||
assert it.next() == 'h'
|
||||
assert it.next() == 'e'
|
||||
assert next(it) == 'h'
|
||||
assert next(it) == 'e'
|
||||
it1 = statesaver.copy(it)
|
||||
assert list(it) == ['l', 'l', 'o']
|
||||
assert list(it1) == ['l', 'l', 'o']
|
||||
|
127
bubbob/test_statesaver.py.bak
Normal file
127
bubbob/test_statesaver.py.bak
Normal file
@ -0,0 +1,127 @@
|
||||
import py
|
||||
import statesaver
|
||||
import new
|
||||
|
||||
def test_list():
|
||||
lst = [None, 12, "hello", 3.4, ("foo", (), [])]
|
||||
lst1 = statesaver.copy(lst)
|
||||
assert lst1 == lst
|
||||
assert lst1 is not lst
|
||||
assert lst1[-1][-1] is not lst[-1][-1]
|
||||
|
||||
def test_dict():
|
||||
dct = {1: "hi", 2: {}}
|
||||
dct1 = statesaver.copy(dct)
|
||||
assert dct1 == dct
|
||||
assert dct1 is not dct
|
||||
assert dct1[2] is not dct[2]
|
||||
|
||||
def test_instance():
|
||||
class Foo:
|
||||
def inst_build(self):
|
||||
return Bar()
|
||||
class Bar:
|
||||
pass
|
||||
x = Foo()
|
||||
x.attr = [1, 2, 3]
|
||||
y = statesaver.copy(x)
|
||||
assert y.__class__ is Bar
|
||||
assert y.attr == [1, 2, 3]
|
||||
assert y.attr is not x.attr
|
||||
|
||||
glob = 2
|
||||
def test_function():
|
||||
# XXX closures not supported
|
||||
def func(x, y=[]):
|
||||
assert glob == 2
|
||||
y.append(x)
|
||||
return y
|
||||
l = func(5)
|
||||
l = func(6)
|
||||
assert l == [5, 6]
|
||||
func1 = statesaver.copy(func)
|
||||
l = func(7)
|
||||
l = func(8)
|
||||
assert l == [5, 6, 7, 8]
|
||||
l = func1(9)
|
||||
l = func1(10)
|
||||
assert l == [5, 6, 9, 10]
|
||||
|
||||
def test_method():
|
||||
def func(x, y=[]):
|
||||
assert glob == 2
|
||||
y.append(x)
|
||||
return y
|
||||
m = new.instancemethod(func, {})
|
||||
assert m() == [{}]
|
||||
m1 = statesaver.copy(m)
|
||||
assert m() == [{}, {}]
|
||||
assert m() == [{}, {}, {}]
|
||||
assert m1() == [{}, {}]
|
||||
assert m1() == [{}, {}, {}]
|
||||
l = m1()
|
||||
assert l[0] is l[1] is l[2] is l[3]
|
||||
|
||||
def test_generator():
|
||||
def gfunc():
|
||||
lst = [5, 6]
|
||||
yield lst.pop()
|
||||
yield lst.pop()
|
||||
g = gfunc()
|
||||
assert g.next() == 6
|
||||
g1 = statesaver.copy(g)
|
||||
assert g.next() == 5
|
||||
py.test.raises(StopIteration, g.next)
|
||||
assert g1.next() == 5
|
||||
py.test.raises(StopIteration, g1.next)
|
||||
|
||||
def test_exhausted_gen():
|
||||
def gfunc():
|
||||
yield 5
|
||||
g = gfunc()
|
||||
for i in g:
|
||||
print i
|
||||
g1 = statesaver.copy(g)
|
||||
assert iter(g1) is g1
|
||||
py.test.raises(StopIteration, g1.next)
|
||||
g2 = statesaver.copy(g1)
|
||||
assert iter(g2) is g2
|
||||
py.test.raises(StopIteration, g2.next)
|
||||
|
||||
def test_seqiter():
|
||||
from UserList import UserList
|
||||
seq = UserList([2, 4, 6, 8])
|
||||
it = iter(seq)
|
||||
assert it.next() == 2
|
||||
assert it.next() == 4
|
||||
it1 = statesaver.copy(it)
|
||||
assert list(it) == [6, 8]
|
||||
assert list(it1) == [6, 8]
|
||||
|
||||
def test_tupleiter():
|
||||
tup = (2, 4, 6, 8)
|
||||
it = iter(tup)
|
||||
assert it.next() == 2
|
||||
assert it.next() == 4
|
||||
it1 = statesaver.copy(it)
|
||||
assert list(it) == [6, 8]
|
||||
assert list(it1) == [6, 8]
|
||||
|
||||
def test_listiter():
|
||||
lst = [2, 4, 6, 8]
|
||||
it = iter(lst)
|
||||
assert it.next() == 2
|
||||
assert it.next() == 4
|
||||
it1 = statesaver.copy(it)
|
||||
lst.append(10)
|
||||
assert list(it) == [6, 8, 10]
|
||||
assert list(it1) == [6, 8]
|
||||
|
||||
def test_stringiter():
|
||||
s = "hello"
|
||||
it = iter(s)
|
||||
assert it.next() == 'h'
|
||||
assert it.next() == 'e'
|
||||
it1 = statesaver.copy(it)
|
||||
assert list(it) == ['l', 'l', 'o']
|
||||
assert list(it1) == ['l', 'l', 'o']
|
BIN
common/__pycache__/gamesrv.cpython-39.pyc
Normal file
BIN
common/__pycache__/gamesrv.cpython-39.pyc
Normal file
Binary file not shown.
BIN
common/__pycache__/msgstruct.cpython-39.pyc
Normal file
BIN
common/__pycache__/msgstruct.cpython-39.pyc
Normal file
Binary file not shown.
@ -1,8 +1,8 @@
|
||||
from __future__ import generators
|
||||
|
||||
from socket import *
|
||||
from select import select
|
||||
from struct import pack, unpack
|
||||
import zlib, os, random, struct, md5, sys
|
||||
import zlib, os, random, struct, hashlib, sys
|
||||
from time import time, ctime
|
||||
from msgstruct import *
|
||||
from errno import EWOULDBLOCK
|
||||
@ -37,7 +37,7 @@ class Icon:
|
||||
framemsgappend(self.msgdef)
|
||||
|
||||
def getimage(self):
|
||||
import pixmap
|
||||
from . import pixmap
|
||||
bitmap, x, y = self.origin
|
||||
image = pixmap.decodepixmap(bitmap.read())
|
||||
return pixmap.cropimage(image, (x, y, self.w, self.h))
|
||||
@ -86,7 +86,7 @@ class DataChunk:
|
||||
client.msgl.append(msgdef)
|
||||
|
||||
def getmd5def(self, fileid, data, offset=0):
|
||||
checksum = md5.new(data).digest()
|
||||
checksum = hashlib.md5.new(data).digest()
|
||||
return message(MSG_MD5_FILE, fileid, protofilepath(self.filename),
|
||||
offset, len(data), checksum)
|
||||
|
||||
@ -111,7 +111,7 @@ class Bitmap(DataChunk):
|
||||
return ico
|
||||
|
||||
def geticonlist(self, w, h, count):
|
||||
return map(lambda i, fn=self.geticon, w=w, h=h: fn(i*w, 0, w, h), range(count))
|
||||
return list(map(lambda i, fn=self.geticon, w=w, h=h: fn(i*w, 0, w, h), list(range(count))))
|
||||
|
||||
def getmsgdef(self, data):
|
||||
if self.colorkey is not None:
|
||||
@ -121,7 +121,7 @@ class Bitmap(DataChunk):
|
||||
|
||||
def defall(self, client):
|
||||
DataChunk.defall(self, client)
|
||||
for i in self.icons.values():
|
||||
for i in list(self.icons.values()):
|
||||
client.msgl.append(i.msgdef)
|
||||
|
||||
|
||||
@ -214,7 +214,8 @@ class Music(DataChunk):
|
||||
self.md5msgs = {}
|
||||
DataChunk.__init__(self)
|
||||
|
||||
def read(self, (start, length)):
|
||||
def read(self, xxx_todo_changeme):
|
||||
(start, length) = xxx_todo_changeme
|
||||
self.f.seek(start)
|
||||
return self.f.read(length)
|
||||
|
||||
@ -264,7 +265,7 @@ def compactsprites(insert_new=None, insert_before=None):
|
||||
insert_before = None
|
||||
newsprites = ['']
|
||||
newd = {}
|
||||
l = sprites_by_n.items()
|
||||
l = list(sprites_by_n.items())
|
||||
l.sort()
|
||||
for n, s in l:
|
||||
if n == insert_before:
|
||||
@ -371,7 +372,7 @@ class Sprite:
|
||||
n1 = 1
|
||||
if self.alive > n1:
|
||||
if n1 in sprites_by_n:
|
||||
keys = sprites_by_n.keys()
|
||||
keys = list(sprites_by_n.keys())
|
||||
keys.remove(self.alive)
|
||||
keys.sort()
|
||||
keys = keys[keys.index(n1):]
|
||||
@ -452,7 +453,7 @@ class Client:
|
||||
self.activity = self.last_ping = time()
|
||||
self.force_ping_delay = 0.6
|
||||
for c in clients:
|
||||
for id in c.players.keys():
|
||||
for id in list(c.players.keys()):
|
||||
self.msgl.append(message(MSG_PLAYER_JOIN, id, c is self))
|
||||
|
||||
def emit(self, udpdata, broadcast_extras):
|
||||
@ -465,10 +466,10 @@ class Client:
|
||||
if self.udpsocket is not None:
|
||||
if self.sounds:
|
||||
if broadcast_extras is None or self not in broadcast_clients:
|
||||
udpdata = ''.join(self.sounds.keys() + [udpdata])
|
||||
udpdata = ''.join(list(self.sounds.keys()) + [udpdata])
|
||||
else:
|
||||
broadcast_extras.update(self.sounds)
|
||||
for key, value in self.sounds.items():
|
||||
for key, value in list(self.sounds.items()):
|
||||
if value:
|
||||
self.sounds[key] = value-1
|
||||
else:
|
||||
@ -481,8 +482,8 @@ class Client:
|
||||
for udpdata in udpdatas:
|
||||
try:
|
||||
self.udpsockcounter += self.udpsocket.send(udpdata)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'ignored:', str(e)
|
||||
except error as e:
|
||||
print('ignored:', str(e), file=sys.stderr)
|
||||
pass # ignore UDP send errors (buffer full, etc.)
|
||||
if self.has_music > 1 and NOW >= self.musicstreamer:
|
||||
self.musicstreamer += 0.99
|
||||
@ -559,7 +560,7 @@ class Client:
|
||||
def send_buffer(self, buffer):
|
||||
try:
|
||||
count = self.socket.send(buffer[:self.SEND_BOUND_PER_FRAME])
|
||||
except error, e:
|
||||
except error as e:
|
||||
if e.args[0] != EWOULDBLOCK:
|
||||
self.msgl = []
|
||||
self.initialdata = ""
|
||||
@ -588,7 +589,7 @@ class Client:
|
||||
if fn:
|
||||
fn(self, *values[1:])
|
||||
else:
|
||||
print "unknown message from", self.addr, ":", values
|
||||
print("unknown message from", self.addr, ":", values)
|
||||
self.buf = data
|
||||
except struct.error:
|
||||
import traceback
|
||||
@ -608,7 +609,7 @@ then use the following address:
|
||||
def input_handler(self):
|
||||
try:
|
||||
data = self.socket.recv(2048)
|
||||
except error, e:
|
||||
except error as e:
|
||||
self.disconnect(e, "socket.recv")
|
||||
else:
|
||||
if data:
|
||||
@ -628,9 +629,9 @@ then use the following address:
|
||||
extra = ""
|
||||
if infn:
|
||||
extra += " in " + infn
|
||||
print 'Disconnected by', self.addr, extra
|
||||
print('Disconnected by', self.addr, extra)
|
||||
self.log('disconnected' + extra)
|
||||
for p in self.players.values():
|
||||
for p in list(self.players.values()):
|
||||
p._playerleaves()
|
||||
try:
|
||||
del broadcast_clients[self]
|
||||
@ -646,7 +647,7 @@ then use the following address:
|
||||
game.FnDisconnected()
|
||||
|
||||
def killplayer(self, player):
|
||||
for id, p in self.players.items():
|
||||
for id, p in list(self.players.items()):
|
||||
if p is player:
|
||||
framemsgappend(message(MSG_PLAYER_KILL, id))
|
||||
del self.players[id]
|
||||
@ -654,19 +655,19 @@ then use the following address:
|
||||
game.updateplayers()
|
||||
|
||||
def joinplayer(self, id, *rest):
|
||||
if self.players.has_key(id):
|
||||
print "Note: player %s is already playing" % (self.addr+(id,),)
|
||||
if id in self.players:
|
||||
print("Note: player %s is already playing" % (self.addr+(id,),))
|
||||
return
|
||||
if game is None:
|
||||
return # refusing new player before the game starts
|
||||
p = game.FnPlayers()[id]
|
||||
if p is None:
|
||||
print "Too many players. New player %s refused." % (self.addr+(id,),)
|
||||
print("Too many players. New player %s refused." % (self.addr+(id,),))
|
||||
self.msgl.append(message(MSG_PLAYER_KILL, id))
|
||||
elif p.isplaying():
|
||||
print "Note: player %s is already played by another client" % (self.addr+(id,),)
|
||||
print("Note: player %s is already played by another client" % (self.addr+(id,),))
|
||||
else:
|
||||
print "New player %s" % (self.addr+(id,),)
|
||||
print("New player %s" % (self.addr+(id,),))
|
||||
p._client = self
|
||||
p.playerjoin()
|
||||
p.setplayername('')
|
||||
@ -679,7 +680,7 @@ then use the following address:
|
||||
try:
|
||||
p = self.players[id]
|
||||
except KeyError:
|
||||
print "Note: player %s is not playing" % (self.addr+(id,),)
|
||||
print("Note: player %s is not playing" % (self.addr+(id,),))
|
||||
else:
|
||||
p._playerleaves()
|
||||
|
||||
@ -700,7 +701,7 @@ then use the following address:
|
||||
if port == MSG_INLINE_FRAME or port == 0:
|
||||
# client requests data in-line on the TCP stream
|
||||
self.dyncompress = None
|
||||
import udpovertcp
|
||||
from . import udpovertcp
|
||||
self.udpsocket = udpovertcp.SocketMarshaller(self.socket, self)
|
||||
s = self.udpsocket.tcpsock
|
||||
self.log('set_udp_port: udp-over-tcp')
|
||||
@ -714,10 +715,10 @@ then use the following address:
|
||||
self.udpsocket.setblocking(0)
|
||||
addr = addr or self.addr[0]
|
||||
self.udpsocket.connect((addr, port))
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot set UDP socket to", addr, str(e)
|
||||
except error as e:
|
||||
print("Cannot set UDP socket to", addr, str(e), file=sys.stderr)
|
||||
self.udpsocket = None
|
||||
self.udpsockcounter = sys.maxint
|
||||
self.udpsockcounter = sys.maxsize
|
||||
else:
|
||||
if self.proto >= 3:
|
||||
self.setup_dyncompress()
|
||||
@ -726,15 +727,15 @@ then use the following address:
|
||||
if s:
|
||||
try:
|
||||
s.setsockopt(SOL_IP, IP_TOS, 0x10) # IPTOS_LOWDELAY
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot set IPTOS_LOWDELAY:", str(e)
|
||||
except error as e:
|
||||
print("Cannot set IPTOS_LOWDELAY:", str(e), file=sys.stderr)
|
||||
|
||||
def enable_sound(self, sound_mode=1, *rest):
|
||||
if sound_mode != self.has_sound:
|
||||
self.sounds = {}
|
||||
self.has_sound = sound_mode
|
||||
if self.has_sound > 0:
|
||||
for snd in samples.values():
|
||||
for snd in list(samples.values()):
|
||||
snd.defall(self)
|
||||
#self.log('enable_sound %s' % sound_mode)
|
||||
|
||||
@ -766,10 +767,10 @@ then use the following address:
|
||||
if self.initialized < 2:
|
||||
# send all current bitmap data
|
||||
self.initialized = 2
|
||||
for b in bitmaps.values():
|
||||
for b in list(bitmaps.values()):
|
||||
b.defall(self)
|
||||
self.finishinit(game)
|
||||
for id, p in game.FnPlayers().items():
|
||||
for id, p in list(game.FnPlayers().items()):
|
||||
if p.standardplayericon is not None:
|
||||
self.msgl.append(message(MSG_PLAYER_ICON, id, p.standardplayericon.code))
|
||||
self.msgl.append(message(MSG_PONG, *rest))
|
||||
@ -781,7 +782,7 @@ then use the following address:
|
||||
pass
|
||||
|
||||
def log(self, message):
|
||||
print self.addr, message
|
||||
print(self.addr, message)
|
||||
|
||||
def protocol_version(self, version, *rest):
|
||||
self.proto = version
|
||||
@ -980,7 +981,7 @@ def opentcpsocket(port=None):
|
||||
except error:
|
||||
if port == INADDR_ANY:
|
||||
for i in range(10):
|
||||
port = random.choice(xrange(8000, 12000))
|
||||
port = random.choice(range(8000, 12000))
|
||||
try:
|
||||
s.bind(('', port))
|
||||
s.listen(1)
|
||||
@ -989,7 +990,7 @@ def opentcpsocket(port=None):
|
||||
else:
|
||||
break
|
||||
else:
|
||||
raise error, "server cannot find a free TCP socket port"
|
||||
raise error("server cannot find a free TCP socket port")
|
||||
else:
|
||||
raise
|
||||
|
||||
@ -1004,13 +1005,13 @@ def openpingsocket(only_port=None):
|
||||
only_port = only_port or PORTS.get('PING', None)
|
||||
s = findsocket('PING')
|
||||
if s is None:
|
||||
import hostchooser
|
||||
from . import hostchooser
|
||||
s = hostchooser.serverside_ping(only_port)
|
||||
if s is None:
|
||||
return None
|
||||
def pingsocket_handler(s=s):
|
||||
global game
|
||||
import hostchooser
|
||||
from . import hostchooser
|
||||
if game is not None:
|
||||
args = game.FnDesc, ('', game.address[1]), game.FnExtraDesc()
|
||||
else:
|
||||
@ -1032,10 +1033,10 @@ def openhttpsocket(ServerClass=None, HandlerClass=None,
|
||||
s = findsocket('HTTP')
|
||||
if s is None:
|
||||
if ServerClass is None:
|
||||
from BaseHTTPServer import HTTPServer as ServerClass
|
||||
from http.server import HTTPServer as ServerClass
|
||||
if HandlerClass is None:
|
||||
import javaserver
|
||||
from httpserver import MiniHandler as HandlerClass
|
||||
from . import javaserver
|
||||
from .httpserver import MiniHandler as HandlerClass
|
||||
server_address = ('', port or 8000)
|
||||
try:
|
||||
httpd = ServerClass(server_address, HandlerClass)
|
||||
@ -1044,8 +1045,8 @@ def openhttpsocket(ServerClass=None, HandlerClass=None,
|
||||
server_address = ('', INADDR_ANY)
|
||||
try:
|
||||
httpd = ServerClass(server_address, HandlerClass)
|
||||
except error, e:
|
||||
print >> sys.stderr, "cannot start HTTP server", str(e)
|
||||
except error as e:
|
||||
print("cannot start HTTP server", str(e), file=sys.stderr)
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
@ -1053,7 +1054,7 @@ def openhttpsocket(ServerClass=None, HandlerClass=None,
|
||||
addsocket('HTTP', s, httpd.handle_request)
|
||||
return s
|
||||
|
||||
BROADCAST_PORT_RANGE = xrange(18000, 19000)
|
||||
BROADCAST_PORT_RANGE = range(18000, 19000)
|
||||
#BROADCAST_MESSAGE comes from msgstruct
|
||||
BROADCAST_DELAY = 0.6180
|
||||
BROADCAST_DELAY_INCR = 2.7183
|
||||
@ -1064,8 +1065,8 @@ def openbroadcastsocket(broadcastport=None):
|
||||
try:
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot broadcast", str(e)
|
||||
except error as e:
|
||||
print("Cannot broadcast", str(e), file=sys.stderr)
|
||||
return None
|
||||
port = broadcastport or random.choice(BROADCAST_PORT_RANGE)
|
||||
addsocket('BROADCAST', s, port=port)
|
||||
@ -1100,20 +1101,20 @@ class Game:
|
||||
clearsprites()
|
||||
game = self
|
||||
if recording:
|
||||
for b in bitmaps.values():
|
||||
for b in list(bitmaps.values()):
|
||||
b.defall(recording)
|
||||
self.pendingclients = []
|
||||
|
||||
def openserver(self):
|
||||
ps = openpingsocket()
|
||||
print '%s server at %s:%d, Broadcast %d, UDP %d' % (
|
||||
print('%s server at %s:%d, Broadcast %d, UDP %d' % (
|
||||
self.FnDesc, self.address[0], self.address[1],
|
||||
displaysockport(self.broadcast_s), displaysockport(ps))
|
||||
displaysockport(self.broadcast_s), displaysockport(ps)))
|
||||
|
||||
hs = openhttpsocket()
|
||||
if hs:
|
||||
print 'HTTP server: http://%s:%d' % (
|
||||
self.address[0], displaysockport(hs))
|
||||
print('HTTP server: http://%s:%d' % (
|
||||
self.address[0], displaysockport(hs)))
|
||||
|
||||
try:
|
||||
from localmsg import autonotify
|
||||
@ -1185,7 +1186,7 @@ class Game:
|
||||
if recording:
|
||||
recording.udpdata(udpdata)
|
||||
if broadcast_extras is not None:
|
||||
udpdata = ''.join(broadcast_extras.keys() + [udpdata])
|
||||
udpdata = ''.join(list(broadcast_extras.keys()) + [udpdata])
|
||||
try:
|
||||
self.broadcast_s.sendto(udpdata,
|
||||
('<broadcast>', self.broadcast_port))
|
||||
@ -1212,18 +1213,18 @@ class Game:
|
||||
|
||||
def newclient(self, conn, addr):
|
||||
if len(clients)==MAX_CLIENTS:
|
||||
print "Too many connections; refusing new connection from", addr
|
||||
print("Too many connections; refusing new connection from", addr)
|
||||
conn.close()
|
||||
else:
|
||||
try:
|
||||
addrname = (gethostbyaddr(addr[0])[0],) + addr[1:]
|
||||
except:
|
||||
addrname = addr
|
||||
print 'Connected by', addrname
|
||||
print('Connected by', addrname)
|
||||
try:
|
||||
c = FnClient(conn, addrname)
|
||||
except error, e:
|
||||
print 'Connexion already lost!', e
|
||||
except error as e:
|
||||
print('Connexion already lost!', e)
|
||||
else:
|
||||
if game is not None:
|
||||
c.opengame(game)
|
||||
@ -1240,14 +1241,14 @@ def recursiveloop(endtime, extra_sockets):
|
||||
delay = game.mainstep()
|
||||
else:
|
||||
delay = 5.0
|
||||
iwtd = extra_sockets + serversockets.keys()
|
||||
iwtd = extra_sockets + list(serversockets.keys())
|
||||
timediff = max(0.0, endtime - time())
|
||||
iwtd, owtd, ewtd = select(iwtd, [], iwtd, min(delay, timediff))
|
||||
if ewtd:
|
||||
if game:
|
||||
game.socketerrors(ewtd)
|
||||
if ewtd:
|
||||
print >> sys.stderr, "Unexpected socket error reported"
|
||||
print("Unexpected socket error reported", file=sys.stderr)
|
||||
for s in iwtd:
|
||||
if s in serversockets:
|
||||
serversockets[s]() # call handler
|
||||
@ -1269,10 +1270,10 @@ def mainloop():
|
||||
delay = game.mainstep()
|
||||
else:
|
||||
delay = SERVER_SHUTDOWN or 5.0
|
||||
iwtd = serversockets.keys()
|
||||
iwtd = list(serversockets.keys())
|
||||
try:
|
||||
iwtd, owtd, ewtd = select(iwtd, [], iwtd, delay)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
from select import error as select_error
|
||||
if not isinstance(e, select_error):
|
||||
raise
|
||||
@ -1281,7 +1282,7 @@ def mainloop():
|
||||
if game:
|
||||
game.socketerrors(ewtd)
|
||||
if ewtd:
|
||||
print >> sys.stderr, "Unexpected socket error reported"
|
||||
print("Unexpected socket error reported", file=sys.stderr)
|
||||
servertimeout = None
|
||||
if iwtd:
|
||||
for s in iwtd:
|
||||
@ -1291,13 +1292,13 @@ def mainloop():
|
||||
elif SERVER_SHUTDOWN and not ewtd and not owtd:
|
||||
SERVER_SHUTDOWN -= delay
|
||||
if SERVER_SHUTDOWN <= 0.001:
|
||||
raise SystemExit, "Server shutdown requested."
|
||||
raise SystemExit("Server shutdown requested.")
|
||||
elif clients or getattr(game, 'autoreset', 0):
|
||||
servertimeout = None
|
||||
elif servertimeout is None:
|
||||
servertimeout = time() + SERVER_TIMEOUT
|
||||
elif time() > servertimeout:
|
||||
raise SystemExit, "No more server activity, timing out."
|
||||
raise SystemExit("No more server activity, timing out.")
|
||||
except KeyboardInterrupt:
|
||||
if game is None or not game.FnExcHandler(1):
|
||||
raise
|
||||
@ -1310,7 +1311,7 @@ def mainloop():
|
||||
removesocket('LISTEN')
|
||||
removesocket('PING')
|
||||
if clients:
|
||||
print "Server crash -- waiting for clients to terminate..."
|
||||
print("Server crash -- waiting for clients to terminate...")
|
||||
while clients:
|
||||
iwtd = [c.socket for c in clients]
|
||||
try:
|
||||
@ -1325,12 +1326,12 @@ def mainloop():
|
||||
elif c.socket in iwtd:
|
||||
try:
|
||||
data = c.socket.recv(2048)
|
||||
except error, e:
|
||||
except error as e:
|
||||
c.disconnect(e)
|
||||
else:
|
||||
if not data and not hasattr(c.socket, 'RECV_CAN_RETURN_EMPTY'):
|
||||
c.disconnect("end of data")
|
||||
print "Server closed."
|
||||
print("Server closed.")
|
||||
|
||||
def closeeverything():
|
||||
global SERVER_SHUTDOWN
|
||||
|
1378
common/gamesrv.py.bak
Normal file
1378
common/gamesrv.py.bak
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@ def serverside_ping(only_port=None):
|
||||
s.bind(('', port))
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
return s
|
||||
except error, e:
|
||||
except error as e:
|
||||
if only_port is None:
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.bind(('', INADDR_ANY))
|
||||
@ -25,28 +25,27 @@ def serverside_ping(only_port=None):
|
||||
def answer_ping(s, descr, addr, extra='', httpport=''):
|
||||
try:
|
||||
data, source = s.recvfrom(100)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'ping error:', str(e)
|
||||
except error as e:
|
||||
print('ping error:', str(e), file=sys.stderr)
|
||||
return
|
||||
if data == PING_MESSAGE:
|
||||
print >> sys.stderr, "ping by", source
|
||||
print("ping by", source, file=sys.stderr)
|
||||
answer = '%s:%s:%s:%s:%s:%s' % (PONG_MESSAGE, descr,
|
||||
addr[0], addr[1], extra, httpport)
|
||||
s.sendto(answer, source)
|
||||
else:
|
||||
print >> sys.stderr, \
|
||||
"unexpected data on UDP port %d by" % UDP_PORT, source
|
||||
print("unexpected data on UDP port %d by" % UDP_PORT, source, file=sys.stderr)
|
||||
|
||||
|
||||
def pick(hostlist, delay=1):
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
for host in hostlist:
|
||||
print >> sys.stderr, "* Looking for a server on %s... " % host
|
||||
print("* Looking for a server on %s... " % host, file=sys.stderr)
|
||||
try:
|
||||
s.sendto(PING_MESSAGE, (host, UDP_PORT))
|
||||
except error, e:
|
||||
print >> sys.stderr, 'send:', str(e)
|
||||
except error as e:
|
||||
print('send:', str(e), file=sys.stderr)
|
||||
continue
|
||||
while 1:
|
||||
iwtd, owtd, ewtd = select.select([s], [], [], delay)
|
||||
@ -54,9 +53,9 @@ def pick(hostlist, delay=1):
|
||||
break
|
||||
try:
|
||||
data, answer_from = s.recvfrom(200)
|
||||
except error, e:
|
||||
except error as e:
|
||||
if e.args[0] != ETIMEDOUT:
|
||||
print >> sys.stderr, 'recv:', str(e)
|
||||
print('recv:', str(e), file=sys.stderr)
|
||||
continue
|
||||
break
|
||||
data = data.split(':')
|
||||
@ -68,20 +67,20 @@ def pick(hostlist, delay=1):
|
||||
pass
|
||||
else:
|
||||
result = (hostname, port)
|
||||
print >> sys.stderr, "* Picking %r at" % data[1], result
|
||||
print("* Picking %r at" % data[1], result, file=sys.stderr)
|
||||
return result
|
||||
print >> sys.stderr, "got an unexpected answer", data, "from", answer_from
|
||||
print >> sys.stderr, "no server found."
|
||||
print("got an unexpected answer", data, "from", answer_from, file=sys.stderr)
|
||||
print("no server found.", file=sys.stderr)
|
||||
raise SystemExit
|
||||
|
||||
def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
|
||||
tries=2, delay=0.5, verbose=1, port_needed=1):
|
||||
import gamesrv
|
||||
from . import gamesrv
|
||||
if verbose:
|
||||
print >> sys.stderr, 'Looking for servers in the following list:'
|
||||
print('Looking for servers in the following list:', file=sys.stderr)
|
||||
for host, udpport in hostlist:
|
||||
print >> sys.stderr, ' %s, UDP port %s' % (
|
||||
host, udpport or ("%s (default)" % UDP_PORT))
|
||||
print(' %s, UDP port %s' % (
|
||||
host, udpport or ("%s (default)" % UDP_PORT)), file=sys.stderr)
|
||||
events = {}
|
||||
replies = []
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
@ -93,21 +92,21 @@ def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
|
||||
if host != '<broadcast>':
|
||||
try:
|
||||
ipaddr = gethostbyname(host)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'gethostbyname:', str(e)
|
||||
except error as e:
|
||||
print('gethostbyname:', str(e), file=sys.stderr)
|
||||
s.sendto(PING_MESSAGE, (ipaddr, udpport or UDP_PORT))
|
||||
hostsend, hostrecv = events.setdefault(ipaddr, ([], []))
|
||||
hostsend.append(time.time())
|
||||
except error, e:
|
||||
print >> sys.stderr, 'send:', str(e)
|
||||
except error as e:
|
||||
print('send:', str(e), file=sys.stderr)
|
||||
continue
|
||||
endtime = time.time() + delay
|
||||
while gamesrv.recursiveloop(endtime, [s]):
|
||||
try:
|
||||
data, answer_from = s.recvfrom(200)
|
||||
except error, e:
|
||||
except error as e:
|
||||
if e.args[0] != ETIMEDOUT:
|
||||
print >> sys.stderr, 'recv:', str(e)
|
||||
print('recv:', str(e), file=sys.stderr)
|
||||
continue
|
||||
break
|
||||
try:
|
||||
@ -134,7 +133,7 @@ def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
|
||||
server = ':'.join(data[1:2]+data[4:])
|
||||
replies.append((hostname, realhostname, port, server, ipaddr))
|
||||
else:
|
||||
print >> sys.stderr, "got an unexpected answer from", answer_from
|
||||
print("got an unexpected answer from", answer_from, file=sys.stderr)
|
||||
servers = {}
|
||||
aliases = {}
|
||||
timeout = time.time() + 2.0 # wait for gethostbyaddr() for 2 seconds
|
||||
@ -155,8 +154,8 @@ def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
|
||||
if replies:
|
||||
time.sleep(0.08) # time for gethostbyaddr() to finish
|
||||
if verbose:
|
||||
print >> sys.stderr, "%d answer(s):" % len(servers), servers.keys()
|
||||
for host, port in servers.keys():
|
||||
print("%d answer(s):" % len(servers), list(servers.keys()), file=sys.stderr)
|
||||
for host, port in list(servers.keys()):
|
||||
ping = None
|
||||
ipaddr = aliases[host]
|
||||
if ipaddr in events:
|
||||
@ -176,7 +175,7 @@ def _lazygetter(hostname, resultlst):
|
||||
try:
|
||||
hostname = gethostbyaddr(hostname)[0]
|
||||
if hostname == 'localhost':
|
||||
from msgstruct import HOSTNAME as hostname
|
||||
from .msgstruct import HOSTNAME as hostname
|
||||
except error:
|
||||
pass
|
||||
finally:
|
||||
@ -187,6 +186,6 @@ def lazy_gethostbyaddr(hostname):
|
||||
return HOSTNAMECACHE[hostname]
|
||||
except KeyError:
|
||||
resultlst = HOSTNAMECACHE[hostname] = []
|
||||
import thread
|
||||
thread.start_new_thread(_lazygetter, (hostname, resultlst))
|
||||
import _thread
|
||||
_thread.start_new_thread(_lazygetter, (hostname, resultlst))
|
||||
return resultlst
|
||||
|
192
common/hostchooser.py.bak
Normal file
192
common/hostchooser.py.bak
Normal file
@ -0,0 +1,192 @@
|
||||
from socket import *
|
||||
import time, select, sys
|
||||
from errno import ETIMEDOUT
|
||||
|
||||
UDP_PORT = 8056
|
||||
PING_MESSAGE = "pclient-game-ping"
|
||||
PONG_MESSAGE = "server-game-pong"
|
||||
|
||||
|
||||
def serverside_ping(only_port=None):
|
||||
port = only_port or UDP_PORT
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
try:
|
||||
s.bind(('', port))
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
return s
|
||||
except error, e:
|
||||
if only_port is None:
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.bind(('', INADDR_ANY))
|
||||
return s
|
||||
else:
|
||||
return None
|
||||
|
||||
def answer_ping(s, descr, addr, extra='', httpport=''):
|
||||
try:
|
||||
data, source = s.recvfrom(100)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'ping error:', str(e)
|
||||
return
|
||||
if data == PING_MESSAGE:
|
||||
print >> sys.stderr, "ping by", source
|
||||
answer = '%s:%s:%s:%s:%s:%s' % (PONG_MESSAGE, descr,
|
||||
addr[0], addr[1], extra, httpport)
|
||||
s.sendto(answer, source)
|
||||
else:
|
||||
print >> sys.stderr, \
|
||||
"unexpected data on UDP port %d by" % UDP_PORT, source
|
||||
|
||||
|
||||
def pick(hostlist, delay=1):
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
for host in hostlist:
|
||||
print >> sys.stderr, "* Looking for a server on %s... " % host
|
||||
try:
|
||||
s.sendto(PING_MESSAGE, (host, UDP_PORT))
|
||||
except error, e:
|
||||
print >> sys.stderr, 'send:', str(e)
|
||||
continue
|
||||
while 1:
|
||||
iwtd, owtd, ewtd = select.select([s], [], [], delay)
|
||||
if not iwtd:
|
||||
break
|
||||
try:
|
||||
data, answer_from = s.recvfrom(200)
|
||||
except error, e:
|
||||
if e.args[0] != ETIMEDOUT:
|
||||
print >> sys.stderr, 'recv:', str(e)
|
||||
continue
|
||||
break
|
||||
data = data.split(':')
|
||||
if len(data) >= 4 and data[0] == PONG_MESSAGE:
|
||||
hostname = data[2] or answer_from[0]
|
||||
try:
|
||||
port = int(data[3])
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
result = (hostname, port)
|
||||
print >> sys.stderr, "* Picking %r at" % data[1], result
|
||||
return result
|
||||
print >> sys.stderr, "got an unexpected answer", data, "from", answer_from
|
||||
print >> sys.stderr, "no server found."
|
||||
raise SystemExit
|
||||
|
||||
def find_servers(hostlist=[('127.0.0.1', None), ('<broadcast>', None)],
|
||||
tries=2, delay=0.5, verbose=1, port_needed=1):
|
||||
import gamesrv
|
||||
if verbose:
|
||||
print >> sys.stderr, 'Looking for servers in the following list:'
|
||||
for host, udpport in hostlist:
|
||||
print >> sys.stderr, ' %s, UDP port %s' % (
|
||||
host, udpport or ("%s (default)" % UDP_PORT))
|
||||
events = {}
|
||||
replies = []
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
for trynum in range(tries):
|
||||
for host, udpport in hostlist:
|
||||
try:
|
||||
ipaddr = host
|
||||
if host != '<broadcast>':
|
||||
try:
|
||||
ipaddr = gethostbyname(host)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'gethostbyname:', str(e)
|
||||
s.sendto(PING_MESSAGE, (ipaddr, udpport or UDP_PORT))
|
||||
hostsend, hostrecv = events.setdefault(ipaddr, ([], []))
|
||||
hostsend.append(time.time())
|
||||
except error, e:
|
||||
print >> sys.stderr, 'send:', str(e)
|
||||
continue
|
||||
endtime = time.time() + delay
|
||||
while gamesrv.recursiveloop(endtime, [s]):
|
||||
try:
|
||||
data, answer_from = s.recvfrom(200)
|
||||
except error, e:
|
||||
if e.args[0] != ETIMEDOUT:
|
||||
print >> sys.stderr, 'recv:', str(e)
|
||||
continue
|
||||
break
|
||||
try:
|
||||
ipaddr = gethostbyname(answer_from[0])
|
||||
except error:
|
||||
ipaddr = answer_from[0]
|
||||
else:
|
||||
hostsend, hostrecv = events.setdefault(ipaddr, ([], []))
|
||||
hostrecv.append(time.time())
|
||||
data = data.split(':')
|
||||
if len(data) >= 4 and data[0] == PONG_MESSAGE:
|
||||
try:
|
||||
port = int(data[3])
|
||||
except ValueError:
|
||||
if port_needed:
|
||||
continue
|
||||
port = ''
|
||||
if data[2]:
|
||||
hostname = data[2]
|
||||
realhostname = [hostname]
|
||||
else:
|
||||
hostname = answer_from[0]
|
||||
realhostname = lazy_gethostbyaddr(hostname)
|
||||
server = ':'.join(data[1:2]+data[4:])
|
||||
replies.append((hostname, realhostname, port, server, ipaddr))
|
||||
else:
|
||||
print >> sys.stderr, "got an unexpected answer from", answer_from
|
||||
servers = {}
|
||||
aliases = {}
|
||||
timeout = time.time() + 2.0 # wait for gethostbyaddr() for 2 seconds
|
||||
while replies:
|
||||
i = 0
|
||||
now = time.time()
|
||||
while i < len(replies):
|
||||
hostname, realhostname, port, server, ipaddr = replies[i]
|
||||
if realhostname:
|
||||
hostname = realhostname[0] # got an answer
|
||||
elif now < timeout:
|
||||
i += 1 # must wait some more time
|
||||
continue
|
||||
result = (hostname, port)
|
||||
servers[result] = server
|
||||
aliases[hostname] = ipaddr
|
||||
del replies[i]
|
||||
if replies:
|
||||
time.sleep(0.08) # time for gethostbyaddr() to finish
|
||||
if verbose:
|
||||
print >> sys.stderr, "%d answer(s):" % len(servers), servers.keys()
|
||||
for host, port in servers.keys():
|
||||
ping = None
|
||||
ipaddr = aliases[host]
|
||||
if ipaddr in events:
|
||||
hostsend, hostrecv = events[ipaddr]
|
||||
if len(hostsend) == len(hostrecv) == tries:
|
||||
ping = min([t2-t1 for t1, t2 in zip(hostsend, hostrecv)])
|
||||
servers[host, port] = (servers[host, port], ping)
|
||||
sys.setcheckinterval(4096)
|
||||
return servers
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
HOSTNAMECACHE = {}
|
||||
|
||||
def _lazygetter(hostname, resultlst):
|
||||
try:
|
||||
try:
|
||||
hostname = gethostbyaddr(hostname)[0]
|
||||
if hostname == 'localhost':
|
||||
from msgstruct import HOSTNAME as hostname
|
||||
except error:
|
||||
pass
|
||||
finally:
|
||||
resultlst.append(hostname)
|
||||
|
||||
def lazy_gethostbyaddr(hostname):
|
||||
try:
|
||||
return HOSTNAMECACHE[hostname]
|
||||
except KeyError:
|
||||
resultlst = HOSTNAMECACHE[hostname] = []
|
||||
import thread
|
||||
thread.start_new_thread(_lazygetter, (hostname, resultlst))
|
||||
return resultlst
|
@ -1,10 +1,10 @@
|
||||
from __future__ import generators
|
||||
from __future__ import nested_scopes
|
||||
import BaseHTTPServer
|
||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
||||
import urlparse, cgi, htmlentitydefs
|
||||
|
||||
|
||||
import http.server
|
||||
from http.server import SimpleHTTPRequestHandler
|
||||
import urllib.parse, cgi, html.entities
|
||||
import sys, os, time
|
||||
from cStringIO import StringIO
|
||||
from io import StringIO
|
||||
|
||||
|
||||
class Translator:
|
||||
@ -28,7 +28,7 @@ class Translator:
|
||||
prevstdout = sys.stdout
|
||||
try:
|
||||
sys.stdout = f = StringIO()
|
||||
exec expr in self.globals, self.locals
|
||||
exec(expr, self.globals, self.locals)
|
||||
finally:
|
||||
sys.stdout = prevstdout
|
||||
return f.getvalue()
|
||||
@ -59,7 +59,7 @@ class TranslatorIO:
|
||||
# HTML quoting
|
||||
|
||||
text_to_html = {}
|
||||
for key, value in htmlentitydefs.entitydefs.items():
|
||||
for key, value in list(html.entities.entitydefs.items()):
|
||||
text_to_html[value] = '&' + key + ';'
|
||||
|
||||
def htmlquote(s):
|
||||
@ -107,7 +107,7 @@ class HTTPRequestError(Exception):
|
||||
class MiniHandler(SimpleHTTPRequestHandler):
|
||||
|
||||
def send_head(self, query=''):
|
||||
addr, host, path, query1, fragment = urlparse.urlsplit(self.path)
|
||||
addr, host, path, query1, fragment = urllib.parse.urlsplit(self.path)
|
||||
path = canonicalpath(path)
|
||||
if path not in pathloaders:
|
||||
if path + '/' in pathloaders:
|
||||
@ -123,10 +123,10 @@ class MiniHandler(SimpleHTTPRequestHandler):
|
||||
hdr = self.headers
|
||||
hdr['remote host'] = self.client_address[0]
|
||||
f, ctype = loader(headers=hdr, **kwds)
|
||||
except IOError, e:
|
||||
except IOError as e:
|
||||
self.send_error(404, "I/O error: " + str(e))
|
||||
return None
|
||||
except HTTPRequestError, e:
|
||||
except HTTPRequestError as e:
|
||||
self.send_error(500, str(e))
|
||||
return None
|
||||
except:
|
||||
@ -187,6 +187,6 @@ Please <a href="%s">click here</a> to continue.
|
||||
actions_when_finished = []
|
||||
|
||||
def my_host():
|
||||
import gamesrv
|
||||
from . import gamesrv
|
||||
port = gamesrv.socketports[gamesrv.openhttpsocket()]
|
||||
return '127.0.0.1:%d' % port
|
||||
|
192
common/httpserver.py.bak
Normal file
192
common/httpserver.py.bak
Normal file
@ -0,0 +1,192 @@
|
||||
from __future__ import generators
|
||||
from __future__ import nested_scopes
|
||||
import BaseHTTPServer
|
||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
||||
import urlparse, cgi, htmlentitydefs
|
||||
import sys, os, time
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
||||
class Translator:
|
||||
"""For use with format strings.
|
||||
|
||||
'formatstring % translator' will evaluate all %(xxx)s expressions
|
||||
found in the format string in the given globals/locals.
|
||||
|
||||
Multiline expressions are assumed to be one or several complete
|
||||
statements; they are executed and whatever they print is inserted back
|
||||
into the format string."""
|
||||
|
||||
def __init__(self, globals, locals):
|
||||
self.globals = globals
|
||||
self.locals = locals
|
||||
|
||||
def __getitem__(self, expr):
|
||||
if '\n' in expr:
|
||||
if not expr.endswith('\n'):
|
||||
expr += '\n'
|
||||
prevstdout = sys.stdout
|
||||
try:
|
||||
sys.stdout = f = StringIO()
|
||||
exec expr in self.globals, self.locals
|
||||
finally:
|
||||
sys.stdout = prevstdout
|
||||
return f.getvalue()
|
||||
else:
|
||||
return eval(expr, self.globals, self.locals)
|
||||
|
||||
class TranslatorIO:
|
||||
"Lazy version of Translator."
|
||||
|
||||
def __init__(self, fmt, d):
|
||||
self.gen = self.generate(fmt, d)
|
||||
|
||||
def read(self, ignored=None):
|
||||
for text in self.gen:
|
||||
if text:
|
||||
return text
|
||||
return ''
|
||||
|
||||
def close(self):
|
||||
self.gen = ()
|
||||
|
||||
def generate(self, fmt, d):
|
||||
t = Translator(d, d)
|
||||
for data in fmt.split('\x0c'):
|
||||
yield data % t
|
||||
|
||||
|
||||
# HTML quoting
|
||||
|
||||
text_to_html = {}
|
||||
for key, value in htmlentitydefs.entitydefs.items():
|
||||
text_to_html[value] = '&' + key + ';'
|
||||
|
||||
def htmlquote(s):
|
||||
return ''.join([text_to_html.get(c, c) for c in s])
|
||||
|
||||
|
||||
# HTTP Request Handler
|
||||
|
||||
pathloaders = {}
|
||||
|
||||
def canonicalpath(url):
|
||||
if url.startswith('/'):
|
||||
url = url[1:]
|
||||
return url.lower()
|
||||
|
||||
def register(url, loader):
|
||||
pathloaders[canonicalpath(url)] = loader
|
||||
|
||||
def is_registered(url):
|
||||
return canonicalpath(url) in pathloaders
|
||||
|
||||
def load(filename, mimetype=None, locals=None):
|
||||
if mimetype and mimetype.startswith('text/'):
|
||||
mode = 'r'
|
||||
else:
|
||||
mode = 'rb'
|
||||
f = open(filename, mode)
|
||||
if locals is not None:
|
||||
data = f.read()
|
||||
f.close()
|
||||
#data = data.replace('%"', '%%"')
|
||||
d = globals().copy()
|
||||
d.update(locals)
|
||||
f = TranslatorIO(data, d)
|
||||
return f, mimetype
|
||||
|
||||
def fileloader(filename, mimetype=None):
|
||||
def loader(**options):
|
||||
return load(filename, mimetype)
|
||||
return loader
|
||||
|
||||
class HTTPRequestError(Exception):
|
||||
pass
|
||||
|
||||
class MiniHandler(SimpleHTTPRequestHandler):
|
||||
|
||||
def send_head(self, query=''):
|
||||
addr, host, path, query1, fragment = urlparse.urlsplit(self.path)
|
||||
path = canonicalpath(path)
|
||||
if path not in pathloaders:
|
||||
if path + '/' in pathloaders:
|
||||
return self.redirect(path + '/')
|
||||
self.send_error(404)
|
||||
return None
|
||||
kwds = {}
|
||||
for q in [query1, query]:
|
||||
if q:
|
||||
kwds.update(cgi.parse_qs(q))
|
||||
loader = pathloaders[path]
|
||||
try:
|
||||
hdr = self.headers
|
||||
hdr['remote host'] = self.client_address[0]
|
||||
f, ctype = loader(headers=hdr, **kwds)
|
||||
except IOError, e:
|
||||
self.send_error(404, "I/O error: " + str(e))
|
||||
return None
|
||||
except HTTPRequestError, e:
|
||||
self.send_error(500, str(e))
|
||||
return None
|
||||
except:
|
||||
f = StringIO()
|
||||
import traceback
|
||||
traceback.print_exc(file=f)
|
||||
data = htmlquote(f.getvalue())
|
||||
data = data.replace('\n', '<br>\n')
|
||||
self.send_error(500)
|
||||
return StringIO('<hr><p>'+data+'</p>')
|
||||
if ctype is None:
|
||||
ctype = self.guess_type(self.translate_path(self.path))
|
||||
elif f is None:
|
||||
return self.redirect(ctype)
|
||||
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", ctype)
|
||||
self.end_headers()
|
||||
return f
|
||||
|
||||
def redirect(self, url):
|
||||
self.send_response(302)
|
||||
self.send_header("Content-type", 'text/html')
|
||||
self.send_header("Location", url)
|
||||
self.end_headers()
|
||||
return StringIO('''<html><head></head><body>
|
||||
Please <a href="%s">click here</a> to continue.
|
||||
</body></html>
|
||||
''' % url)
|
||||
|
||||
def do_POST(self):
|
||||
try:
|
||||
nbytes = int(self.headers.getheader('content-length'))
|
||||
except:
|
||||
nbytes = 0
|
||||
query = self.rfile.read(nbytes).strip()
|
||||
f = self.send_head(query)
|
||||
if f:
|
||||
self.copyfile(f, self.wfile)
|
||||
f.close()
|
||||
|
||||
def parse_request(self):
|
||||
if self.raw_requestline == '':
|
||||
return False
|
||||
else:
|
||||
return SimpleHTTPRequestHandler.parse_request(self)
|
||||
|
||||
def address_string(self):
|
||||
"""Override to avoid DNS lookups"""
|
||||
return "%s:%d" % self.client_address
|
||||
|
||||
def finish(self):
|
||||
SimpleHTTPRequestHandler.finish(self)
|
||||
self.connection.close()
|
||||
while actions_when_finished:
|
||||
actions_when_finished.pop(0)()
|
||||
|
||||
actions_when_finished = []
|
||||
|
||||
def my_host():
|
||||
import gamesrv
|
||||
port = gamesrv.socketports[gamesrv.openhttpsocket()]
|
||||
return '127.0.0.1:%d' % port
|
@ -1,6 +1,6 @@
|
||||
import sys, os
|
||||
from cStringIO import StringIO
|
||||
import httpserver
|
||||
from io import StringIO
|
||||
from . import httpserver
|
||||
|
||||
PLAYERNAMES = ['Bub', 'Bob', 'Boob', 'Beb',
|
||||
'Biob', 'Bab', 'Bib',
|
||||
@ -68,11 +68,11 @@ def indexloader(**options):
|
||||
if 'cheat' in options:
|
||||
for opt in options.pop('cheat'):
|
||||
__cheat(opt)
|
||||
import gamesrv
|
||||
from . import gamesrv
|
||||
if gamesrv.game is None:
|
||||
indexdata = EMPTY_PAGE
|
||||
else:
|
||||
names = playernames(options).items()
|
||||
names = list(playernames(options).items())
|
||||
indexdata = INDEX_PAGE % {
|
||||
'title': gamesrv.game.FnDesc,
|
||||
'width': gamesrv.game.width,
|
||||
@ -114,16 +114,16 @@ def wav2au(data):
|
||||
return data
|
||||
|
||||
def sampleloader(code=[], **options):
|
||||
import gamesrv
|
||||
from . import gamesrv
|
||||
try:
|
||||
data = wave_cache[code[0]]
|
||||
except KeyError:
|
||||
for key, snd in gamesrv.samples.items():
|
||||
for key, snd in list(gamesrv.samples.items()):
|
||||
if str(getattr(snd, 'code', '')) == code[0]:
|
||||
data = wave_cache[code[0]] = wav2au(snd.read())
|
||||
break
|
||||
else:
|
||||
raise KeyError, code[0]
|
||||
raise KeyError(code[0])
|
||||
return StringIO(data), 'audio/wav'
|
||||
|
||||
|
||||
|
157
common/javaserver.py.bak
Normal file
157
common/javaserver.py.bak
Normal file
@ -0,0 +1,157 @@
|
||||
import sys, os
|
||||
from cStringIO import StringIO
|
||||
import httpserver
|
||||
|
||||
PLAYERNAMES = ['Bub', 'Bob', 'Boob', 'Beb',
|
||||
'Biob', 'Bab', 'Bib',
|
||||
'Baub', 'Beab', 'Biab']
|
||||
LOCALDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
DATADIR = os.path.join(LOCALDIR, os.pardir, 'http2', 'data')
|
||||
|
||||
EMPTY_PAGE = '''<html>
|
||||
<head><title>No server is running</title></head>
|
||||
<body><h1>No server is running at the moment.</h1>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
INDEX_PAGE = '''<html>
|
||||
<head><title>%(title)s</title></head>
|
||||
<body><h1>%(title)s</h1>
|
||||
<applet code=pclient.class width=%(width)s height=%(height)s>
|
||||
<param name="gameport" value="%(gameport)d">
|
||||
%(names1)s
|
||||
</applet>
|
||||
<br>
|
||||
<p align="center"><a href="name.html?%(names2)s">Player Names & Teams</a></p>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
NAME_LINE1 = '<param name="%s" value="%s">'
|
||||
NAME_SEP1 = '\n'
|
||||
NAME_LINE2 = '%s=%s'
|
||||
NAME_SEP2 = '&'
|
||||
|
||||
def playernames(options):
|
||||
NUM_PLAYERS = len(PLAYERNAMES)
|
||||
result = {}
|
||||
anyname = None
|
||||
for id in range(NUM_PLAYERS):
|
||||
keyid = 'player%d' % id
|
||||
if keyid in options:
|
||||
value = options[keyid][0]
|
||||
anyname = anyname or value
|
||||
teamid = 'team%d' % id
|
||||
if teamid in options:
|
||||
team = options[teamid][0]
|
||||
if len(team) == 1:
|
||||
value = '%s (%s)' % (value, team)
|
||||
result[keyid] = value
|
||||
if 'c' in options:
|
||||
for id in range(NUM_PLAYERS):
|
||||
keyid = 'player%d' % id
|
||||
try:
|
||||
del result[keyid]
|
||||
except KeyError:
|
||||
pass
|
||||
if 'f' in options:
|
||||
for id in range(NUM_PLAYERS):
|
||||
keyid = 'player%d' % id
|
||||
if not result.get(keyid):
|
||||
result[keyid] = anyname or PLAYERNAMES[id]
|
||||
else:
|
||||
anyname = result[keyid]
|
||||
return result
|
||||
|
||||
def indexloader(**options):
|
||||
if 'cheat' in options:
|
||||
for opt in options.pop('cheat'):
|
||||
__cheat(opt)
|
||||
import gamesrv
|
||||
if gamesrv.game is None:
|
||||
indexdata = EMPTY_PAGE
|
||||
else:
|
||||
names = playernames(options).items()
|
||||
indexdata = INDEX_PAGE % {
|
||||
'title': gamesrv.game.FnDesc,
|
||||
'width': gamesrv.game.width,
|
||||
'height': gamesrv.game.height,
|
||||
'gameport': gamesrv.game.address[1],
|
||||
'names1': NAME_SEP1.join([NAME_LINE1 % kv for kv in names]),
|
||||
'names2': NAME_SEP2.join([NAME_LINE2 % kv for kv in names]),
|
||||
}
|
||||
return StringIO(indexdata), 'text/html'
|
||||
|
||||
def nameloader(**options):
|
||||
if 's' in options:
|
||||
return indexloader(**options)
|
||||
locals = {
|
||||
'options': playernames(options),
|
||||
}
|
||||
return httpserver.load(os.path.join(DATADIR, 'name.html'),
|
||||
'text/html', locals=locals)
|
||||
|
||||
|
||||
wave_cache = {}
|
||||
|
||||
def wav2au(data):
|
||||
# Very limited! Assumes a standard 8-bit mono .wav as input
|
||||
import audioop, struct
|
||||
freq, = struct.unpack("<i", data[24:28])
|
||||
data = data[44:]
|
||||
data = audioop.bias(data, 1, -128)
|
||||
data, ignored = audioop.ratecv(data, 1, 1, freq, 8000, None)
|
||||
data = audioop.lin2ulaw(data, 1)
|
||||
data = struct.pack('>4siiiii8s',
|
||||
'.snd', # header
|
||||
struct.calcsize('>4siiiii8s'), # header size
|
||||
len(data), # data size
|
||||
1, # encoding
|
||||
8000, # sample rate
|
||||
1, # channels
|
||||
'magic.au') + data
|
||||
return data
|
||||
|
||||
def sampleloader(code=[], **options):
|
||||
import gamesrv
|
||||
try:
|
||||
data = wave_cache[code[0]]
|
||||
except KeyError:
|
||||
for key, snd in gamesrv.samples.items():
|
||||
if str(getattr(snd, 'code', '')) == code[0]:
|
||||
data = wave_cache[code[0]] = wav2au(snd.read())
|
||||
break
|
||||
else:
|
||||
raise KeyError, code[0]
|
||||
return StringIO(data), 'audio/wav'
|
||||
|
||||
|
||||
def setup():
|
||||
dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
os.pardir,
|
||||
'java'))
|
||||
if not os.path.isdir(dir):
|
||||
return
|
||||
|
||||
# register all '.class' files
|
||||
for name in os.listdir(dir):
|
||||
if name.endswith('.class'):
|
||||
httpserver.register(name, httpserver.fileloader(os.path.join(dir, name)))
|
||||
|
||||
# register a '', an 'index.html', and a 'name.html' file
|
||||
httpserver.register('', indexloader)
|
||||
httpserver.register('index.html', indexloader)
|
||||
httpserver.register('name.html', nameloader)
|
||||
|
||||
# 'name.html' has a few images, list the .png files in DATADIR
|
||||
for fn in os.listdir(DATADIR):
|
||||
fn = fn.lower()
|
||||
if fn.endswith('.png'):
|
||||
httpserver.register(fn, httpserver.fileloader(
|
||||
os.path.join(DATADIR, fn)))
|
||||
|
||||
# register the sample loader
|
||||
httpserver.register('sample.wav', sampleloader)
|
||||
|
||||
setup()
|
@ -1,8 +1,8 @@
|
||||
from __future__ import generators
|
||||
import cStringIO
|
||||
|
||||
import io
|
||||
|
||||
def decodepixmap(data):
|
||||
f = cStringIO.StringIO(data)
|
||||
f = io.StringIO(data)
|
||||
sig = f.readline().strip()
|
||||
assert sig == "P6"
|
||||
while 1:
|
||||
@ -10,7 +10,7 @@ def decodepixmap(data):
|
||||
if not line.startswith('#'):
|
||||
break
|
||||
wh = line.split()
|
||||
w, h = map(int, wh)
|
||||
w, h = list(map(int, wh))
|
||||
sig = f.readline().strip()
|
||||
assert sig == "255"
|
||||
data = f.read()
|
||||
@ -20,7 +20,9 @@ def decodepixmap(data):
|
||||
def encodepixmap(w, h, data):
|
||||
return 'P6\n%d %d\n255\n%s' % (w, h, data)
|
||||
|
||||
def cropimage((w, h, data), (x1, y1, w1, h1)):
|
||||
def cropimage(xxx_todo_changeme, xxx_todo_changeme1):
|
||||
(w, h, data) = xxx_todo_changeme
|
||||
(x1, y1, w1, h1) = xxx_todo_changeme1
|
||||
assert 0 <= x1 <= x1+w1 <= w
|
||||
assert 0 <= y1 <= y1+h1 <= h
|
||||
scanline = w*3
|
||||
@ -80,10 +82,12 @@ translation_darker = ('\x00\x01' + '\x00'*126 +
|
||||
''.join([chr(n//4) for n in range(0,128)]))
|
||||
translation_dragon = translation_darker[:255] + '\xC0'
|
||||
|
||||
def make_dark((w, h, data), translation):
|
||||
def make_dark(xxx_todo_changeme2, translation):
|
||||
(w, h, data) = xxx_todo_changeme2
|
||||
return w, h, data.translate(translation)
|
||||
|
||||
def col((r, g, b)):
|
||||
def col(xxx_todo_changeme3):
|
||||
(r, g, b) = xxx_todo_changeme3
|
||||
r = ord(r)
|
||||
g = ord(g)
|
||||
b = ord(b)
|
||||
|
163
common/pixmap.py.bak
Normal file
163
common/pixmap.py.bak
Normal file
@ -0,0 +1,163 @@
|
||||
from __future__ import generators
|
||||
import cStringIO
|
||||
|
||||
def decodepixmap(data):
|
||||
f = cStringIO.StringIO(data)
|
||||
sig = f.readline().strip()
|
||||
assert sig == "P6"
|
||||
while 1:
|
||||
line = f.readline().strip()
|
||||
if not line.startswith('#'):
|
||||
break
|
||||
wh = line.split()
|
||||
w, h = map(int, wh)
|
||||
sig = f.readline().strip()
|
||||
assert sig == "255"
|
||||
data = f.read()
|
||||
f.close()
|
||||
return w, h, data
|
||||
|
||||
def encodepixmap(w, h, data):
|
||||
return 'P6\n%d %d\n255\n%s' % (w, h, data)
|
||||
|
||||
def cropimage((w, h, data), (x1, y1, w1, h1)):
|
||||
assert 0 <= x1 <= x1+w1 <= w
|
||||
assert 0 <= y1 <= y1+h1 <= h
|
||||
scanline = w*3
|
||||
lines = [data[p:p+w1*3]
|
||||
for p in range(y1*scanline + x1*3,
|
||||
(y1+h1)*scanline + x1*3,
|
||||
scanline)]
|
||||
return w1, h1, ''.join(lines)
|
||||
|
||||
def vflip(w, h, data):
|
||||
scanline = w*3
|
||||
lines = [data[p:p+scanline] for p in range(0, len(data), scanline)]
|
||||
lines.reverse()
|
||||
return ''.join(lines)
|
||||
|
||||
def hflip(w, h, data):
|
||||
scanline = w*3
|
||||
lines = [''.join([data[p:p+3] for p in range(p1+scanline-3, p1-3, -3)])
|
||||
for p1 in range(0, len(data), scanline)]
|
||||
return ''.join(lines)
|
||||
|
||||
def rotate_cw(w, h, data):
|
||||
scanline = w*3
|
||||
lastline = len(data) - scanline
|
||||
lines = [''.join([data[p:p+3] for p in range(lastline + p1, -1, -scanline)])
|
||||
for p1 in range(0, scanline, 3)]
|
||||
return ''.join(lines)
|
||||
|
||||
def rotate_ccw(w, h, data):
|
||||
scanline = w*3
|
||||
lines = [''.join([data[p:p+3] for p in range(p1, len(data), scanline)])
|
||||
for p1 in range(scanline-3, -3, -3)]
|
||||
return ''.join(lines)
|
||||
|
||||
def rotate_180(w, h, data):
|
||||
scanline = w*3
|
||||
lines = [''.join([data[p:p+3] for p in range(p1+scanline-3, p1-3, -3)])
|
||||
for p1 in range(0, len(data), scanline)]
|
||||
lines.reverse()
|
||||
return ''.join(lines)
|
||||
|
||||
def makebkgnd(w, h, data):
|
||||
scanline = 3*w
|
||||
result = []
|
||||
for position in range(0, scanline*h, scanline):
|
||||
line = []
|
||||
for p in range(position, position+scanline, 3):
|
||||
line.append(2 * (chr(ord(data[p ]) >> 3) +
|
||||
chr(ord(data[p+1]) >> 3) +
|
||||
chr(ord(data[p+2]) >> 3)))
|
||||
line = ''.join(line)
|
||||
result.append(line)
|
||||
result.append(line)
|
||||
return w*2, h*2, ''.join(result)
|
||||
|
||||
translation_darker = ('\x00\x01' + '\x00'*126 +
|
||||
''.join([chr(n//4) for n in range(0,128)]))
|
||||
translation_dragon = translation_darker[:255] + '\xC0'
|
||||
|
||||
def make_dark((w, h, data), translation):
|
||||
return w, h, data.translate(translation)
|
||||
|
||||
def col((r, g, b)):
|
||||
r = ord(r)
|
||||
g = ord(g)
|
||||
b = ord(b)
|
||||
return ((g>>2 + r>>3) << 24) | (b << 16) | (g << 8) | r
|
||||
|
||||
def imagezoomer(w, h, data):
|
||||
"Zoom a cartoon image by a factor of three, progressively."
|
||||
scale = 3
|
||||
scanline = 3*w
|
||||
rw = (w-1)*scale+1
|
||||
rh = (h-1)*scale+1
|
||||
pixels = []
|
||||
colcache = {}
|
||||
revcache = {}
|
||||
for base in range(0, scanline*h, scanline):
|
||||
line = []
|
||||
for x in range(w):
|
||||
key = data[base + 3*x : base + 3*(x+1)]
|
||||
try:
|
||||
c = colcache[key]
|
||||
except KeyError:
|
||||
c = colcache[key] = col(key)
|
||||
revcache[c] = key
|
||||
line.append(c)
|
||||
pixels.append(line)
|
||||
yield None
|
||||
|
||||
Pairs = {
|
||||
(0, 0): [(0, 0, 0, 0),
|
||||
(-1,0, 1, 0),
|
||||
(0,-1, 0, 1)],
|
||||
(1, 0): [(0, 0, 1, 0),
|
||||
(0, 1, 1,-1),
|
||||
(0,-1, 1, 1)],
|
||||
(2, 0): [(0, 0, 1, 0),
|
||||
(0, 1, 1,-1),
|
||||
(0,-1, 1, 1)],
|
||||
(0, 1): [(0, 0, 0, 1),
|
||||
(-1,0, 1, 1),
|
||||
(1, 0,-1, 1)],
|
||||
(1, 1): [(0, 0, 1, 1),
|
||||
(0, 1, 1, -1),
|
||||
(1, 0,-1, 1)],
|
||||
(2, 1): [(1, 0, 0, 1),
|
||||
(0,-1, 1, 1),
|
||||
(0, 0, 2, 1)],
|
||||
(0, 2): [(0, 0, 0, 1),
|
||||
(-1,0, 1, 1),
|
||||
(1, 0,-1, 1)],
|
||||
(1, 2): [(0, 1, 1, 0),
|
||||
(-1,0, 1, 1),
|
||||
(0, 0, 1, 2)],
|
||||
(2, 2): [(0, 0, 1, 1),
|
||||
(0, 1, 2, 0),
|
||||
(1, 0, 0, 2)],
|
||||
}
|
||||
result = []
|
||||
for y in range(rh):
|
||||
yield None
|
||||
for x in range(rw):
|
||||
# ______________________________
|
||||
|
||||
i = x//scale
|
||||
j = y//scale
|
||||
ps = []
|
||||
for dx1, dy1, dx2, dy2 in Pairs[x%scale, y%scale]:
|
||||
if (0 <= i+dx1 < w and 0 <= i+dx2 < w and
|
||||
0 <= j+dy1 < h and 0 <= j+dy2 < h):
|
||||
p1 = pixels[j+dy1][i+dx1]
|
||||
p2 = pixels[j+dy2][i+dx2]
|
||||
ps.append(max(p1, p2))
|
||||
p1 = min(ps)
|
||||
|
||||
# ______________________________
|
||||
result.append(revcache[p1])
|
||||
data = ''.join(result)
|
||||
yield (rw, rh, data)
|
@ -24,7 +24,7 @@ class LogFile:
|
||||
self.f.close()
|
||||
self.f = None
|
||||
|
||||
def __nonzero__(self):
|
||||
def __bool__(self):
|
||||
return self.f is not None
|
||||
|
||||
def _open(self, filename):
|
||||
@ -42,8 +42,8 @@ class LogFile:
|
||||
return 0
|
||||
self.filename = filename
|
||||
if self.f.tell() > 0:
|
||||
print >> self.f
|
||||
print >> self.f, '='*44
|
||||
print(file=self.f)
|
||||
print('='*44, file=self.f)
|
||||
return 1
|
||||
|
||||
def _check(self):
|
||||
|
106
common/stdlog.py.bak
Normal file
106
common/stdlog.py.bak
Normal file
@ -0,0 +1,106 @@
|
||||
import sys, os
|
||||
from time import localtime, ctime
|
||||
|
||||
|
||||
class LogFile:
|
||||
|
||||
def __init__(self, filename=None, limitsize=32768):
|
||||
if filename is None:
|
||||
filename = sys.argv[0]
|
||||
if filename.endswith('.py'):
|
||||
filename = filename[:-3]
|
||||
filename += '.log'
|
||||
self.limitsize = limitsize
|
||||
if not self._open(filename):
|
||||
import tempfile
|
||||
filename = os.path.join(tempfile.gettempdir(),
|
||||
os.path.basename(filename))
|
||||
if not self._open(filename):
|
||||
self.f = self.filename = None
|
||||
self.lasttime = None
|
||||
|
||||
def close(self):
|
||||
if self.f is not None:
|
||||
self.f.close()
|
||||
self.f = None
|
||||
|
||||
def __nonzero__(self):
|
||||
return self.f is not None
|
||||
|
||||
def _open(self, filename):
|
||||
try:
|
||||
self.f = open(filename, 'r+', 1)
|
||||
self.f.seek(0, 2)
|
||||
except IOError:
|
||||
# The open r+ might have failed simply because the file
|
||||
# does not exist. Try to create it.
|
||||
try:
|
||||
self.f = open(filename, 'w+', 1)
|
||||
except (OSError, IOError):
|
||||
return 0
|
||||
except OSError:
|
||||
return 0
|
||||
self.filename = filename
|
||||
if self.f.tell() > 0:
|
||||
print >> self.f
|
||||
print >> self.f, '='*44
|
||||
return 1
|
||||
|
||||
def _check(self):
|
||||
if self.f is None:
|
||||
return 0
|
||||
lt = localtime()
|
||||
if lt[:4] != self.lasttime:
|
||||
self.lasttime = lt[:4]
|
||||
if self.f.tell() >= self.limitsize:
|
||||
self.f.seek(-(self.limitsize>>1), 1)
|
||||
data = self.f.read()
|
||||
self.f.seek(0)
|
||||
self.f.write('(...)' + data)
|
||||
self.f.truncate()
|
||||
self.f.write('========= %s =========\n' % ctime())
|
||||
return 1
|
||||
|
||||
def write(self, data):
|
||||
if self._check():
|
||||
self.f.write(data)
|
||||
|
||||
def writelines(self, data):
|
||||
if self._check():
|
||||
self.f.writelines(data)
|
||||
|
||||
def flush(self):
|
||||
if self._check():
|
||||
self.f.flush()
|
||||
|
||||
|
||||
class Logger:
|
||||
stdout_captured = 0
|
||||
stderr_captured = 0
|
||||
|
||||
def __init__(self, f):
|
||||
self.targets = [f]
|
||||
|
||||
def capture_stdout(self):
|
||||
if not Logger.stdout_captured:
|
||||
self.targets.append(sys.stdout)
|
||||
sys.stdout = self
|
||||
Logger.stdout_captured = 1
|
||||
|
||||
def capture_stderr(self):
|
||||
if not Logger.stderr_captured:
|
||||
self.targets.append(sys.stderr)
|
||||
sys.stderr = self
|
||||
Logger.stderr_captured = 1
|
||||
|
||||
def write(self, data):
|
||||
for f in self.targets:
|
||||
f.write(data)
|
||||
|
||||
def writelines(self, data):
|
||||
for f in self.targets:
|
||||
f.writelines(data)
|
||||
|
||||
def flush(self):
|
||||
for f in self.targets:
|
||||
f.flush()
|
@ -1,5 +1,5 @@
|
||||
from socket import *
|
||||
from msgstruct import *
|
||||
from .msgstruct import *
|
||||
#from fcntl import ioctl
|
||||
#from termios import TIOCOUTQ
|
||||
from zlib import compressobj, Z_SYNC_FLUSH
|
||||
@ -19,12 +19,12 @@ class SocketMarshaller:
|
||||
# try to reduce TCP latency
|
||||
try:
|
||||
tcpsock.setsockopt(SOL_IP, IP_TOS, 0x10) # IPTOS_LOWDELAY
|
||||
except error, e:
|
||||
print "Cannot set IPTOS_LOWDELAY for client:", str(e)
|
||||
except error as e:
|
||||
print("Cannot set IPTOS_LOWDELAY for client:", str(e))
|
||||
try:
|
||||
tcpsock.setsockopt(SOL_TCP, TCP_NODELAY, 1)
|
||||
except error, e:
|
||||
print "Cannot set TCP_NODELAY for client:", str(e)
|
||||
except error as e:
|
||||
print("Cannot set TCP_NODELAY for client:", str(e))
|
||||
compressor = compressobj(6)
|
||||
self.compress = compressor.compress
|
||||
self.compress_flush = compressor.flush
|
||||
|
46
common/udpovertcp.py.bak
Normal file
46
common/udpovertcp.py.bak
Normal file
@ -0,0 +1,46 @@
|
||||
from socket import *
|
||||
from msgstruct import *
|
||||
#from fcntl import ioctl
|
||||
#from termios import TIOCOUTQ
|
||||
from zlib import compressobj, Z_SYNC_FLUSH
|
||||
import struct
|
||||
|
||||
ZeroBuffer = struct.pack("i", 0)
|
||||
|
||||
|
||||
class SocketMarshaller:
|
||||
|
||||
def __init__(self, tcpsock, mixer):
|
||||
self.tcpsock = tcpsock
|
||||
self.mixer = mixer
|
||||
self.mixer_can_mix = mixer.send_can_mix
|
||||
self.mixer_send = mixer.send_buffer
|
||||
self.tcpsock_fd = tcpsock.fileno()
|
||||
# try to reduce TCP latency
|
||||
try:
|
||||
tcpsock.setsockopt(SOL_IP, IP_TOS, 0x10) # IPTOS_LOWDELAY
|
||||
except error, e:
|
||||
print "Cannot set IPTOS_LOWDELAY for client:", str(e)
|
||||
try:
|
||||
tcpsock.setsockopt(SOL_TCP, TCP_NODELAY, 1)
|
||||
except error, e:
|
||||
print "Cannot set TCP_NODELAY for client:", str(e)
|
||||
compressor = compressobj(6)
|
||||
self.compress = compressor.compress
|
||||
self.compress_flush = compressor.flush
|
||||
|
||||
def send(self, data):
|
||||
if self.mixer_can_mix():
|
||||
# discard all packets if there is still data waiting in tcpsock
|
||||
# --- mmmh, works much better without this check ---
|
||||
#try:
|
||||
# if ioctl(self.tcpsock_fd, TIOCOUTQ, ZeroBuffer) != ZeroBuffer:
|
||||
# return
|
||||
#except IOError, e:
|
||||
# print "ioctl(TIOCOUTQ) failed, disconnecting client"
|
||||
# self.mixer.disconnect(e)
|
||||
#else:
|
||||
data = self.compress(data) + self.compress_flush(Z_SYNC_FLUSH)
|
||||
self.mixer_send(message(MSG_INLINE_FRAME, data))
|
||||
return len(data)
|
||||
return 0
|
@ -16,8 +16,8 @@ LOCALDIR = os.path.dirname(os.path.abspath(LOCALDIR))
|
||||
sys.path.insert(0, os.path.dirname(LOCALDIR))
|
||||
sys.path.insert(0, LOCALDIR)
|
||||
import common
|
||||
import pclient
|
||||
import modes
|
||||
from . import pclient
|
||||
from . import modes
|
||||
|
||||
|
||||
UdpLookForServer = [
|
||||
@ -28,42 +28,42 @@ UdpLookForServer = [
|
||||
def parse_cmdline(argv):
|
||||
# parse command-line
|
||||
def usage():
|
||||
print >> sys.stderr, 'usage:'
|
||||
print >> sys.stderr, ' python Client.py [-d#] [-s#] [extra options] [host[:port]]'
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, 'options:'
|
||||
print >> sys.stderr, ' host search for a game on the given machine'
|
||||
print >> sys.stderr, ' host:port connect to the given game server'
|
||||
print >> sys.stderr, ' (default search for any local server)'
|
||||
print >> sys.stderr, ' -d# --display=# graphic driver (see below)'
|
||||
print >> sys.stderr, ' -s# --sound=# sound driver (see below)'
|
||||
print >> sys.stderr, ' --music=no disable background music'
|
||||
print >> sys.stderr, ' -h --help display this text'
|
||||
print >> sys.stderr, ' -m --metaserver connect with the help of the metaserver'
|
||||
print >> sys.stderr, ' (list servers with Client.py -m)'
|
||||
print >> sys.stderr, ' -t --tcp for slow or proxy connections'
|
||||
print >> sys.stderr, ' -u --udp for fast direct connections'
|
||||
print >> sys.stderr, ' (default is to autodetect tcp or udp)'
|
||||
print >> sys.stderr, ' --port UDP=# or #:# fixed inbound udp port or host:port'
|
||||
print >> sys.stderr, ' --port TCP=# fixed inbound tcp port (-m only)'
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, 'graphic drivers:'
|
||||
print('usage:', file=sys.stderr)
|
||||
print(' python Client.py [-d#] [-s#] [extra options] [host[:port]]', file=sys.stderr)
|
||||
print(file=sys.stderr)
|
||||
print('options:', file=sys.stderr)
|
||||
print(' host search for a game on the given machine', file=sys.stderr)
|
||||
print(' host:port connect to the given game server', file=sys.stderr)
|
||||
print(' (default search for any local server)', file=sys.stderr)
|
||||
print(' -d# --display=# graphic driver (see below)', file=sys.stderr)
|
||||
print(' -s# --sound=# sound driver (see below)', file=sys.stderr)
|
||||
print(' --music=no disable background music', file=sys.stderr)
|
||||
print(' -h --help display this text', file=sys.stderr)
|
||||
print(' -m --metaserver connect with the help of the metaserver', file=sys.stderr)
|
||||
print(' (list servers with Client.py -m)', file=sys.stderr)
|
||||
print(' -t --tcp for slow or proxy connections', file=sys.stderr)
|
||||
print(' -u --udp for fast direct connections', file=sys.stderr)
|
||||
print(' (default is to autodetect tcp or udp)', file=sys.stderr)
|
||||
print(' --port UDP=# or #:# fixed inbound udp port or host:port', file=sys.stderr)
|
||||
print(' --port TCP=# fixed inbound tcp port (-m only)', file=sys.stderr)
|
||||
print(file=sys.stderr)
|
||||
print('graphic drivers:', file=sys.stderr)
|
||||
for info in modes.graphicmodeslist():
|
||||
info.printline(sys.stderr)
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, 'sound drivers:'
|
||||
print(file=sys.stderr)
|
||||
print('sound drivers:', file=sys.stderr)
|
||||
for info in modes.soundmodeslist():
|
||||
info.printline(sys.stderr)
|
||||
print >> sys.stderr
|
||||
print(file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
shortopts = 'd:s:htum'
|
||||
longopts = ['display=', 'sound=', 'music=', 'help', 'tcp', 'udp',
|
||||
'cfg=', 'metaserver', 'port=']
|
||||
for info in modes.graphicmodeslist() + modes.soundmodeslist():
|
||||
short, long = info.getformaloptions()
|
||||
short, int = info.getformaloptions()
|
||||
shortopts += short
|
||||
longopts += long
|
||||
longopts += int
|
||||
try:
|
||||
from getopt import gnu_getopt as getopt
|
||||
except ImportError:
|
||||
@ -71,9 +71,9 @@ def parse_cmdline(argv):
|
||||
from getopt import error
|
||||
try:
|
||||
opts, args = getopt(argv, shortopts, longopts)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'Client.py: %s' % str(e)
|
||||
print >> sys.stderr
|
||||
except error as e:
|
||||
print('Client.py: %s' % str(e), file=sys.stderr)
|
||||
print(file=sys.stderr)
|
||||
usage()
|
||||
|
||||
metaserver = 0
|
||||
@ -144,7 +144,7 @@ def parse_cmdline(argv):
|
||||
return directconnect(server), mode
|
||||
|
||||
def directconnect(sockaddr):
|
||||
print "connecting to %s:%d..." % sockaddr
|
||||
print("connecting to %s:%d..." % sockaddr)
|
||||
from socket import socket, AF_INET, SOCK_STREAM
|
||||
s = socket(AF_INET, SOCK_STREAM)
|
||||
s.connect(sockaddr)
|
||||
|
170
display/Client.py.bak
Normal file
170
display/Client.py.bak
Normal file
@ -0,0 +1,170 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# __________
|
||||
import os, sys
|
||||
if __name__ == '__main__':
|
||||
LOCALDIR = sys.argv[0]
|
||||
else:
|
||||
LOCALDIR = __file__
|
||||
try:
|
||||
LOCALDIR = os.readlink(LOCALDIR)
|
||||
except:
|
||||
pass
|
||||
LOCALDIR = os.path.dirname(os.path.abspath(LOCALDIR))
|
||||
# ----------
|
||||
|
||||
sys.path.insert(0, os.path.dirname(LOCALDIR))
|
||||
sys.path.insert(0, LOCALDIR)
|
||||
import common
|
||||
import pclient
|
||||
import modes
|
||||
|
||||
|
||||
UdpLookForServer = [
|
||||
'127.0.0.1',
|
||||
'<broadcast>',
|
||||
]
|
||||
|
||||
def parse_cmdline(argv):
|
||||
# parse command-line
|
||||
def usage():
|
||||
print >> sys.stderr, 'usage:'
|
||||
print >> sys.stderr, ' python Client.py [-d#] [-s#] [extra options] [host[:port]]'
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, 'options:'
|
||||
print >> sys.stderr, ' host search for a game on the given machine'
|
||||
print >> sys.stderr, ' host:port connect to the given game server'
|
||||
print >> sys.stderr, ' (default search for any local server)'
|
||||
print >> sys.stderr, ' -d# --display=# graphic driver (see below)'
|
||||
print >> sys.stderr, ' -s# --sound=# sound driver (see below)'
|
||||
print >> sys.stderr, ' --music=no disable background music'
|
||||
print >> sys.stderr, ' -h --help display this text'
|
||||
print >> sys.stderr, ' -m --metaserver connect with the help of the metaserver'
|
||||
print >> sys.stderr, ' (list servers with Client.py -m)'
|
||||
print >> sys.stderr, ' -t --tcp for slow or proxy connections'
|
||||
print >> sys.stderr, ' -u --udp for fast direct connections'
|
||||
print >> sys.stderr, ' (default is to autodetect tcp or udp)'
|
||||
print >> sys.stderr, ' --port UDP=# or #:# fixed inbound udp port or host:port'
|
||||
print >> sys.stderr, ' --port TCP=# fixed inbound tcp port (-m only)'
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, 'graphic drivers:'
|
||||
for info in modes.graphicmodeslist():
|
||||
info.printline(sys.stderr)
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, 'sound drivers:'
|
||||
for info in modes.soundmodeslist():
|
||||
info.printline(sys.stderr)
|
||||
print >> sys.stderr
|
||||
sys.exit(2)
|
||||
|
||||
shortopts = 'd:s:htum'
|
||||
longopts = ['display=', 'sound=', 'music=', 'help', 'tcp', 'udp',
|
||||
'cfg=', 'metaserver', 'port=']
|
||||
for info in modes.graphicmodeslist() + modes.soundmodeslist():
|
||||
short, long = info.getformaloptions()
|
||||
shortopts += short
|
||||
longopts += long
|
||||
try:
|
||||
from getopt import gnu_getopt as getopt
|
||||
except ImportError:
|
||||
from getopt import getopt
|
||||
from getopt import error
|
||||
try:
|
||||
opts, args = getopt(argv, shortopts, longopts)
|
||||
except error, e:
|
||||
print >> sys.stderr, 'Client.py: %s' % str(e)
|
||||
print >> sys.stderr
|
||||
usage()
|
||||
|
||||
metaserver = 0
|
||||
driver = sound = None
|
||||
extraopts = {}
|
||||
for key, value in opts:
|
||||
if key in ('-d', '--display'):
|
||||
driver = value
|
||||
elif key in ('-s', '--sound'):
|
||||
sound = value
|
||||
elif key in ('-t', '--tcp'):
|
||||
extraopts['udp_over_tcp'] = 1
|
||||
elif key in ('-u', '--udp'):
|
||||
extraopts['udp_over_tcp'] = 0
|
||||
elif key in ('-m', '--metaserver'):
|
||||
metaserver = 1
|
||||
elif key == '--port':
|
||||
import common.msgstruct
|
||||
try:
|
||||
portname, value = value.split('=')
|
||||
if portname == 'UDP':
|
||||
portname = 'CLIENT'
|
||||
elif portname == 'TCP':
|
||||
portname = 'BACK'
|
||||
except ValueError:
|
||||
portname = 'CLIENT'
|
||||
if portname == 'CLIENT' and ':' in value:
|
||||
udphostname, value = value.split(':')
|
||||
common.msgstruct.PORTS['sendudpto'] = udphostname
|
||||
common.msgstruct.PORTS[portname] = int(value)
|
||||
elif key == '--cfg':
|
||||
extraopts['cfgfile'] = value
|
||||
elif key in ('-h', '--help'):
|
||||
usage()
|
||||
else:
|
||||
extraopts[key] = value
|
||||
mode = driver, sound, extraopts
|
||||
|
||||
if metaserver:
|
||||
if len(args) == 0:
|
||||
metalist()
|
||||
sys.exit(0)
|
||||
elif len(args) != 1 or ':' not in args[0]:
|
||||
usage()
|
||||
return metaconnect(args[0]), mode
|
||||
|
||||
if args:
|
||||
if len(args) > 1:
|
||||
usage()
|
||||
hosts = args[0].split(':')
|
||||
if len(hosts) == 1:
|
||||
host, = hosts
|
||||
from common import hostchooser
|
||||
server = hostchooser.pick([host] * 5)
|
||||
elif len(hosts) == 2:
|
||||
host, port = hosts
|
||||
try:
|
||||
port = int(port)
|
||||
except ValueError:
|
||||
usage()
|
||||
server = host, port
|
||||
else:
|
||||
usage()
|
||||
return directconnect(server), mode
|
||||
|
||||
from common import hostchooser
|
||||
server = hostchooser.pick(UdpLookForServer * 3)
|
||||
return directconnect(server), mode
|
||||
|
||||
def directconnect(sockaddr):
|
||||
print "connecting to %s:%d..." % sockaddr
|
||||
from socket import socket, AF_INET, SOCK_STREAM
|
||||
s = socket(AF_INET, SOCK_STREAM)
|
||||
s.connect(sockaddr)
|
||||
return s, sockaddr
|
||||
|
||||
def metaconnect(metaaddr):
|
||||
from metaserver import metaclient
|
||||
import common.msgstruct
|
||||
port = common.msgstruct.PORTS.get('BACK')
|
||||
s = metaclient.meta_connect(metaaddr, port)
|
||||
sockaddr = s.getpeername()
|
||||
return s, sockaddr
|
||||
|
||||
def metalist():
|
||||
from metaserver import metaclient
|
||||
metaclient.print_server_list()
|
||||
|
||||
def main():
|
||||
(s, sockaddr), mode = parse_cmdline(sys.argv[1:])
|
||||
pclient.run(s, sockaddr, mode)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,4 +1,4 @@
|
||||
from __future__ import generators
|
||||
|
||||
import os, md5, sys
|
||||
#import common.debug
|
||||
|
||||
@ -18,7 +18,7 @@ class FileCache:
|
||||
del self.cache[filename]
|
||||
if filename not in self.cache:
|
||||
if len(self.cache) >= FileCache.MAX_FILES:
|
||||
(time, mode, f), k = min([(v,k) for (k,v) in self.cache.items()])
|
||||
(time, mode, f), k = min([(v,k) for (k,v) in list(self.cache.items())])
|
||||
f.close()
|
||||
del self.cache[k]
|
||||
try:
|
||||
@ -54,13 +54,13 @@ class FileBlock:
|
||||
def overwrite(self, newdata):
|
||||
self.memorydata = newdata
|
||||
if self.readonly:
|
||||
print >> sys.stderr, "cannot overwrite file", self.filename
|
||||
print("cannot overwrite file", self.filename, file=sys.stderr)
|
||||
return
|
||||
try:
|
||||
f = Data.Cache.access(self.filename, self.position, writing=1)
|
||||
f.write(newdata)
|
||||
except (IOError, OSError):
|
||||
print >> sys.stderr, "cache write error:", self.filename
|
||||
print("cache write error:", self.filename, file=sys.stderr)
|
||||
return
|
||||
self.complete = 1
|
||||
del self.memorydata
|
||||
@ -107,7 +107,7 @@ class Data:
|
||||
f.write(data)
|
||||
f.flush()
|
||||
except (IOError, OSError):
|
||||
print >> sys.stderr, "cache write error:", self.backupfile
|
||||
print("cache write error:", self.backupfile, file=sys.stderr)
|
||||
|
||||
def loadfrom(self, filename, position, length, checksum):
|
||||
"""Try to load data from the given filename, with the given
|
||||
@ -128,19 +128,19 @@ class Data:
|
||||
# correct data
|
||||
self.store(position, data, name, readonly)
|
||||
return 1
|
||||
if self.content is not None and not self.content.has_key(position):
|
||||
if self.content is not None and position not in self.content:
|
||||
self.content[position] = FileBlock(cachename, position, length,
|
||||
readonly=0, complete=0)
|
||||
elif self.readonly:
|
||||
print >> sys.stderr, "Note: the music data has changed. You can get"
|
||||
print >> sys.stderr, "the server's version by deleting", directname
|
||||
print("Note: the music data has changed. You can get", file=sys.stderr)
|
||||
print("the server's version by deleting", directname, file=sys.stderr)
|
||||
return 1 # incorrect data, but ignored
|
||||
return 0
|
||||
|
||||
def read(self):
|
||||
"""Return the data as built so far."""
|
||||
if self.content is not None:
|
||||
items = self.content.items()
|
||||
items = list(self.content.items())
|
||||
items.sort()
|
||||
result = ''
|
||||
for position, block in items:
|
||||
@ -155,7 +155,7 @@ class Data:
|
||||
|
||||
def fopen(self):
|
||||
if self.content is not None:
|
||||
from cStringIO import StringIO
|
||||
from io import StringIO
|
||||
return StringIO(self.read())
|
||||
else:
|
||||
return Data.Cache.access(self.backupfile, 0)
|
||||
@ -166,19 +166,19 @@ class Data:
|
||||
the file that we want."""
|
||||
if not self.backupfile:
|
||||
files = {}
|
||||
for position, block in self.content.items():
|
||||
for position, block in list(self.content.items()):
|
||||
if not isinstance(block, FileBlock):
|
||||
break
|
||||
if block.complete:
|
||||
files[block.filename] = block
|
||||
else:
|
||||
if len(files) == 1:
|
||||
self.backupfile, block = files.items()[0]
|
||||
self.backupfile, block = list(files.items())[0]
|
||||
self.readonly = block.readonly
|
||||
if not self.backupfile:
|
||||
self.backupfile = mktemp(fileexthint)
|
||||
f = Data.Cache.access(self.backupfile, 0, writing=1)
|
||||
for position, block in self.content.items():
|
||||
for position, block in list(self.content.items()):
|
||||
f.seek(position)
|
||||
f.write(block.read())
|
||||
f.flush()
|
||||
@ -258,4 +258,4 @@ def enumtempfiles():
|
||||
i += 1
|
||||
|
||||
def mktemp(fileext, gen = enumtempfiles()):
|
||||
return gen.next() + fileext
|
||||
return next(gen) + fileext
|
||||
|
261
display/caching.py.bak
Normal file
261
display/caching.py.bak
Normal file
@ -0,0 +1,261 @@
|
||||
from __future__ import generators
|
||||
import os, md5, sys
|
||||
#import common.debug
|
||||
|
||||
|
||||
class FileCache:
|
||||
MAX_FILES = 8
|
||||
|
||||
def __init__(self):
|
||||
self.cache = {}
|
||||
self.time = 0
|
||||
|
||||
def access(self, filename, position, writing=0):
|
||||
if filename in self.cache:
|
||||
time, mode, f = self.cache[filename]
|
||||
if writing > mode:
|
||||
f.close()
|
||||
del self.cache[filename]
|
||||
if filename not in self.cache:
|
||||
if len(self.cache) >= FileCache.MAX_FILES:
|
||||
(time, mode, f), k = min([(v,k) for (k,v) in self.cache.items()])
|
||||
f.close()
|
||||
del self.cache[k]
|
||||
try:
|
||||
f = open(filename, ('rb', 'r+b')[writing])
|
||||
except (IOError, OSError):
|
||||
if not writing:
|
||||
raise
|
||||
if not os.path.isdir(os.path.dirname(filename)):
|
||||
os.mkdir(os.path.dirname(filename))
|
||||
f = open(filename, 'w+b')
|
||||
mode = writing
|
||||
self.time += 1
|
||||
self.cache[filename] = self.time, mode, f
|
||||
f.seek(position)
|
||||
return f
|
||||
|
||||
|
||||
class MemoryBlock:
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
def overwrite(self, newdata):
|
||||
self.data = newdata
|
||||
def read(self):
|
||||
return self.data
|
||||
|
||||
class FileBlock:
|
||||
def __init__(self, filename, position, length, readonly=1, complete=1):
|
||||
self.filename = filename
|
||||
self.position = position
|
||||
self.length = length
|
||||
self.readonly = readonly
|
||||
self.complete = complete
|
||||
def overwrite(self, newdata):
|
||||
self.memorydata = newdata
|
||||
if self.readonly:
|
||||
print >> sys.stderr, "cannot overwrite file", self.filename
|
||||
return
|
||||
try:
|
||||
f = Data.Cache.access(self.filename, self.position, writing=1)
|
||||
f.write(newdata)
|
||||
except (IOError, OSError):
|
||||
print >> sys.stderr, "cache write error:", self.filename
|
||||
return
|
||||
self.complete = 1
|
||||
del self.memorydata
|
||||
def read(self):
|
||||
if self.complete:
|
||||
f = Data.Cache.access(self.filename, self.position)
|
||||
return f.read(self.length)
|
||||
else:
|
||||
return self.memorydata
|
||||
|
||||
|
||||
class Data:
|
||||
SafeChars = {}
|
||||
for c in ".abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789":
|
||||
SafeChars[c] = c
|
||||
Translate = ''.join([SafeChars.get(chr(c), '_') for c in range(256)])
|
||||
del c, SafeChars
|
||||
Cache = FileCache()
|
||||
|
||||
def __init__(self):
|
||||
self.content = {}
|
||||
self.backupfile = None
|
||||
self.readonly = 0
|
||||
|
||||
clear = __init__
|
||||
|
||||
### Public interface ###
|
||||
|
||||
def store(self, position, data, filename=None, readonly=1):
|
||||
"""This class assumes that all accesses to block within the data
|
||||
are done for disjoint intervals: no overlapping writes !"""
|
||||
if self.content is not None:
|
||||
try:
|
||||
self.content[position].overwrite(data)
|
||||
except KeyError:
|
||||
if filename is None:
|
||||
self.content[position] = MemoryBlock(data)
|
||||
else:
|
||||
self.content[position] = FileBlock(filename, position,
|
||||
len(data), readonly)
|
||||
if self.backupfile and not self.readonly:
|
||||
try:
|
||||
f = Data.Cache.access(self.backupfile, position, writing=1)
|
||||
f.write(data)
|
||||
f.flush()
|
||||
except (IOError, OSError):
|
||||
print >> sys.stderr, "cache write error:", self.backupfile
|
||||
|
||||
def loadfrom(self, filename, position, length, checksum):
|
||||
"""Try to load data from the given filename, with the given
|
||||
expected MD5 checksum. The filename must be Unix-style, and is
|
||||
looked up both in the directory SOURCEDIR and with a mangled name
|
||||
in the cache directory CACHEDIR."""
|
||||
directname = os.path.join(self.SOURCEDIR, *filename.split('/'))
|
||||
mangledname = filename.translate(Data.Translate)
|
||||
cachename = os.path.join(self.CACHEDIR, mangledname)
|
||||
for name, readonly in ((directname, 1), (cachename, 0)):
|
||||
try:
|
||||
f = Data.Cache.access(name, position)
|
||||
data = f.read(length)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
else:
|
||||
if len(data) == length and md5.new(data).digest() == checksum:
|
||||
# correct data
|
||||
self.store(position, data, name, readonly)
|
||||
return 1
|
||||
if self.content is not None and not self.content.has_key(position):
|
||||
self.content[position] = FileBlock(cachename, position, length,
|
||||
readonly=0, complete=0)
|
||||
elif self.readonly:
|
||||
print >> sys.stderr, "Note: the music data has changed. You can get"
|
||||
print >> sys.stderr, "the server's version by deleting", directname
|
||||
return 1 # incorrect data, but ignored
|
||||
return 0
|
||||
|
||||
def read(self):
|
||||
"""Return the data as built so far."""
|
||||
if self.content is not None:
|
||||
items = self.content.items()
|
||||
items.sort()
|
||||
result = ''
|
||||
for position, block in items:
|
||||
if len(result) < position:
|
||||
result += '\x00' * (position-len(result))
|
||||
data = block.read()
|
||||
result = result[:position] + data + result[position+len(data):]
|
||||
return result
|
||||
else:
|
||||
f = Data.Cache.access(self.backupfile, 0)
|
||||
return f.read()
|
||||
|
||||
def fopen(self):
|
||||
if self.content is not None:
|
||||
from cStringIO import StringIO
|
||||
return StringIO(self.read())
|
||||
else:
|
||||
return Data.Cache.access(self.backupfile, 0)
|
||||
|
||||
def freezefilename(self, fileexthint='.wav'):
|
||||
"""Return the name of a file from which the data can be read. If all
|
||||
the current data comes from the same file, it is assumed to be exactly
|
||||
the file that we want."""
|
||||
if not self.backupfile:
|
||||
files = {}
|
||||
for position, block in self.content.items():
|
||||
if not isinstance(block, FileBlock):
|
||||
break
|
||||
if block.complete:
|
||||
files[block.filename] = block
|
||||
else:
|
||||
if len(files) == 1:
|
||||
self.backupfile, block = files.items()[0]
|
||||
self.readonly = block.readonly
|
||||
if not self.backupfile:
|
||||
self.backupfile = mktemp(fileexthint)
|
||||
f = Data.Cache.access(self.backupfile, 0, writing=1)
|
||||
for position, block in self.content.items():
|
||||
f.seek(position)
|
||||
f.write(block.read())
|
||||
f.flush()
|
||||
#print 'freezefilename ->', self.backupfile
|
||||
#print ' readonly =', self.readonly
|
||||
self.content = None
|
||||
return self.backupfile
|
||||
|
||||
# ____________________________________________________________
|
||||
# Temporary files management
|
||||
# from the 'py' lib, mostly written by hpk
|
||||
|
||||
def try_remove_dir(udir):
|
||||
try:
|
||||
for name in os.listdir(udir):
|
||||
try:
|
||||
os.unlink(os.path.join(udir, name))
|
||||
except:
|
||||
pass
|
||||
os.rmdir(udir)
|
||||
except:
|
||||
pass
|
||||
|
||||
def make_numbered_dir(prefix='tmp-bub-n-bros-', rootdir=None, keep=0,
|
||||
lock_timeout = 172800): # two days
|
||||
""" return unique directory with a number greater than the current
|
||||
maximum one. The number is assumed to start directly after prefix.
|
||||
Directories with a number less than (maxnum-keep) will be removed.
|
||||
"""
|
||||
import atexit, tempfile
|
||||
if rootdir is None:
|
||||
rootdir = tempfile.gettempdir()
|
||||
|
||||
def parse_num(bn):
|
||||
""" parse the number out of a path (if it matches the prefix) """
|
||||
if bn.startswith(prefix):
|
||||
try:
|
||||
return int(bn[len(prefix):])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# compute the maximum number currently in use with the
|
||||
# prefix
|
||||
maxnum = -1
|
||||
for basename in os.listdir(rootdir):
|
||||
num = parse_num(basename)
|
||||
if num is not None:
|
||||
maxnum = max(maxnum, num)
|
||||
|
||||
# make the new directory
|
||||
udir = os.path.join(rootdir, prefix + str(maxnum+1))
|
||||
os.mkdir(udir)
|
||||
|
||||
# try to remove the directory at process exit
|
||||
atexit.register(try_remove_dir, udir)
|
||||
|
||||
# prune old directories
|
||||
for basename in os.listdir(rootdir):
|
||||
num = parse_num(basename)
|
||||
if num is not None and num <= (maxnum - keep):
|
||||
d1 = os.path.join(rootdir, basename)
|
||||
try:
|
||||
t1 = os.stat(d1).st_mtime
|
||||
t2 = os.stat(udir).st_mtime
|
||||
if abs(t2-t1) < lock_timeout:
|
||||
continue # skip directories still recently used
|
||||
except:
|
||||
pass
|
||||
try_remove_dir(d1)
|
||||
return udir
|
||||
|
||||
def enumtempfiles():
|
||||
tempdir = make_numbered_dir()
|
||||
i = 0
|
||||
while True:
|
||||
yield os.path.join(tempdir, 'b%d' % i)
|
||||
i += 1
|
||||
|
||||
def mktemp(fileext, gen = enumtempfiles()):
|
||||
return gen.next() + fileext
|
@ -4,8 +4,8 @@
|
||||
################################################
|
||||
|
||||
import os, sys, math
|
||||
from modes import KeyPressed, KeyReleased
|
||||
import caching
|
||||
from .modes import KeyPressed, KeyReleased
|
||||
from . import caching
|
||||
|
||||
def import_trickery():
|
||||
global gtk, gdk
|
||||
@ -59,7 +59,8 @@ class Display:
|
||||
pb = self.pixmap(32, 32, ((pixel+hole)*16 + (hole+pixel)*16) * 16, 0x010101)
|
||||
self.taskbkgnd = self.renderpixbuf(pb)
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
def taskbar(self, xxx_todo_changeme):
|
||||
(x, y, w, h) = xxx_todo_changeme
|
||||
scale = self.scale
|
||||
x2 = x+w
|
||||
y2 = y+h
|
||||
@ -74,9 +75,9 @@ class Display:
|
||||
def pixmap(self, w, h, data, colorkey=-1):
|
||||
filename = self.tempppmfile
|
||||
f = open(filename, 'wb')
|
||||
print >> f, 'P6'
|
||||
print >> f, w, h
|
||||
print >> f, 255
|
||||
print('P6', file=f)
|
||||
print(w, h, file=f)
|
||||
print(255, file=f)
|
||||
f.write(data)
|
||||
f.close()
|
||||
pb = gdk.pixbuf_new_from_file(filename)
|
||||
@ -101,7 +102,8 @@ class Display:
|
||||
else:
|
||||
return (pixmap, self.gc, None)
|
||||
|
||||
def getopticon(self, input, (x, y, w, h), ignored_alpha=255):
|
||||
def getopticon(self, input, xxx_todo_changeme1, ignored_alpha=255):
|
||||
(x, y, w, h) = xxx_todo_changeme1
|
||||
if len(input) == 3:
|
||||
return None
|
||||
pb, = input
|
||||
@ -116,7 +118,8 @@ class Display:
|
||||
else:
|
||||
return self.renderpixbuf((newpb,))
|
||||
|
||||
def getppm(self, (x, y, w, h), int=int, ceil=math.ceil):
|
||||
def getppm(self, xxx_todo_changeme2, int=int, ceil=math.ceil):
|
||||
(x, y, w, h) = xxx_todo_changeme2
|
||||
scale = self.scale
|
||||
if isinstance(scale, int):
|
||||
x *= scale
|
||||
@ -134,7 +137,8 @@ class Display:
|
||||
bkgnd.draw_drawable(self.gc, self.offscreen, x, y, 0, 0, w, h)
|
||||
return bkgnd, self.gc, None
|
||||
|
||||
def putppm(self, x, y, (pixmap, gc, ignored), rect=None, int=int):
|
||||
def putppm(self, x, y, xxx_todo_changeme3, rect=None, int=int):
|
||||
(pixmap, gc, ignored) = xxx_todo_changeme3
|
||||
if pixmap is None:
|
||||
return
|
||||
scale = self.scale
|
||||
|
204
display/dpy_gtk.py.bak
Normal file
204
display/dpy_gtk.py.bak
Normal file
@ -0,0 +1,204 @@
|
||||
|
||||
################################################
|
||||
## GTK-based implementation of xshm ##
|
||||
################################################
|
||||
|
||||
import os, sys, math
|
||||
from modes import KeyPressed, KeyReleased
|
||||
import caching
|
||||
|
||||
def import_trickery():
|
||||
global gtk, gdk
|
||||
argv = sys.argv[:]
|
||||
del sys.argv[1:]
|
||||
import gtk
|
||||
from gtk import gdk
|
||||
sys.argv[:] = argv
|
||||
import_trickery()
|
||||
|
||||
|
||||
class Display:
|
||||
|
||||
def __init__(self, width, height, title, zoom="100"):
|
||||
if zoom.endswith('%'):
|
||||
zoom = zoom[:-1]
|
||||
scale = float(zoom) / 100.0
|
||||
iscale = int(scale+0.001)
|
||||
if abs(scale - iscale) < 0.002:
|
||||
scale = iscale
|
||||
self.scale = scale
|
||||
|
||||
self.width = int(width * scale)
|
||||
self.height = int(height * scale)
|
||||
self.tempppmfile = caching.mktemp('.ppm')
|
||||
|
||||
# create a top level window
|
||||
w = self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
w.connect("destroy", lambda w: sys.exit())
|
||||
w.connect("key-press-event", self.key_press_event)
|
||||
w.connect("key-release-event", self.key_release_event)
|
||||
w.connect("motion-notify-event", self.motion_notify_event)
|
||||
w.connect("button-press-event", self.button_press_event)
|
||||
w.add_events(gdk.KEY_PRESS_MASK |
|
||||
gdk.POINTER_MOTION_MASK |
|
||||
gdk.BUTTON_PRESS_MASK)
|
||||
w.resize(self.width, self.height)
|
||||
w.set_title(title)
|
||||
w.show()
|
||||
|
||||
self.offscreen = gtk.create_pixmap(w.window, self.width, self.height)
|
||||
self.gc = gdk.gc_new(w.window)
|
||||
self.gc.set_rgb_fg_color(gdk.color_parse('#000000'))
|
||||
|
||||
self.events_key = []
|
||||
self.events_mouse = []
|
||||
self.event_motion = None
|
||||
|
||||
pixel = "\x00\x00\x80"
|
||||
hole = "\x01\x01\x01"
|
||||
pb = self.pixmap(32, 32, ((pixel+hole)*16 + (hole+pixel)*16) * 16, 0x010101)
|
||||
self.taskbkgnd = self.renderpixbuf(pb)
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
scale = self.scale
|
||||
x2 = x+w
|
||||
y2 = y+h
|
||||
x, y, x2, y2 = int(x*scale), int(y*scale), int(x2*scale), int(y2*scale)
|
||||
pixmap, gc, ignored = self.taskbkgnd
|
||||
for j in range(y, y2, 32):
|
||||
for i in range(x, x2, 32):
|
||||
gc.set_clip_origin(i, j)
|
||||
self.offscreen.draw_drawable(gc, pixmap, 0, 0,
|
||||
i, j, x2-i, y2-j)
|
||||
|
||||
def pixmap(self, w, h, data, colorkey=-1):
|
||||
filename = self.tempppmfile
|
||||
f = open(filename, 'wb')
|
||||
print >> f, 'P6'
|
||||
print >> f, w, h
|
||||
print >> f, 255
|
||||
f.write(data)
|
||||
f.close()
|
||||
pb = gdk.pixbuf_new_from_file(filename)
|
||||
if colorkey >= 0:
|
||||
pb = pb.add_alpha(1, chr(colorkey >> 16),
|
||||
chr((colorkey >> 8) & 0xFF),
|
||||
chr(colorkey & 0xFF))
|
||||
if self.scale == 1:
|
||||
return self.renderpixbuf((pb,))
|
||||
else:
|
||||
return (pb,)
|
||||
|
||||
def renderpixbuf(self, input):
|
||||
if len(input) == 3:
|
||||
return input
|
||||
pb, = input
|
||||
pixmap, mask = pb.render_pixmap_and_mask()
|
||||
if mask is not None:
|
||||
gc = gdk.gc_new(self.window.window)
|
||||
gc.set_clip_mask(mask)
|
||||
return (pixmap, gc, mask)
|
||||
else:
|
||||
return (pixmap, self.gc, None)
|
||||
|
||||
def getopticon(self, input, (x, y, w, h), ignored_alpha=255):
|
||||
if len(input) == 3:
|
||||
return None
|
||||
pb, = input
|
||||
scale = self.scale
|
||||
newpb = gdk.Pixbuf("rgb", 1, 8, w, h)
|
||||
newpb.fill(0)
|
||||
pb.copy_area(x, y, w, h, newpb, 0, 0)
|
||||
newpb = newpb.scale_simple(int(w*scale), int(h*scale),
|
||||
gdk.INTERP_HYPER)
|
||||
if newpb is None:
|
||||
return None, None, None
|
||||
else:
|
||||
return self.renderpixbuf((newpb,))
|
||||
|
||||
def getppm(self, (x, y, w, h), int=int, ceil=math.ceil):
|
||||
scale = self.scale
|
||||
if isinstance(scale, int):
|
||||
x *= scale
|
||||
y *= scale
|
||||
w *= scale
|
||||
h *= scale
|
||||
else:
|
||||
w = int(ceil((x+w)*scale))
|
||||
h = int(ceil((y+h)*scale))
|
||||
x = int(x*scale)
|
||||
y = int(y*scale)
|
||||
w -= x
|
||||
h -= y
|
||||
bkgnd = gtk.create_pixmap(self.window.window, w, h)
|
||||
bkgnd.draw_drawable(self.gc, self.offscreen, x, y, 0, 0, w, h)
|
||||
return bkgnd, self.gc, None
|
||||
|
||||
def putppm(self, x, y, (pixmap, gc, ignored), rect=None, int=int):
|
||||
if pixmap is None:
|
||||
return
|
||||
scale = self.scale
|
||||
if rect is None:
|
||||
srcx = srcy = 0
|
||||
w = h = 4095
|
||||
else:
|
||||
srcx, srcy, w, h = rect
|
||||
x = int(x*scale)
|
||||
y = int(y*scale)
|
||||
if gc is not self.gc:
|
||||
gc.set_clip_origin(x-srcx, y-srcy)
|
||||
self.offscreen.draw_drawable(gc, pixmap, srcx, srcy, x, y, w, h)
|
||||
|
||||
def flip(self):
|
||||
self.window.window.draw_drawable(self.gc, self.offscreen,
|
||||
0, 0, 0, 0, self.width, self.height)
|
||||
gdk.flush()
|
||||
self.events_poll()
|
||||
|
||||
def close(self):
|
||||
self.window.destroy()
|
||||
|
||||
def clear(self):
|
||||
self.offscreen.draw_rectangle(self.gc, 1,
|
||||
0, 0, self.width, self.height)
|
||||
|
||||
def events_poll(self):
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
|
||||
def key_press_event(self, window, event):
|
||||
self.events_key.append((event.keyval, KeyPressed))
|
||||
|
||||
def key_release_event(self, window, event):
|
||||
self.events_key.append((event.keyval, KeyReleased))
|
||||
|
||||
def motion_notify_event(self, window, event):
|
||||
self.event_motion = (int(event.x/self.scale), int(event.y/self.scale))
|
||||
|
||||
def button_press_event(self, window, event):
|
||||
self.events_mouse.append((int(event.x/self.scale), int(event.y/self.scale)))
|
||||
|
||||
def keyevents(self):
|
||||
self.events_poll()
|
||||
result = self.events_key
|
||||
self.events_key = []
|
||||
return result
|
||||
|
||||
def pointermotion(self):
|
||||
result = self.event_motion
|
||||
self.event_motion = None
|
||||
return result
|
||||
|
||||
def mouseevents(self):
|
||||
self.events_poll()
|
||||
result = self.events_mouse
|
||||
self.events_mouse = []
|
||||
return result
|
||||
|
||||
def selectlist(self):
|
||||
return []
|
||||
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
return 'Scale image by <%s size=5>%%' % (
|
||||
nameval('text', 'zoom', default='100'))
|
@ -6,7 +6,7 @@
|
||||
import os
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
from modes import KeyPressed, KeyReleased
|
||||
from .modes import KeyPressed, KeyReleased
|
||||
|
||||
|
||||
class Display:
|
||||
@ -154,7 +154,8 @@ class Display:
|
||||
def selectlist(self):
|
||||
return []
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
def taskbar(self, xxx_todo_changeme):
|
||||
(x, y, w, h) = xxx_todo_changeme
|
||||
tbs, tbh = self.tbcache
|
||||
if tbh != h:
|
||||
tbs = pygame.Surface((32, h)).convert_alpha(self.offscreen)
|
||||
@ -192,7 +193,7 @@ def events_dispatch(handlers = EVENT_HANDLERS):
|
||||
e = pygame.event.poll()
|
||||
if e.type == NOEVENT:
|
||||
break
|
||||
elif handlers.has_key(e.type):
|
||||
elif e.type in handlers:
|
||||
handlers[e.type](e)
|
||||
|
||||
|
||||
|
206
display/dpy_pygame.py.bak
Normal file
206
display/dpy_pygame.py.bak
Normal file
@ -0,0 +1,206 @@
|
||||
|
||||
################################################
|
||||
## pygame-based implementation of xshm ##
|
||||
################################################
|
||||
|
||||
import os
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
from modes import KeyPressed, KeyReleased
|
||||
|
||||
|
||||
class Display:
|
||||
musthidemouse = 0
|
||||
mousevisible = 1
|
||||
|
||||
def __init__(self, width, height, title, transparency='yes', fullscreen='no'):
|
||||
self.use_transparency = not transparency.startswith('n')
|
||||
self.use_fullscreen = fullscreen.startswith('y')
|
||||
|
||||
# Initialize pygame
|
||||
pygame.init()
|
||||
|
||||
# Set the display mode
|
||||
winstyle = HWSURFACE
|
||||
if self.use_fullscreen:
|
||||
winstyle |= FULLSCREEN
|
||||
bestdepth = pygame.display.mode_ok((width, height), winstyle, 32)
|
||||
self.screen = pygame.display.set_mode((width, height),
|
||||
winstyle, bestdepth)
|
||||
self.offscreen = pygame.Surface((width, height))
|
||||
#decorate the game window
|
||||
pygame.display.set_caption(title)
|
||||
#pygame.mouse.set_visible(0)
|
||||
self.tbcache = None, None
|
||||
self.events_key = []
|
||||
self.events_mouse = []
|
||||
self.prevposition = None
|
||||
EVENT_HANDLERS[KEYDOWN] = self.keydown_handler
|
||||
EVENT_HANDLERS[KEYUP] = self.keyup_handler
|
||||
EVENT_HANDLERS[MOUSEBUTTONDOWN] = self.mousebuttondown_handler
|
||||
|
||||
def keydown_handler(self, e):
|
||||
if e.key == K_ESCAPE and self.use_fullscreen:
|
||||
raise SystemExit # ESC to exit the game if full-screen
|
||||
self.showmouse(not self.musthidemouse)
|
||||
self.events_key.append((e.key, KeyPressed))
|
||||
del self.events_key[:-16]
|
||||
|
||||
def keyup_handler(self, e):
|
||||
self.events_key.append((e.key, KeyReleased))
|
||||
del self.events_key[:-16]
|
||||
|
||||
def mousebuttondown_handler(self, e):
|
||||
self.showmouse(1)
|
||||
self.events_mouse.append(e.pos)
|
||||
del self.events_mouse[:-8]
|
||||
|
||||
def pixmap(self, w, h, data, colorkey=-1):
|
||||
img = pygame.image.fromstring(data, (w, h), "RGB")
|
||||
if colorkey >= 0:
|
||||
r = colorkey & 0xFF
|
||||
g = (colorkey >> 8) & 0xFF
|
||||
b = (colorkey >> 16) & 0xFF
|
||||
img.set_colorkey([r, g, b])
|
||||
return img # not optimized -- must use getopticon()
|
||||
|
||||
def getopticon(self, pixmap, rect, alpha=255):
|
||||
if not self.use_transparency:
|
||||
alpha = 255
|
||||
img = pixmap.subsurface(rect)
|
||||
colorkey = pixmap.get_colorkey()
|
||||
if alpha == 255 and not colorkey:
|
||||
return img.convert(self.offscreen)
|
||||
else:
|
||||
if colorkey:
|
||||
img.set_colorkey(colorkey, RLEACCEL)
|
||||
if alpha < 255:
|
||||
img.set_alpha(alpha, RLEACCEL)
|
||||
img = img.convert_alpha(self.offscreen)
|
||||
img.set_alpha(255, RLEACCEL)
|
||||
return img
|
||||
|
||||
## def vflipppm(self, img):
|
||||
## w, h = img.get_size()
|
||||
## colorkey = img.get_colorkey()
|
||||
## data = pygame.image.tostring(img, "RGB", 1)
|
||||
## flipimg = pygame.image.fromstring(data, (w, h), "RGB")
|
||||
## flipimg.set_colorkey(colorkey, RLEACCEL)
|
||||
## return flipimg, h
|
||||
|
||||
def getppm(self, rect):
|
||||
bkgnd = pygame.Surface(rect[2:])
|
||||
bkgnd.blit(self.offscreen, (0, 0), rect)
|
||||
return bkgnd
|
||||
|
||||
def putppm(self, x, y, bitmap, rect=None):
|
||||
if rect:
|
||||
self.offscreen.blit(bitmap, (x, y), rect)
|
||||
else:
|
||||
self.offscreen.blit(bitmap, (x, y))
|
||||
|
||||
def flip(self):
|
||||
self.screen.blit(self.offscreen, (0, 0))
|
||||
pygame.display.flip()
|
||||
events_dispatch()
|
||||
|
||||
def close(self):
|
||||
self.showmouse(1)
|
||||
pygame.display.quit()
|
||||
|
||||
def clear(self):
|
||||
self.offscreen.fill([0,0,0,])
|
||||
|
||||
def events_poll(self):
|
||||
while 1:
|
||||
e = pygame.event.poll()
|
||||
if e.type == NOEVENT:
|
||||
break
|
||||
elif e.type == KEYDOWN:
|
||||
self.events_key.append((e.key, KeyPressed))
|
||||
del self.events_key[:-16]
|
||||
elif e.type == KEYUP:
|
||||
self.events_key.append((e.key, KeyReleased))
|
||||
del self.events_key[:-16]
|
||||
elif e.type == MOUSEBUTTONDOWN:
|
||||
self.events_mouse.append(e.pos)
|
||||
del self.events_mouse[:-8]
|
||||
elif e.type == ENDMUSICEVENT:
|
||||
self.next_music()
|
||||
elif e.type == QUIT:
|
||||
raise SystemExit
|
||||
|
||||
def keyevents(self):
|
||||
events_dispatch()
|
||||
events = self.events_key
|
||||
self.events_key = []
|
||||
return events
|
||||
|
||||
def pointermotion(self):
|
||||
position = pygame.mouse.get_pos()
|
||||
if position != self.prevposition:
|
||||
self.showmouse(1)
|
||||
self.prevposition = position
|
||||
return position
|
||||
else:
|
||||
return None
|
||||
|
||||
def mouseevents(self):
|
||||
events_dispatch()
|
||||
events = self.events_mouse
|
||||
self.events_mouse = []
|
||||
return events
|
||||
|
||||
def selectlist(self):
|
||||
return []
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
tbs, tbh = self.tbcache
|
||||
if tbh != h:
|
||||
tbs = pygame.Surface((32, h)).convert_alpha(self.offscreen)
|
||||
alpha_f = 256.0 / h
|
||||
for j in range(h):
|
||||
tbs.fill((128, 128, 255, int(j*alpha_f)),
|
||||
(0, j, 32, 1))
|
||||
self.tbcache = tbs, h
|
||||
for i in range(x, x+w, 32):
|
||||
dw = x+w-i
|
||||
if dw < 32:
|
||||
self.offscreen.blit(tbs, (i, y), (0, 0, dw, h))
|
||||
else:
|
||||
self.offscreen.blit(tbs, (i, y))
|
||||
|
||||
def settaskbar(self, tb_visible):
|
||||
self.showmouse(1)
|
||||
self.musthidemouse = not tb_visible # and self.use_fullscreen
|
||||
|
||||
def showmouse(self, v):
|
||||
if v != self.mousevisible:
|
||||
self.mousevisible = v
|
||||
pygame.mouse.set_visible(v)
|
||||
|
||||
|
||||
def quit_handler(e):
|
||||
raise SystemExit
|
||||
|
||||
EVENT_HANDLERS = {
|
||||
QUIT: quit_handler,
|
||||
}
|
||||
|
||||
def events_dispatch(handlers = EVENT_HANDLERS):
|
||||
while 1:
|
||||
e = pygame.event.poll()
|
||||
if e.type == NOEVENT:
|
||||
break
|
||||
elif handlers.has_key(e.type):
|
||||
handlers[e.type](e)
|
||||
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
return '''
|
||||
<%s> Full Screen (Esc key to exit)</input><%s><br>
|
||||
<%s> Draw slightly transparent bubbles</input><%s><br>
|
||||
''' % (nameval("checkbox", "fullscreen", "yes", default="no"),
|
||||
nameval("hidden", "fullscreen", "no"),
|
||||
nameval("checkbox", "transparency", "yes", default="yes"),
|
||||
nameval("hidden", "transparency", "no"))
|
@ -1,7 +1,7 @@
|
||||
import sys
|
||||
import wingame
|
||||
from modes import BaseDisplay
|
||||
from cStringIO import StringIO
|
||||
from .modes import BaseDisplay
|
||||
from io import StringIO
|
||||
|
||||
|
||||
class Display(BaseDisplay):
|
||||
|
23
display/dpy_windows.py.bak
Executable file
23
display/dpy_windows.py.bak
Executable file
@ -0,0 +1,23 @@
|
||||
import sys
|
||||
import wingame
|
||||
from modes import BaseDisplay
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
||||
class Display(BaseDisplay):
|
||||
|
||||
def __init__(self, width, height, title):
|
||||
self.xdpy = xdpy = wingame.Display(width, height)
|
||||
xdpy.settitle(title)
|
||||
self.pixmap = xdpy.pixmap
|
||||
self.getppm = xdpy.getppm
|
||||
self.putppm = xdpy.putppm
|
||||
self.close = xdpy.close
|
||||
self.clear = xdpy.clear
|
||||
self.flip = xdpy.flip
|
||||
self.keyevents = xdpy.keyevents
|
||||
self.mouseevents = xdpy.mouseevents
|
||||
self.pointermotion = xdpy.pointermotion
|
||||
|
||||
def selectlist(self):
|
||||
return []
|
@ -1,7 +1,7 @@
|
||||
import sys
|
||||
import xshm
|
||||
from modes import BaseDisplay
|
||||
from cStringIO import StringIO
|
||||
from .modes import BaseDisplay
|
||||
from io import StringIO
|
||||
|
||||
|
||||
class Display(BaseDisplay):
|
||||
@ -20,9 +20,8 @@ class Display(BaseDisplay):
|
||||
self.mouseevents = xdpy.mouseevents
|
||||
self.pointermotion = xdpy.pointermotion
|
||||
if use_shm and not xdpy.shmmode():
|
||||
print >> sys.stderr, \
|
||||
"Note: cannot use SHM extension (%dx%d), display will be slow." % \
|
||||
(width, height)
|
||||
print("Note: cannot use SHM extension (%dx%d), display will be slow." % \
|
||||
(width, height), file=sys.stderr)
|
||||
|
||||
def selectlist(self):
|
||||
if hasattr(self.xdpy, 'fd'):
|
||||
|
40
display/dpy_x.py.bak
Normal file
40
display/dpy_x.py.bak
Normal file
@ -0,0 +1,40 @@
|
||||
import sys
|
||||
import xshm
|
||||
from modes import BaseDisplay
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
||||
class Display(BaseDisplay):
|
||||
|
||||
def __init__(self, width, height, title, shm='yes'):
|
||||
use_shm = not shm.startswith('n')
|
||||
self.xdpy = xdpy = xshm.Display(width, height, use_shm)
|
||||
self.pixmap = xdpy.pixmap
|
||||
self.getppm = xdpy.getppm
|
||||
self.putppm = xdpy.putppm
|
||||
self.overlayppm = xdpy.overlayppm
|
||||
self.close = xdpy.close
|
||||
self.clear = xdpy.clear
|
||||
self.flip = xdpy.flip
|
||||
self.keyevents = xdpy.keyevents
|
||||
self.mouseevents = xdpy.mouseevents
|
||||
self.pointermotion = xdpy.pointermotion
|
||||
if use_shm and not xdpy.shmmode():
|
||||
print >> sys.stderr, \
|
||||
"Note: cannot use SHM extension (%dx%d), display will be slow." % \
|
||||
(width, height)
|
||||
|
||||
def selectlist(self):
|
||||
if hasattr(self.xdpy, 'fd'):
|
||||
from socket import fromfd, AF_INET, SOCK_STREAM
|
||||
return [fromfd(self.xdpy.fd(), AF_INET, SOCK_STREAM)]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
return '''
|
||||
<%s> Use the shared memory extension</input><%s><br>
|
||||
<font size=-1>Note: Disable it for remote connections or old X servers</font>
|
||||
''' % (nameval("checkbox", "shm", "yes", default="yes"),
|
||||
nameval("hidden", "shm", "no"))
|
@ -7,7 +7,8 @@ KeyReleased = 3
|
||||
class BaseDisplay:
|
||||
__taskbkgnd = None
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
def taskbar(self, xxx_todo_changeme):
|
||||
(x, y, w, h) = xxx_todo_changeme
|
||||
if self.__taskbkgnd is None:
|
||||
pixel = "\x00\x00\x80"
|
||||
hole = "\x01\x01\x01"
|
||||
@ -56,22 +57,22 @@ class Mode:
|
||||
state = ' [%s]' % err
|
||||
else:
|
||||
state = ''
|
||||
print >> f, ' %-8s %s%s' % (self.name, self.descr, state)
|
||||
print(' %-8s %s%s' % (self.name, self.descr, state), file=f)
|
||||
if self.url:
|
||||
print >> f, ' %s' % self.url
|
||||
print(' %s' % self.url, file=f)
|
||||
for line in self.extraoptsdescr:
|
||||
print >> f, ' %s' % line
|
||||
print(' %s' % line, file=f)
|
||||
|
||||
def getformaloptions(self):
|
||||
return '', [c+'=' for c in self.options.keys()]
|
||||
return '', [c+'=' for c in list(self.options.keys())]
|
||||
|
||||
def setoptions(self, options):
|
||||
for key in self.options.keys():
|
||||
if options.has_key('--'+key):
|
||||
for key in list(self.options.keys()):
|
||||
if '--'+key in options:
|
||||
self.options[key] = options['--'+key]
|
||||
|
||||
def currentdriver(self):
|
||||
lst = self.options.items()
|
||||
lst = list(self.options.items())
|
||||
lst.sort()
|
||||
lst = ['--%s=%s' % keyvalue for keyvalue in lst]
|
||||
return ' '.join([self.name] + lst)
|
||||
@ -142,22 +143,22 @@ def findmode(name, lst):
|
||||
return info
|
||||
if last_chance is not None:
|
||||
return last_chance
|
||||
raise KeyError, 'no driver available!'
|
||||
raise KeyError('no driver available!')
|
||||
else:
|
||||
# find mode by name
|
||||
for info in lst:
|
||||
if info.name.upper() == name.upper():
|
||||
err = info.imperror()
|
||||
if err:
|
||||
raise KeyError, '%s: %s' % (info.name, err)
|
||||
raise KeyError('%s: %s' % (info.name, err))
|
||||
return info
|
||||
raise KeyError, '%s: no such driver' % name
|
||||
raise KeyError('%s: no such driver' % name)
|
||||
|
||||
def findmode_err(*args):
|
||||
try:
|
||||
return findmode(*args)
|
||||
except KeyError, e:
|
||||
print >> sys.stderr, str(e)
|
||||
except KeyError as e:
|
||||
print(str(e), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def open_dpy(mode, width, height, title):
|
||||
@ -165,7 +166,7 @@ def open_dpy(mode, width, height, title):
|
||||
ginfo = findmode_err(driver, graphicmodeslist())
|
||||
ginfo.setoptions(extraopts)
|
||||
dpy = ginfo.getmodule().Display(width, height, title, **ginfo.options)
|
||||
print 'graphics driver:', ginfo.currentdriver()
|
||||
print('graphics driver:', ginfo.currentdriver())
|
||||
return dpy
|
||||
|
||||
def open_snd(mode):
|
||||
@ -179,7 +180,7 @@ def open_snd(mode):
|
||||
if (sinfo.options['music'].startswith('n') or
|
||||
sinfo.options['music'] == 'off'):
|
||||
snd.has_music = 0
|
||||
print 'sound driver:', sinfo.currentdriver()
|
||||
print('sound driver:', sinfo.currentdriver())
|
||||
return snd
|
||||
else:
|
||||
return None
|
||||
|
192
display/modes.py.bak
Normal file
192
display/modes.py.bak
Normal file
@ -0,0 +1,192 @@
|
||||
import sys
|
||||
|
||||
KeyPressed = 2
|
||||
KeyReleased = 3
|
||||
|
||||
|
||||
class BaseDisplay:
|
||||
__taskbkgnd = None
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
if self.__taskbkgnd is None:
|
||||
pixel = "\x00\x00\x80"
|
||||
hole = "\x01\x01\x01"
|
||||
self.__taskbkgnd = self.pixmap(32, 32,
|
||||
((pixel+hole)*16 + (hole+pixel)*16) * 16, 0x010101)
|
||||
for j in range(y, y+h, 32):
|
||||
for i in range(x, x+w, 32):
|
||||
self.putppm(i, j, self.__taskbkgnd,
|
||||
(0, 0, x+w-i, y+h-j))
|
||||
|
||||
|
||||
class Mode:
|
||||
low_priority = 0
|
||||
|
||||
def __init__(self, name, descr, extraoptsdescr,
|
||||
options={}, url=None):
|
||||
self.name = name
|
||||
self.descr = descr
|
||||
self.extraoptsdescr = extraoptsdescr
|
||||
self.options = options.copy()
|
||||
self.url = url
|
||||
|
||||
def getmodule(self):
|
||||
return __import__(self.prefix + self.name.lower(), globals(),
|
||||
locals(), ['available'])
|
||||
|
||||
def imperror(self):
|
||||
try:
|
||||
return self.__imperror
|
||||
except AttributeError:
|
||||
try:
|
||||
module = self.getmodule()
|
||||
except ImportError:
|
||||
result = 'not installed'
|
||||
else:
|
||||
result = hasattr(module, 'imperror') and module.imperror()
|
||||
self.__imperror = result
|
||||
return result
|
||||
|
||||
def unique_id(self):
|
||||
return self.prefix + self.name
|
||||
|
||||
def printline(self, f):
|
||||
err = self.imperror()
|
||||
if err:
|
||||
state = ' [%s]' % err
|
||||
else:
|
||||
state = ''
|
||||
print >> f, ' %-8s %s%s' % (self.name, self.descr, state)
|
||||
if self.url:
|
||||
print >> f, ' %s' % self.url
|
||||
for line in self.extraoptsdescr:
|
||||
print >> f, ' %s' % line
|
||||
|
||||
def getformaloptions(self):
|
||||
return '', [c+'=' for c in self.options.keys()]
|
||||
|
||||
def setoptions(self, options):
|
||||
for key in self.options.keys():
|
||||
if options.has_key('--'+key):
|
||||
self.options[key] = options['--'+key]
|
||||
|
||||
def currentdriver(self):
|
||||
lst = self.options.items()
|
||||
lst.sort()
|
||||
lst = ['--%s=%s' % keyvalue for keyvalue in lst]
|
||||
return ' '.join([self.name] + lst)
|
||||
|
||||
def htmloptionstext(self, *args):
|
||||
if self.imperror():
|
||||
return None
|
||||
module = self.getmodule()
|
||||
return (hasattr(module, 'htmloptionstext') and
|
||||
module.htmloptionstext(*args))
|
||||
|
||||
|
||||
class GraphicMode(Mode):
|
||||
prefix = 'dpy_'
|
||||
|
||||
|
||||
class SoundMode(Mode):
|
||||
prefix = 'snd_'
|
||||
|
||||
|
||||
def graphicmodeslist():
|
||||
return [
|
||||
GraphicMode('X', 'XWindow (Linux/Unix)',
|
||||
['--shm=yes use the Shared Memory extension (default)',
|
||||
'--shm=no disable it (for remote connections or old X servers)',
|
||||
],
|
||||
{'shm': 'yes'}),
|
||||
GraphicMode('windows', 'MS Windows', []),
|
||||
GraphicMode('pygame', 'PyGame library (all platforms)',
|
||||
['--fullscreen=yes go full screen (Esc key to exit)',
|
||||
'--transparency=yes slightly transparent bubbles (default)',
|
||||
'--transparency=no disable it (a bit faster)'],
|
||||
{'transparency': 'yes', 'fullscreen': 'no'},
|
||||
url='http://www.pygame.org'),
|
||||
GraphicMode('gtk', 'PyGTK (Gnome)',
|
||||
['--zoom=xxx% scale image by xxx %'],
|
||||
{'zoom': '100'},
|
||||
url='http://www.pygtk.org/'),
|
||||
]
|
||||
|
||||
def soundmodeslist():
|
||||
return [
|
||||
SoundMode('pygame', 'PyGame library mixer (all platforms)',
|
||||
[], url='http://www.pygame.org'),
|
||||
SoundMode('linux', 'audio mixer for Linux',
|
||||
['--freq=# mixer frequency (default 44100)',
|
||||
'--fmt=# data format (default S16_NE, --fmt=list for a list)'],
|
||||
{'freq': '44100', 'fmt': 'S16_NE'}),
|
||||
SoundMode('windows', 'audio mixer for Windows',
|
||||
['--freq=# mixer frequency (default 44100)',
|
||||
'--bits=# bits per sample (8 or default 16)'],
|
||||
{'freq': '44100', 'bits': '16'}),
|
||||
SoundMode('off', 'no sounds', []),
|
||||
]
|
||||
|
||||
def findmode(name, lst):
|
||||
if name is None:
|
||||
# find the first installed mode
|
||||
last_chance = None
|
||||
for info in lst:
|
||||
err = info.imperror()
|
||||
if err:
|
||||
continue
|
||||
if info.low_priority:
|
||||
if last_chance is None:
|
||||
last_chance = info
|
||||
else:
|
||||
return info
|
||||
if last_chance is not None:
|
||||
return last_chance
|
||||
raise KeyError, 'no driver available!'
|
||||
else:
|
||||
# find mode by name
|
||||
for info in lst:
|
||||
if info.name.upper() == name.upper():
|
||||
err = info.imperror()
|
||||
if err:
|
||||
raise KeyError, '%s: %s' % (info.name, err)
|
||||
return info
|
||||
raise KeyError, '%s: no such driver' % name
|
||||
|
||||
def findmode_err(*args):
|
||||
try:
|
||||
return findmode(*args)
|
||||
except KeyError, e:
|
||||
print >> sys.stderr, str(e)
|
||||
sys.exit(1)
|
||||
|
||||
def open_dpy(mode, width, height, title):
|
||||
driver, sound, extraopts = mode
|
||||
ginfo = findmode_err(driver, graphicmodeslist())
|
||||
ginfo.setoptions(extraopts)
|
||||
dpy = ginfo.getmodule().Display(width, height, title, **ginfo.options)
|
||||
print 'graphics driver:', ginfo.currentdriver()
|
||||
return dpy
|
||||
|
||||
def open_snd(mode):
|
||||
driver, sound, extraopts = mode
|
||||
sinfo = findmode_err(sound, soundmodeslist())
|
||||
sinfo.setoptions(extraopts)
|
||||
snd = sinfo.getmodule().Sound(**sinfo.options)
|
||||
if snd.has_sound:
|
||||
sinfo.options['music'] = 'yes'
|
||||
sinfo.setoptions(extraopts)
|
||||
if (sinfo.options['music'].startswith('n') or
|
||||
sinfo.options['music'] == 'off'):
|
||||
snd.has_music = 0
|
||||
print 'sound driver:', sinfo.currentdriver()
|
||||
return snd
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def musichtmloptiontext(nameval):
|
||||
return '''<font size=-1>
|
||||
<%s> Background music</input><%s>
|
||||
</font>''' % (nameval("checkbox", "music", "yes", default="yes", mangling=0),
|
||||
nameval("hidden", "music", "no", mangling=0))
|
@ -8,9 +8,9 @@ import time
|
||||
from common.msgstruct import *
|
||||
from common.pixmap import decodepixmap
|
||||
from common import hostchooser
|
||||
import modes
|
||||
from modes import KeyPressed, KeyReleased
|
||||
import caching
|
||||
from . import modes
|
||||
from .modes import KeyPressed, KeyReleased
|
||||
from . import caching
|
||||
|
||||
#import psyco; psyco.full()
|
||||
|
||||
@ -44,13 +44,13 @@ class Icon:
|
||||
self.rect = None
|
||||
return self.pixmap
|
||||
elif attr in ('bmpcode', 'rect'):
|
||||
raise KeyError, attr
|
||||
raise KeyError(attr)
|
||||
elif attr == 'originalrect':
|
||||
self.originalrect = self.rect
|
||||
return self.originalrect
|
||||
raise AttributeError, attr
|
||||
raise AttributeError(attr)
|
||||
def clear(self):
|
||||
if self.__dict__.has_key('pixmap'):
|
||||
if 'pixmap' in self.__dict__:
|
||||
del self.pixmap
|
||||
|
||||
class DataChunk(caching.Data):
|
||||
@ -77,7 +77,7 @@ class DataChunk(caching.Data):
|
||||
DataChunk.TOTAL += lendata
|
||||
total = DataChunk.TOTAL >> 10
|
||||
if total != prev:
|
||||
print "downloaded %dkb of data from server" % total
|
||||
print("downloaded %dkb of data from server" % total)
|
||||
self.store(position, data)
|
||||
try:
|
||||
self.pending.remove((0, position))
|
||||
@ -104,24 +104,24 @@ class Playfield:
|
||||
self.sockaddr = sockaddr
|
||||
try:
|
||||
self.s.setsockopt(SOL_IP, IP_TOS, 0x10) # IPTOS_LOWDELAY
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot set IPTOS_LOWDELAY:", str(e)
|
||||
except error as e:
|
||||
print("Cannot set IPTOS_LOWDELAY:", str(e), file=sys.stderr)
|
||||
try:
|
||||
self.s.setsockopt(SOL_TCP, TCP_NODELAY, 1)
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot set TCP_NODELAY:", str(e)
|
||||
except error as e:
|
||||
print("Cannot set TCP_NODELAY:", str(e), file=sys.stderr)
|
||||
|
||||
initialbuf = ""
|
||||
while 1:
|
||||
t = self.s.recv(200)
|
||||
if not t and not hasattr(self.s, 'RECV_CAN_RETURN_EMPTY'):
|
||||
raise error, "connexion closed"
|
||||
raise error("connexion closed")
|
||||
initialbuf += t
|
||||
if len(initialbuf) >= len(MSG_WELCOME):
|
||||
head = initialbuf[:len(MSG_WELCOME)]
|
||||
tail = initialbuf[len(MSG_WELCOME):]
|
||||
if head != MSG_WELCOME:
|
||||
raise error, "connected to something not a game server"
|
||||
raise error("connected to something not a game server")
|
||||
if '\n' in tail:
|
||||
break
|
||||
n = tail.index('\n')
|
||||
@ -135,7 +135,7 @@ class Playfield:
|
||||
## if i >= 0:
|
||||
## self.gameident, self.datapath = (self.gameident[:i].strip(),
|
||||
## self.gameident[i+1:-1])
|
||||
print "connected to %r." % self.gameident
|
||||
print("connected to %r." % self.gameident)
|
||||
self.s.sendall(message(CMSG_PROTO_VERSION, 3))
|
||||
|
||||
def setup(self, mode, udp_over_tcp):
|
||||
@ -156,10 +156,10 @@ class Playfield:
|
||||
self.playericons = {}
|
||||
self.screenmode = mode
|
||||
self.initlevel = 0
|
||||
if mode[-1].has_key('udp_over_tcp'):
|
||||
if 'udp_over_tcp' in mode[-1]:
|
||||
udp_over_tcp = mode[-1]['udp_over_tcp']
|
||||
self.trackcfgmtime = None
|
||||
if mode[-1].has_key('cfgfile'):
|
||||
if 'cfgfile' in mode[-1]:
|
||||
self.trackcfgfile = mode[-1]['cfgfile']
|
||||
else:
|
||||
self.trackcfgfile = os.path.join(DataChunk.SOURCEDIR,
|
||||
@ -217,8 +217,8 @@ class Playfield:
|
||||
while self.udpsock in iwtd:
|
||||
try:
|
||||
udpdata = self.udpsock.recv(65535)
|
||||
except error, e:
|
||||
print >> sys.stderr, e
|
||||
except error as e:
|
||||
print(e, file=sys.stderr)
|
||||
errors += 1
|
||||
if errors > 10:
|
||||
raise
|
||||
@ -420,9 +420,9 @@ class Playfield:
|
||||
t = time.time()
|
||||
t, t0 = t-t0, t
|
||||
if t:
|
||||
print "%.2f images per second, %.1f kbytes per second" % (
|
||||
print("%.2f images per second, %.1f kbytes per second" % (
|
||||
float(n)/t,
|
||||
float(self.tcpbytecounter+self.udpbytecounter)/1024/t)
|
||||
float(self.tcpbytecounter+self.udpbytecounter)/1024/t))
|
||||
self.tcpbytecounter = -self.udpbytecounter
|
||||
n = 0
|
||||
self.painttimes = t0, n
|
||||
@ -432,7 +432,7 @@ class Playfield:
|
||||
iconlist = []
|
||||
f = 1.5 * time.time()
|
||||
f = f-int(f)
|
||||
pi = self.playericons.items()
|
||||
pi = list(self.playericons.items())
|
||||
pi.sort()
|
||||
xpos = 0
|
||||
for id, ico in pi:
|
||||
@ -460,7 +460,8 @@ class Playfield:
|
||||
self.animdelay = 0.04
|
||||
return y0, iconlist
|
||||
|
||||
def clic_taskbar(self, (cx,cy)):
|
||||
def clic_taskbar(self, xxx_todo_changeme):
|
||||
(cx,cy) = xxx_todo_changeme
|
||||
y0, icons = self.get_taskbar()
|
||||
if cy >= y0:
|
||||
for x, y, ico, id in icons:
|
||||
@ -480,13 +481,14 @@ class Playfield:
|
||||
pass
|
||||
return y0, bkgnd
|
||||
|
||||
def erase_taskbar(self, (y0, bkgnd)):
|
||||
def erase_taskbar(self, xxx_todo_changeme1):
|
||||
(y0, bkgnd) = xxx_todo_changeme1
|
||||
self.dpy.putppm(0, y0, bkgnd)
|
||||
|
||||
def nextkeyname(self):
|
||||
pid, df = self.keydefinition
|
||||
undef = [(num, keyname) for keyname, (num, icons) in self.keys.items()
|
||||
if not df.has_key(keyname) and icons]
|
||||
undef = [(num, keyname) for keyname, (num, icons) in list(self.keys.items())
|
||||
if keyname not in df and icons]
|
||||
if undef:
|
||||
num, keyname = min(undef)
|
||||
return keyname
|
||||
@ -556,7 +558,7 @@ class Playfield:
|
||||
pending = {}
|
||||
for keysym, event in keyevents:
|
||||
pending[keysym] = event
|
||||
for keysym, event in pending.items():
|
||||
for keysym, event in list(pending.items()):
|
||||
code = self.keycodes.get((keysym, event))
|
||||
if code and self.playing.get(code[0]) == 'l':
|
||||
if (code == self.last_key_event[0] and
|
||||
@ -588,7 +590,7 @@ class Playfield:
|
||||
self.taskbartimeout = None
|
||||
if self.taskbarfree:
|
||||
self.taskbarmode = (nmode or
|
||||
'l' not in self.playing.values() or
|
||||
'l' not in list(self.playing.values()) or
|
||||
(self.keydefinition is not None))
|
||||
if nmode:
|
||||
self.taskbartimeout = time.time() + 5.0
|
||||
@ -597,26 +599,26 @@ class Playfield:
|
||||
|
||||
def define_key(self, keysym):
|
||||
clic_id, df = self.keydefinition
|
||||
if keysym in df.values():
|
||||
if keysym in list(df.values()):
|
||||
return
|
||||
df[self.nextkeyname()] = keysym
|
||||
if self.nextkeyname() is not None:
|
||||
return
|
||||
self.keydefinition = None
|
||||
self.s.sendall(message(CMSG_ADD_PLAYER, clic_id))
|
||||
for keyname, (num, icons) in self.keys.items():
|
||||
for keyname, (num, icons) in list(self.keys.items()):
|
||||
if keyname[:1] == '-':
|
||||
event = KeyReleased
|
||||
keyname = keyname[1:]
|
||||
else:
|
||||
event = KeyPressed
|
||||
if df.has_key(keyname):
|
||||
if keyname in df:
|
||||
keysym = df[keyname]
|
||||
self.keycodes[keysym, event] = \
|
||||
clic_id, message(CMSG_KEY, clic_id, num)
|
||||
|
||||
def msg_unknown(self, *rest):
|
||||
print >> sys.stderr, "?"
|
||||
print("?", file=sys.stderr)
|
||||
|
||||
def msg_player_join(self, id, local, *rest):
|
||||
if local:
|
||||
@ -628,7 +630,7 @@ class Playfield:
|
||||
|
||||
def msg_player_kill(self, id, *rest):
|
||||
self.playing[id] = 0
|
||||
for key, (pid, msg) in self.keycodes.items():
|
||||
for key, (pid, msg) in list(self.keycodes.items()):
|
||||
if pid == id:
|
||||
del self.keycodes[key]
|
||||
|
||||
@ -651,8 +653,8 @@ class Playfield:
|
||||
self.udpsock2 = socket(AF_INET, SOCK_DGRAM)
|
||||
self.udpsock2.bind(('', port))
|
||||
self.udpsock2.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
except error, e:
|
||||
print "Cannot listen on the broadcast port %d" % port, str(e)
|
||||
except error as e:
|
||||
print("Cannot listen on the broadcast port %d" % port, str(e))
|
||||
self.udpsock2 = None
|
||||
else:
|
||||
self.iwtd.append(self.udpsock2)
|
||||
@ -664,7 +666,7 @@ class Playfield:
|
||||
# self.snd.close()
|
||||
if self.dpy is not None:
|
||||
# clear all pixmaps
|
||||
for ico in self.icons.values():
|
||||
for ico in list(self.icons.values()):
|
||||
ico.clear()
|
||||
self.pixmaps.clear()
|
||||
self.dpy.close()
|
||||
@ -726,7 +728,7 @@ class Playfield:
|
||||
f.when_ready(ready)
|
||||
|
||||
def msg_patch_file(self, fileid, position, data, lendata=None, *rest):
|
||||
if self.fileids.has_key(fileid):
|
||||
if fileid in self.fileids:
|
||||
f = self.fileids[fileid]
|
||||
else:
|
||||
f = self.fileids[fileid] = DataChunk(fileid)
|
||||
@ -737,7 +739,7 @@ class Playfield:
|
||||
self.msg_patch_file(fileid, position, data1, len(data), *rest)
|
||||
|
||||
def msg_md5_file(self, fileid, filename, position, length, checksum, *rest):
|
||||
if self.fileids.has_key(fileid):
|
||||
if fileid in self.fileids:
|
||||
f = self.fileids[fileid]
|
||||
else:
|
||||
f = self.fileids[fileid] = DataChunk(fileid)
|
||||
@ -777,13 +779,13 @@ class Playfield:
|
||||
f.close()
|
||||
d = eval(data or '{}', {}, {})
|
||||
except:
|
||||
print >> sys.stderr, 'Invalid config file format'
|
||||
print('Invalid config file format', file=sys.stderr)
|
||||
else:
|
||||
d = d.get(gethostname(), {})
|
||||
namemsg = ''
|
||||
for id, local in self.playing.items():
|
||||
for id, local in list(self.playing.items()):
|
||||
keyid = 'player%d' % id
|
||||
if local == 'l' and d.has_key(keyid):
|
||||
if local == 'l' and keyid in d:
|
||||
namemsg = namemsg + message(
|
||||
CMSG_PLAYER_NAME, id, d[keyid])
|
||||
if namemsg:
|
||||
@ -803,9 +805,9 @@ class Playfield:
|
||||
self.udpsock_low += 1
|
||||
if self.udpsock_low >= 3 and self.initlevel >= 1:
|
||||
# third time now -- that's too much
|
||||
print "Note: routing UDP traffic over TCP",
|
||||
print("Note: routing UDP traffic over TCP", end=' ')
|
||||
inp = self.udpbytecounter / (udpkbytes*1024.0)
|
||||
print "(%d%% packet loss)" % int(100*(1.0-inp))
|
||||
print("(%d%% packet loss)" % int(100*(1.0-inp)))
|
||||
self.start_udp_over_tcp()
|
||||
self.s.sendall(message(CMSG_UDP_PORT, MSG_INLINE_FRAME))
|
||||
else:
|
||||
|
860
display/pclient.py.bak
Normal file
860
display/pclient.py.bak
Normal file
@ -0,0 +1,860 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import sys, os
|
||||
from socket import *
|
||||
from select import select
|
||||
import struct, zlib
|
||||
import time
|
||||
from common.msgstruct import *
|
||||
from common.pixmap import decodepixmap
|
||||
from common import hostchooser
|
||||
import modes
|
||||
from modes import KeyPressed, KeyReleased
|
||||
import caching
|
||||
|
||||
#import psyco; psyco.full()
|
||||
|
||||
# switch to udp_over_tcp if the udp socket didn't receive at least 60% of
|
||||
# the packets sent by the server
|
||||
UDP_EXPECTED_RATIO = 0.60
|
||||
|
||||
|
||||
def loadpixmap(dpy, data, colorkey=None):
|
||||
w, h, data = decodepixmap(data)
|
||||
if colorkey is None:
|
||||
colorkey = -1
|
||||
elif colorkey < 0:
|
||||
r, g, b = struct.unpack("BBB", self.data[:3])
|
||||
colorkey = b | (g<<8) | (r<<16)
|
||||
return dpy.pixmap(w, h, data, colorkey)
|
||||
|
||||
class Icon:
|
||||
alpha = 255
|
||||
def __init__(self, playfield):
|
||||
self.playfield = playfield
|
||||
self.size = 0, 0
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'pixmap':
|
||||
self.pixmap = self.playfield.getpixmap(self.bmpcode)
|
||||
if hasattr(self.playfield.dpy, 'getopticon'):
|
||||
ico = self.playfield.dpy.getopticon(
|
||||
self.pixmap, self.originalrect, self.alpha)
|
||||
if ico is not None:
|
||||
self.pixmap = ico
|
||||
self.rect = None
|
||||
return self.pixmap
|
||||
elif attr in ('bmpcode', 'rect'):
|
||||
raise KeyError, attr
|
||||
elif attr == 'originalrect':
|
||||
self.originalrect = self.rect
|
||||
return self.originalrect
|
||||
raise AttributeError, attr
|
||||
def clear(self):
|
||||
if self.__dict__.has_key('pixmap'):
|
||||
del self.pixmap
|
||||
|
||||
class DataChunk(caching.Data):
|
||||
SOURCEDIR = os.path.abspath(os.path.join(os.path.dirname(caching.__file__),
|
||||
os.pardir))
|
||||
CACHEDIR = os.path.join(SOURCEDIR, 'cache')
|
||||
TOTAL = 0
|
||||
|
||||
def __init__(self, fileid):
|
||||
caching.Data.__init__(self)
|
||||
self.fileid = fileid
|
||||
self.pending = []
|
||||
self.progresshook = None
|
||||
|
||||
def server_md5(self, playfield, filename, position, length, checksum):
|
||||
if not self.loadfrom(filename, position, length, checksum):
|
||||
self.pending.append((0, position))
|
||||
playfield.s.sendall(message(CMSG_DATA_REQUEST, self.fileid,
|
||||
position, length))
|
||||
|
||||
def server_patch(self, position, data, lendata):
|
||||
#print 'server_patch', self.fileid, position, len(data)
|
||||
prev = DataChunk.TOTAL >> 10
|
||||
DataChunk.TOTAL += lendata
|
||||
total = DataChunk.TOTAL >> 10
|
||||
if total != prev:
|
||||
print "downloaded %dkb of data from server" % total
|
||||
self.store(position, data)
|
||||
try:
|
||||
self.pending.remove((0, position))
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
while self.pending and self.pending[0][0]:
|
||||
callback = self.pending[0][1]
|
||||
del self.pending[0]
|
||||
callback(self)
|
||||
|
||||
def when_ready(self, callback):
|
||||
if self.pending:
|
||||
self.pending.append((1, callback))
|
||||
else:
|
||||
callback(self)
|
||||
|
||||
|
||||
class Playfield:
|
||||
TASKBAR_HEIGHT = 48
|
||||
|
||||
def __init__(self, s, sockaddr):
|
||||
self.s = s
|
||||
self.sockaddr = sockaddr
|
||||
try:
|
||||
self.s.setsockopt(SOL_IP, IP_TOS, 0x10) # IPTOS_LOWDELAY
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot set IPTOS_LOWDELAY:", str(e)
|
||||
try:
|
||||
self.s.setsockopt(SOL_TCP, TCP_NODELAY, 1)
|
||||
except error, e:
|
||||
print >> sys.stderr, "Cannot set TCP_NODELAY:", str(e)
|
||||
|
||||
initialbuf = ""
|
||||
while 1:
|
||||
t = self.s.recv(200)
|
||||
if not t and not hasattr(self.s, 'RECV_CAN_RETURN_EMPTY'):
|
||||
raise error, "connexion closed"
|
||||
initialbuf += t
|
||||
if len(initialbuf) >= len(MSG_WELCOME):
|
||||
head = initialbuf[:len(MSG_WELCOME)]
|
||||
tail = initialbuf[len(MSG_WELCOME):]
|
||||
if head != MSG_WELCOME:
|
||||
raise error, "connected to something not a game server"
|
||||
if '\n' in tail:
|
||||
break
|
||||
n = tail.index('\n')
|
||||
line2 = tail[:n]
|
||||
self.initialbuf = tail[n+1:]
|
||||
|
||||
self.gameident = line2.strip()
|
||||
## self.datapath = None
|
||||
## if self.gameident.endswith(']'):
|
||||
## i = self.gameident.rfind('[')
|
||||
## if i >= 0:
|
||||
## self.gameident, self.datapath = (self.gameident[:i].strip(),
|
||||
## self.gameident[i+1:-1])
|
||||
print "connected to %r." % self.gameident
|
||||
self.s.sendall(message(CMSG_PROTO_VERSION, 3))
|
||||
|
||||
def setup(self, mode, udp_over_tcp):
|
||||
self.playing = {} # 0, 1, or 'l' for local
|
||||
self.keys = {}
|
||||
self.keycodes = {}
|
||||
self.last_key_event = (None, None)
|
||||
self.dpy = None
|
||||
self.snd = None
|
||||
self.pixmaps = {} # {bmpcode: dpy_pixmap}
|
||||
self.bitmaps = {} # {bmpcode: (fileid_or_data, colorkey)}
|
||||
self.icons = {}
|
||||
self.sounds = {}
|
||||
self.currentmusic = None
|
||||
self.fileids = {}
|
||||
self.sprites = []
|
||||
self.playingsounds = {}
|
||||
self.playericons = {}
|
||||
self.screenmode = mode
|
||||
self.initlevel = 0
|
||||
if mode[-1].has_key('udp_over_tcp'):
|
||||
udp_over_tcp = mode[-1]['udp_over_tcp']
|
||||
self.trackcfgmtime = None
|
||||
if mode[-1].has_key('cfgfile'):
|
||||
self.trackcfgfile = mode[-1]['cfgfile']
|
||||
else:
|
||||
self.trackcfgfile = os.path.join(DataChunk.SOURCEDIR,
|
||||
'http2', 'config.txt')
|
||||
self.udpsock = None
|
||||
self.udpsock_low = None
|
||||
self.udpsock2 = None
|
||||
self.accepted_broadcast = 0
|
||||
self.tcpbytecounter = 0
|
||||
self.udpbytecounter = 0
|
||||
if udp_over_tcp == 1:
|
||||
self.start_udp_over_tcp()
|
||||
else:
|
||||
self.pending_udp_data = None
|
||||
if udp_over_tcp == 'auto':
|
||||
self.udpsock_low = 0
|
||||
self.dyndecompress = [[None, None, None, None] for i in range(8)]
|
||||
self.dynnorepeat = None
|
||||
|
||||
def run(self, mode, udp_over_tcp='auto'):
|
||||
self.setup(mode, udp_over_tcp)
|
||||
try:
|
||||
self.mainloop()
|
||||
finally:
|
||||
if self.dpy:
|
||||
self.dpy.close()
|
||||
try:
|
||||
self.s.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
def mainloop(self):
|
||||
pss = hostchooser.serverside_ping()
|
||||
self.initial_iwtd = [self.s, pss]
|
||||
self.iwtd = self.initial_iwtd[:]
|
||||
self.animdelay = 0.0
|
||||
inbuf = self.process_inbuf(self.initialbuf)
|
||||
self.initialbuf = ""
|
||||
errors = 0
|
||||
while 1:
|
||||
if self.dpy:
|
||||
self.processkeys()
|
||||
iwtd, owtd, ewtd = select(self.iwtd, [], [], self.animdelay)
|
||||
self.animdelay = 0.5
|
||||
if self.dpy:
|
||||
self.processkeys()
|
||||
if self.s in iwtd:
|
||||
inputdata = self.s.recv(0x6000)
|
||||
self.tcpbytecounter += len(inputdata)
|
||||
inbuf += inputdata
|
||||
inbuf = self.process_inbuf(inbuf)
|
||||
if self.dpy:
|
||||
if self.udpsock in iwtd:
|
||||
udpdata1 = None
|
||||
while self.udpsock in iwtd:
|
||||
try:
|
||||
udpdata = self.udpsock.recv(65535)
|
||||
except error, e:
|
||||
print >> sys.stderr, e
|
||||
errors += 1
|
||||
if errors > 10:
|
||||
raise
|
||||
break
|
||||
self.udpbytecounter += len(udpdata)
|
||||
if len(udpdata) > 3 and '\x80' <= udpdata[0] < '\x90':
|
||||
udpdata = self.dynamic_decompress(udpdata)
|
||||
if udpdata is not None:
|
||||
udpdata1 = udpdata
|
||||
iwtd, owtd, ewtd = select(self.iwtd, [], [], 0)
|
||||
if udpdata1 is not None:
|
||||
self.update_sprites(udpdata1)
|
||||
if self.udpsock2 in iwtd:
|
||||
while self.udpsock2 in iwtd:
|
||||
udpdata = self.udpsock2.recv(65535)
|
||||
self.udpbytecounter += len(udpdata)
|
||||
if udpdata == BROADCAST_MESSAGE:
|
||||
if not self.accepted_broadcast:
|
||||
self.s.sendall(message(CMSG_UDP_PORT, '*'))
|
||||
self.accepted_broadcast = 1
|
||||
#self.udpsock_low = None
|
||||
udpdata = ''
|
||||
iwtd, owtd, ewtd = select(self.iwtd, [], [], 0)
|
||||
if udpdata and self.accepted_broadcast:
|
||||
self.update_sprites(udpdata)
|
||||
if self.pending_udp_data:
|
||||
self.update_sprites(self.pending_udp_data)
|
||||
self.pending_udp_data = ''
|
||||
erasetb = self.taskbarmode and self.draw_taskbar()
|
||||
d = self.dpy.flip()
|
||||
if d:
|
||||
self.animdelay = min(self.animdelay, d)
|
||||
if self.snd:
|
||||
d = self.snd.flop()
|
||||
if d:
|
||||
self.animdelay = min(self.animdelay, d)
|
||||
if erasetb:
|
||||
self.erase_taskbar(erasetb)
|
||||
if pss in iwtd:
|
||||
hostchooser.answer_ping(pss, self.gameident, self.sockaddr)
|
||||
|
||||
def process_inbuf(self, inbuf):
|
||||
while inbuf:
|
||||
values, inbuf = decodemessage(inbuf)
|
||||
if not values:
|
||||
break # incomplete message
|
||||
fn = Playfield.MESSAGES.get(values[0], self.msg_unknown)
|
||||
fn(self, *values[1:])
|
||||
return inbuf
|
||||
|
||||
def dynamic_decompress(self, udpdata):
|
||||
# Format of a UDP version 3 packet:
|
||||
# header byte: 0x80 - 0x87 packet from thread 0 - 7
|
||||
# or 0x88 - 0x8F reset packet from thread 0 - 7
|
||||
# previous frame in same thread (1 byte)
|
||||
# frame number (1 byte)
|
||||
thread = self.dyndecompress[ord(udpdata[0]) & 7]
|
||||
# thread==[decompress, lastframenumber, recompressed, lastframedata]
|
||||
prevframe = udpdata[1]
|
||||
thisframe = udpdata[2]
|
||||
#print '---'
|
||||
#for t in self.dyndecompress:
|
||||
# print repr(t)[:120]
|
||||
#print
|
||||
#print `udpdata[:3]`
|
||||
|
||||
if udpdata[0] >= '\x88':
|
||||
# reset
|
||||
d = zlib.decompressobj().decompress
|
||||
if prevframe != thisframe: # if not global sync point
|
||||
# sync point from a previous frame
|
||||
# find all threads with the same prevframe
|
||||
threads = [t for t in self.dyndecompress if prevframe == t[1]]
|
||||
if not threads:
|
||||
return None # lost
|
||||
# find a thread with already-recompressed data
|
||||
for t in threads:
|
||||
if t[2]:
|
||||
data = t[3]
|
||||
break
|
||||
else:
|
||||
# recompress and cache the prevframe data
|
||||
t = threads[0]
|
||||
data = t[3]
|
||||
co = zlib.compressobj(6)
|
||||
data = co.compress(data) + co.flush(zlib.Z_SYNC_FLUSH)
|
||||
t[2] = 1
|
||||
t[3] = data
|
||||
d(data) # use it to initialize the state of the decompressobj
|
||||
#print d
|
||||
thread[0] = d
|
||||
elif prevframe != thread[1]:
|
||||
#print 'lost'
|
||||
return None # lost
|
||||
else:
|
||||
d = thread[0]
|
||||
# go forward in thread
|
||||
try:
|
||||
framedata = d(udpdata[3:])
|
||||
#print d
|
||||
thread[1] = thisframe
|
||||
thread[2] = 0
|
||||
thread[3] = framedata
|
||||
if thisframe == self.dynnorepeat:
|
||||
return None
|
||||
self.dynnorepeat = thisframe
|
||||
return framedata
|
||||
except zlib.error:
|
||||
#print 'crash'
|
||||
return None
|
||||
|
||||
def geticon(self, icocode):
|
||||
try:
|
||||
return self.icons[icocode]
|
||||
except KeyError:
|
||||
ico = self.icons[icocode] = Icon(self)
|
||||
return ico
|
||||
|
||||
def getpixmap(self, bmpcode):
|
||||
try:
|
||||
return self.pixmaps[bmpcode]
|
||||
except KeyError:
|
||||
data, colorkey = self.bitmaps[bmpcode]
|
||||
if type(data) is type(''):
|
||||
data = zlib.decompress(data)
|
||||
else:
|
||||
if data.pending:
|
||||
raise KeyError
|
||||
data = data.read()
|
||||
pixmap = loadpixmap(self.dpy, data, colorkey)
|
||||
self.pixmaps[bmpcode] = pixmap
|
||||
return pixmap
|
||||
|
||||
def update_sprites(self, udpdata):
|
||||
sprites = self.sprites
|
||||
unpack = struct.unpack
|
||||
|
||||
currentsounds = {}
|
||||
base = 0
|
||||
while udpdata[base+4:base+6] == '\xFF\xFF':
|
||||
key, lvol, rvol = struct.unpack("!hBB", udpdata[base:base+4])
|
||||
try:
|
||||
snd = self.sounds[key]
|
||||
except KeyError:
|
||||
pass # ignore sounds with bad code (probably not defined yet)
|
||||
else:
|
||||
n = self.playingsounds.get(key)
|
||||
if n:
|
||||
currentsounds[key] = n-1
|
||||
elif self.snd:
|
||||
self.snd.play(snd,
|
||||
lvol / 255.0,
|
||||
rvol / 255.0)
|
||||
currentsounds[key] = 4
|
||||
base += 6
|
||||
self.playingsounds = currentsounds
|
||||
|
||||
for j in range(len(sprites)):
|
||||
if sprites[j][0] != udpdata[base:base+6]:
|
||||
removes = sprites[j:]
|
||||
del sprites[j:]
|
||||
removes.reverse()
|
||||
eraser = self.dpy.putppm
|
||||
for reserved, eraseargs in removes:
|
||||
eraser(*eraseargs)
|
||||
break
|
||||
base += 6
|
||||
#print "%d sprites redrawn" % (len(udpdata)/6-j)
|
||||
try:
|
||||
overlayer = self.dpy.overlayppm
|
||||
except AttributeError:
|
||||
getter = self.dpy.getppm
|
||||
setter = self.dpy.putppm
|
||||
for j in range(base, len(udpdata)-5, 6):
|
||||
info = udpdata[j:j+6]
|
||||
x, y, icocode = unpack("!hhh", info[:6])
|
||||
try:
|
||||
ico = self.icons[icocode]
|
||||
sprites.append((info, (x, y, getter((x, y) + ico.size))))
|
||||
setter(x, y, ico.pixmap, ico.rect)
|
||||
except KeyError:
|
||||
#print "bad ico code", icocode
|
||||
pass # ignore sprites with bad ico (probably not defined yet)
|
||||
else:
|
||||
for j in range(base, len(udpdata)-5, 6):
|
||||
info = udpdata[j:j+6]
|
||||
x, y, icocode = unpack("!hhh", info[:6])
|
||||
try:
|
||||
ico = self.icons[icocode]
|
||||
overlay = overlayer(x, y, ico.pixmap, ico.rect, ico.alpha)
|
||||
sprites.append((info, overlay))
|
||||
except KeyError:
|
||||
#print "bad ico code", icocode
|
||||
pass # ignore sprites with bad ico (probably not defined yet)
|
||||
|
||||
t0, n = self.painttimes
|
||||
n = n + 1
|
||||
if n == 50:
|
||||
t = time.time()
|
||||
t, t0 = t-t0, t
|
||||
if t:
|
||||
print "%.2f images per second, %.1f kbytes per second" % (
|
||||
float(n)/t,
|
||||
float(self.tcpbytecounter+self.udpbytecounter)/1024/t)
|
||||
self.tcpbytecounter = -self.udpbytecounter
|
||||
n = 0
|
||||
self.painttimes = t0, n
|
||||
|
||||
def get_taskbar(self):
|
||||
y0 = self.height - self.TASKBAR_HEIGHT
|
||||
iconlist = []
|
||||
f = 1.5 * time.time()
|
||||
f = f-int(f)
|
||||
pi = self.playericons.items()
|
||||
pi.sort()
|
||||
xpos = 0
|
||||
for id, ico in pi:
|
||||
if self.playing.get(id) != 'l':
|
||||
w, h = ico.size
|
||||
xpos += int(w * 5 / 3)
|
||||
if not self.playing.get(id):
|
||||
y = self.height - h
|
||||
if self.keydefinition and id == self.keydefinition[0]:
|
||||
num, icons = self.keys[self.nextkeyname()]
|
||||
ico = icons[int(f*len(icons))-1]
|
||||
y = y0 + int((self.TASKBAR_HEIGHT-ico.size[1])/2)
|
||||
self.animdelay = 0.04
|
||||
iconlist.append((xpos-w, y, ico, id))
|
||||
pi.reverse()
|
||||
f = f * (1.0-f) * 4.0
|
||||
xpos = self.width
|
||||
for id, ico in pi:
|
||||
if self.playing.get(id) == 'l':
|
||||
w, h = ico.size
|
||||
xpos -= int(w * 5 / 3)
|
||||
dy = self.TASKBAR_HEIGHT - h - 1
|
||||
y = self.height - h - int(dy*f)
|
||||
iconlist.append((xpos, y, ico, id))
|
||||
self.animdelay = 0.04
|
||||
return y0, iconlist
|
||||
|
||||
def clic_taskbar(self, (cx,cy)):
|
||||
y0, icons = self.get_taskbar()
|
||||
if cy >= y0:
|
||||
for x, y, ico, id in icons:
|
||||
if x <= cx < x+ico.size[0]:
|
||||
return id
|
||||
return None
|
||||
|
||||
def draw_taskbar(self):
|
||||
y0, icons = self.get_taskbar()
|
||||
rect = (0, y0, self.width, self.TASKBAR_HEIGHT)
|
||||
bkgnd = self.dpy.getppm(rect)
|
||||
self.dpy.taskbar(rect)
|
||||
for x, y, ico, id in icons:
|
||||
try:
|
||||
self.dpy.putppm(x, y, ico.pixmap, ico.rect)
|
||||
except KeyError:
|
||||
pass
|
||||
return y0, bkgnd
|
||||
|
||||
def erase_taskbar(self, (y0, bkgnd)):
|
||||
self.dpy.putppm(0, y0, bkgnd)
|
||||
|
||||
def nextkeyname(self):
|
||||
pid, df = self.keydefinition
|
||||
undef = [(num, keyname) for keyname, (num, icons) in self.keys.items()
|
||||
if not df.has_key(keyname) and icons]
|
||||
if undef:
|
||||
num, keyname = min(undef)
|
||||
return keyname
|
||||
else:
|
||||
return None
|
||||
|
||||
def startplaying(self):
|
||||
args = ()
|
||||
if hasattr(self.s, 'udp_over_udp_mixer'):
|
||||
# for SocketOverUdp: reuse the UDP address
|
||||
port = self.s.getsockname()[1]
|
||||
self.udpsock_low = None
|
||||
self.s.udp_over_udp_decoder = self.udp_over_udp_decoder
|
||||
self.start_udp_over_tcp()
|
||||
elif self.pending_udp_data is not None:
|
||||
port = MSG_INLINE_FRAME
|
||||
else:
|
||||
if '*udpsock*' in PORTS:
|
||||
self.udpsock, (host, port) = PORTS['*udpsock*']
|
||||
args = (host,)
|
||||
else:
|
||||
self.udpsock = socket(AF_INET, SOCK_DGRAM)
|
||||
self.udpsock.bind(('', PORTS.get('CLIENT', INADDR_ANY)))
|
||||
host, port = self.udpsock.getsockname()
|
||||
# Send a dummy UDP message to the server. Some NATs will
|
||||
# then let through the UDP messages from the server.
|
||||
self.udpsock.sendto('.', self.s.getpeername())
|
||||
self.iwtd.append(self.udpsock)
|
||||
self.initial_iwtd.append(self.udpsock)
|
||||
if 'sendudpto' in PORTS:
|
||||
args = (PORTS['sendudpto'],)
|
||||
outbound = []
|
||||
outbound.append(message(CMSG_UDP_PORT, port, *args))
|
||||
if self.snd and self.snd.has_music:
|
||||
outbound.append(message(CMSG_ENABLE_MUSIC, 1))
|
||||
outbound.append(message(CMSG_PING))
|
||||
self.s.sendall(''.join(outbound))
|
||||
|
||||
def start_udp_over_tcp(self):
|
||||
self.pending_udp_data = ''
|
||||
self.udp_over_tcp_decompress = zlib.decompressobj().decompress
|
||||
self.udpsock_low = None
|
||||
for name in ('udpsock', 'udpsock2'):
|
||||
sock = getattr(self, name)
|
||||
if sock is not None:
|
||||
try:
|
||||
self.iwtd.remove(sock)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
self.initial_iwtd.remove(sock)
|
||||
except ValueError:
|
||||
pass
|
||||
sock.close()
|
||||
setattr(self, name, None)
|
||||
|
||||
def udp_over_udp_decoder(self, udpdata):
|
||||
if len(udpdata) > 3 and '\x80' <= udpdata[0] < '\x90':
|
||||
data = self.dynamic_decompress(udpdata)
|
||||
if data:
|
||||
self.pending_udp_data = data
|
||||
|
||||
def processkeys(self):
|
||||
keyevents = self.dpy.keyevents()
|
||||
if keyevents:
|
||||
now = time.time()
|
||||
pending = {}
|
||||
for keysym, event in keyevents:
|
||||
pending[keysym] = event
|
||||
for keysym, event in pending.items():
|
||||
code = self.keycodes.get((keysym, event))
|
||||
if code and self.playing.get(code[0]) == 'l':
|
||||
if (code == self.last_key_event[0] and
|
||||
now - self.last_key_event[1] < 0.77):
|
||||
continue # don't send too much events for auto-repeat
|
||||
self.last_key_event = code, now
|
||||
self.s.sendall(code[1])
|
||||
elif self.keydefinition:
|
||||
self.define_key(keysym)
|
||||
pointermotion = self.dpy.pointermotion()
|
||||
if pointermotion:
|
||||
x, y = pointermotion
|
||||
self.settaskbar(y >= self.height - 2*self.TASKBAR_HEIGHT)
|
||||
mouseevents = self.dpy.mouseevents()
|
||||
if mouseevents:
|
||||
self.settaskbar(1)
|
||||
self.keydefinition = None
|
||||
for clic in mouseevents:
|
||||
clic_id = self.clic_taskbar(clic)
|
||||
if clic_id is not None:
|
||||
if self.playing.get(clic_id) == 'l':
|
||||
self.s.sendall(message(CMSG_REMOVE_PLAYER, clic_id))
|
||||
else:
|
||||
self.keydefinition = clic_id, {}
|
||||
if self.taskbartimeout is not None and time.time() > self.taskbartimeout:
|
||||
self.settaskbar(0)
|
||||
|
||||
def settaskbar(self, nmode):
|
||||
self.taskbartimeout = None
|
||||
if self.taskbarfree:
|
||||
self.taskbarmode = (nmode or
|
||||
'l' not in self.playing.values() or
|
||||
(self.keydefinition is not None))
|
||||
if nmode:
|
||||
self.taskbartimeout = time.time() + 5.0
|
||||
if hasattr(self.dpy, 'settaskbar'):
|
||||
self.dpy.settaskbar(self.taskbarmode)
|
||||
|
||||
def define_key(self, keysym):
|
||||
clic_id, df = self.keydefinition
|
||||
if keysym in df.values():
|
||||
return
|
||||
df[self.nextkeyname()] = keysym
|
||||
if self.nextkeyname() is not None:
|
||||
return
|
||||
self.keydefinition = None
|
||||
self.s.sendall(message(CMSG_ADD_PLAYER, clic_id))
|
||||
for keyname, (num, icons) in self.keys.items():
|
||||
if keyname[:1] == '-':
|
||||
event = KeyReleased
|
||||
keyname = keyname[1:]
|
||||
else:
|
||||
event = KeyPressed
|
||||
if df.has_key(keyname):
|
||||
keysym = df[keyname]
|
||||
self.keycodes[keysym, event] = \
|
||||
clic_id, message(CMSG_KEY, clic_id, num)
|
||||
|
||||
def msg_unknown(self, *rest):
|
||||
print >> sys.stderr, "?"
|
||||
|
||||
def msg_player_join(self, id, local, *rest):
|
||||
if local:
|
||||
self.playing[id] = 'l'
|
||||
self.settaskbar(0)
|
||||
self.checkcfgfile(1)
|
||||
else:
|
||||
self.playing[id] = 1
|
||||
|
||||
def msg_player_kill(self, id, *rest):
|
||||
self.playing[id] = 0
|
||||
for key, (pid, msg) in self.keycodes.items():
|
||||
if pid == id:
|
||||
del self.keycodes[key]
|
||||
|
||||
def msg_broadcast_port(self, port):
|
||||
if self.pending_udp_data is not None:
|
||||
return
|
||||
if self.udpsock2 is not None:
|
||||
try:
|
||||
self.iwtd.remove(self.udpsock2)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
self.initial_iwtd.remove(self.udpsock2)
|
||||
except ValueError:
|
||||
pass
|
||||
self.udpsock2.close()
|
||||
self.udpsock2 = None
|
||||
self.accepted_broadcast = 0
|
||||
try:
|
||||
self.udpsock2 = socket(AF_INET, SOCK_DGRAM)
|
||||
self.udpsock2.bind(('', port))
|
||||
self.udpsock2.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
except error, e:
|
||||
print "Cannot listen on the broadcast port %d" % port, str(e)
|
||||
self.udpsock2 = None
|
||||
else:
|
||||
self.iwtd.append(self.udpsock2)
|
||||
self.initial_iwtd.append(self.udpsock2)
|
||||
|
||||
def msg_def_playfield(self, width, height, backcolor=None,
|
||||
gameident=None, *rest):
|
||||
#if self.snd is not None:
|
||||
# self.snd.close()
|
||||
if self.dpy is not None:
|
||||
# clear all pixmaps
|
||||
for ico in self.icons.values():
|
||||
ico.clear()
|
||||
self.pixmaps.clear()
|
||||
self.dpy.close()
|
||||
del self.sprites[:]
|
||||
self.width = width
|
||||
self.height = height
|
||||
if gameident:
|
||||
self.gameident = gameident
|
||||
self.dpy = modes.open_dpy(self.screenmode, width, height, self.gameident)
|
||||
self.snd = self.snd or modes.open_snd(self.screenmode)
|
||||
if self.snd:
|
||||
self.s.sendall(message(CMSG_ENABLE_SOUND))
|
||||
self.iwtd = self.dpy.selectlist() + self.initial_iwtd
|
||||
self.dpy.clear() # backcolor is ignored
|
||||
self.painttimes = (time.time(), 0)
|
||||
self.s.sendall(message(CMSG_PING))
|
||||
self.taskbarmode = 0
|
||||
self.taskbarfree = 0
|
||||
self.taskbartimeout = None
|
||||
self.keydefinition = None
|
||||
|
||||
def msg_def_key(self, name, num, *icons):
|
||||
self.keys[name] = num, [self.geticon(ico) for ico in icons]
|
||||
|
||||
def msg_def_icon(self, bmpcode, icocode, x, y, w, h, alpha=255, *rest):
|
||||
## if h<0:
|
||||
## try:
|
||||
## bitmap, height = self.flippedbitmaps[bmpcode]
|
||||
## except KeyError:
|
||||
## bitmap, height = self.dpy.vflipppm(self.bitmaps[bmpcode])
|
||||
## self.flippedbitmaps[bmpcode] = bitmap, height
|
||||
## y = height - y
|
||||
## h = - h
|
||||
## else:
|
||||
ico = self.geticon(icocode)
|
||||
ico.bmpcode = bmpcode
|
||||
ico.rect = x, y, w, h
|
||||
ico.size = w, h
|
||||
if alpha < 255:
|
||||
ico.alpha = alpha
|
||||
|
||||
def msg_def_bitmap(self, bmpcode, data, colorkey=None, *rest):
|
||||
if type(data) is not type(''):
|
||||
data = self.fileids[data]
|
||||
self.bitmaps[bmpcode] = data, colorkey
|
||||
|
||||
def msg_def_sample(self, smpcode, data, *rest):
|
||||
def ready(f, self=self, smpcode=smpcode):
|
||||
if self.snd:
|
||||
self.sounds[smpcode] = self.snd.sound(f)
|
||||
f.clear()
|
||||
if type(data) is type(''):
|
||||
data = zlib.decompress(data)
|
||||
f = DataChunk(None)
|
||||
f.store(0, data)
|
||||
ready(f)
|
||||
else:
|
||||
f = self.fileids[data]
|
||||
f.when_ready(ready)
|
||||
|
||||
def msg_patch_file(self, fileid, position, data, lendata=None, *rest):
|
||||
if self.fileids.has_key(fileid):
|
||||
f = self.fileids[fileid]
|
||||
else:
|
||||
f = self.fileids[fileid] = DataChunk(fileid)
|
||||
f.server_patch(position, data, lendata or len(data))
|
||||
|
||||
def msg_zpatch_file(self, fileid, position, data, *rest):
|
||||
data1 = zlib.decompress(data)
|
||||
self.msg_patch_file(fileid, position, data1, len(data), *rest)
|
||||
|
||||
def msg_md5_file(self, fileid, filename, position, length, checksum, *rest):
|
||||
if self.fileids.has_key(fileid):
|
||||
f = self.fileids[fileid]
|
||||
else:
|
||||
f = self.fileids[fileid] = DataChunk(fileid)
|
||||
f.server_md5(self, filename, position, length, checksum)
|
||||
|
||||
def msg_play_music(self, loop_from, *codes):
|
||||
codes = [self.fileids[c] for c in codes]
|
||||
self.currentmusic = loop_from, codes, list(codes)
|
||||
self.activate_music()
|
||||
|
||||
def activate_music(self, f=None):
|
||||
loop_from, codes, checkcodes = self.currentmusic
|
||||
if checkcodes:
|
||||
checkcodes.pop().when_ready(self.activate_music)
|
||||
elif self.snd:
|
||||
self.snd.play_musics(codes, loop_from)
|
||||
|
||||
def msg_fadeout(self, time, *rest):
|
||||
if self.snd:
|
||||
self.snd.fadeout(time)
|
||||
|
||||
def msg_player_icon(self, pid, icocode, *rest):
|
||||
self.playericons[pid] = self.geticon(icocode)
|
||||
|
||||
def checkcfgfile(self, force=0):
|
||||
if self.trackcfgfile:
|
||||
try:
|
||||
st = os.stat(self.trackcfgfile)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
if force or (st.st_mtime != self.trackcfgmtime):
|
||||
self.trackcfgmtime = st.st_mtime
|
||||
try:
|
||||
f = open(self.trackcfgfile, 'r')
|
||||
data = f.read().strip()
|
||||
f.close()
|
||||
d = eval(data or '{}', {}, {})
|
||||
except:
|
||||
print >> sys.stderr, 'Invalid config file format'
|
||||
else:
|
||||
d = d.get(gethostname(), {})
|
||||
namemsg = ''
|
||||
for id, local in self.playing.items():
|
||||
keyid = 'player%d' % id
|
||||
if local == 'l' and d.has_key(keyid):
|
||||
namemsg = namemsg + message(
|
||||
CMSG_PLAYER_NAME, id, d[keyid])
|
||||
if namemsg:
|
||||
self.s.sendall(namemsg)
|
||||
|
||||
def msg_ping(self, *rest):
|
||||
self.s.sendall(message(CMSG_PONG, *rest))
|
||||
self.checkcfgfile()
|
||||
if rest and self.udpsock_low is not None:
|
||||
udpkbytes = rest[0]
|
||||
if not udpkbytes:
|
||||
return
|
||||
#inp = self.udpbytecounter / (udpkbytes*1024.0)
|
||||
#print "(%d%% packet loss)" % int(100*(1.0-inp))
|
||||
if (udpkbytes<<10) * UDP_EXPECTED_RATIO > self.udpbytecounter:
|
||||
# too many packets were dropped (including, maybe, all of them)
|
||||
self.udpsock_low += 1
|
||||
if self.udpsock_low >= 3 and self.initlevel >= 1:
|
||||
# third time now -- that's too much
|
||||
print "Note: routing UDP traffic over TCP",
|
||||
inp = self.udpbytecounter / (udpkbytes*1024.0)
|
||||
print "(%d%% packet loss)" % int(100*(1.0-inp))
|
||||
self.start_udp_over_tcp()
|
||||
self.s.sendall(message(CMSG_UDP_PORT, MSG_INLINE_FRAME))
|
||||
else:
|
||||
# enough packets received
|
||||
self.udpsock_low = 0
|
||||
|
||||
def msg_pong(self, *rest):
|
||||
if self.initlevel == 0:
|
||||
self.startplaying()
|
||||
self.initlevel = 1
|
||||
elif self.initlevel == 1:
|
||||
if self.snd and self.snd.has_music:
|
||||
self.s.sendall(message(CMSG_ENABLE_MUSIC, 2))
|
||||
self.initlevel = 2
|
||||
if not self.taskbarfree and not self.taskbarmode:
|
||||
self.taskbarfree = 1
|
||||
self.settaskbar(1)
|
||||
|
||||
def msg_inline_frame(self, data, *rest):
|
||||
if self.pending_udp_data is not None:
|
||||
self.pending_udp_data = self.udp_over_tcp_decompress(data)
|
||||
|
||||
MESSAGES = {
|
||||
MSG_BROADCAST_PORT:msg_broadcast_port,
|
||||
MSG_DEF_PLAYFIELD: msg_def_playfield,
|
||||
MSG_DEF_KEY : msg_def_key,
|
||||
MSG_DEF_ICON : msg_def_icon,
|
||||
MSG_DEF_BITMAP : msg_def_bitmap,
|
||||
MSG_DEF_SAMPLE : msg_def_sample,
|
||||
MSG_PLAY_MUSIC : msg_play_music,
|
||||
MSG_FADEOUT : msg_fadeout,
|
||||
MSG_PLAYER_JOIN : msg_player_join,
|
||||
MSG_PLAYER_KILL : msg_player_kill,
|
||||
MSG_PLAYER_ICON : msg_player_icon,
|
||||
MSG_PING : msg_ping,
|
||||
MSG_PONG : msg_pong,
|
||||
MSG_INLINE_FRAME : msg_inline_frame,
|
||||
MSG_PATCH_FILE : msg_patch_file,
|
||||
MSG_ZPATCH_FILE : msg_zpatch_file,
|
||||
MSG_MD5_FILE : msg_md5_file,
|
||||
## MSG_LOAD_PREFIX : msg_load_prefix,
|
||||
}
|
||||
|
||||
|
||||
def run(s, sockaddr, *args, **kw):
|
||||
try:
|
||||
import psyco
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
psyco.bind(Playfield.update_sprites)
|
||||
Playfield(s, sockaddr).run(*args, **kw)
|
@ -3,13 +3,13 @@
|
||||
import sys, os, gzip
|
||||
from socket import *
|
||||
from select import select
|
||||
import cStringIO, struct, zlib
|
||||
import io, struct, zlib
|
||||
import time
|
||||
sys.path.insert(0, os.pardir)
|
||||
from common.msgstruct import *
|
||||
from common import hostchooser
|
||||
import modes
|
||||
from modes import KeyPressed, KeyReleased
|
||||
from . import modes
|
||||
from .modes import KeyPressed, KeyReleased
|
||||
|
||||
#import psyco; psyco.full()
|
||||
|
||||
@ -17,7 +17,7 @@ SOURCEDIR = os.pardir
|
||||
|
||||
|
||||
def loadpixmap(dpy, data, colorkey=None):
|
||||
f = cStringIO.StringIO(data)
|
||||
f = io.StringIO(data)
|
||||
sig = f.readline().strip()
|
||||
assert sig == "P6"
|
||||
while 1:
|
||||
@ -25,7 +25,7 @@ def loadpixmap(dpy, data, colorkey=None):
|
||||
if not line.startswith('#'):
|
||||
break
|
||||
wh = line.split()
|
||||
w, h = map(int, wh)
|
||||
w, h = list(map(int, wh))
|
||||
sig = f.readline().strip()
|
||||
assert sig == "255"
|
||||
data = f.read()
|
||||
@ -38,7 +38,8 @@ def loadpixmap(dpy, data, colorkey=None):
|
||||
return dpy.pixmap(w, h, data, colorkey)
|
||||
|
||||
class Icon:
|
||||
def __init__(self, bitmap, (x, y, w, h), alpha):
|
||||
def __init__(self, bitmap, xxx_todo_changeme, alpha):
|
||||
(x, y, w, h) = xxx_todo_changeme
|
||||
self.rect = x, y, w, h
|
||||
self.size = w, h
|
||||
self.bitmap = bitmap
|
||||
@ -70,7 +71,7 @@ class Playback:
|
||||
#print values[0],
|
||||
fn = Playback.MESSAGES.get(values[0], self.msg_unknown)
|
||||
fn(self, *values[1:])
|
||||
print '%d frames in file.' % len(self.frames)
|
||||
print('%d frames in file.' % len(self.frames))
|
||||
f.close()
|
||||
assert self.width, "no playfield definition found in file"
|
||||
|
||||
@ -83,13 +84,13 @@ class Playback:
|
||||
|
||||
def buildicons(self):
|
||||
bitmaps = {}
|
||||
for bmpcode, (data, colorkey) in self.defbitmaps.items():
|
||||
for bmpcode, (data, colorkey) in list(self.defbitmaps.items()):
|
||||
if isinstance(data, str):
|
||||
data = zlib.decompress(data)
|
||||
else:
|
||||
data = self.deffiles[data]
|
||||
bitmaps[bmpcode] = loadpixmap(self.dpy, data, colorkey)
|
||||
for icocode, (bmpcode, rect, alpha) in self.deficons.items():
|
||||
for icocode, (bmpcode, rect, alpha) in list(self.deficons.items()):
|
||||
self.icons[icocode] = Icon(bitmaps[bmpcode], rect, alpha)
|
||||
|
||||
def go(self, n):
|
||||
@ -101,9 +102,9 @@ class Playback:
|
||||
"shm only!"
|
||||
w, h, data, reserved = self.dpy.getppm((0, 0, self.width, self.height))
|
||||
f = open(filename or ('frame%d.ppm' % self.n), 'wb')
|
||||
print >> f, 'P6'
|
||||
print >> f, w, h
|
||||
print >> f, 255
|
||||
print('P6', file=f)
|
||||
print(w, h, file=f)
|
||||
print(255, file=f)
|
||||
for i in range(0, len(data), 4):
|
||||
f.write(data[i+2]+data[i+1]+data[i])
|
||||
f.close()
|
||||
|
203
display/playback.py.bak
Normal file
203
display/playback.py.bak
Normal file
@ -0,0 +1,203 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import sys, os, gzip
|
||||
from socket import *
|
||||
from select import select
|
||||
import cStringIO, struct, zlib
|
||||
import time
|
||||
sys.path.insert(0, os.pardir)
|
||||
from common.msgstruct import *
|
||||
from common import hostchooser
|
||||
import modes
|
||||
from modes import KeyPressed, KeyReleased
|
||||
|
||||
#import psyco; psyco.full()
|
||||
|
||||
SOURCEDIR = os.pardir
|
||||
|
||||
|
||||
def loadpixmap(dpy, data, colorkey=None):
|
||||
f = cStringIO.StringIO(data)
|
||||
sig = f.readline().strip()
|
||||
assert sig == "P6"
|
||||
while 1:
|
||||
line = f.readline().strip()
|
||||
if not line.startswith('#'):
|
||||
break
|
||||
wh = line.split()
|
||||
w, h = map(int, wh)
|
||||
sig = f.readline().strip()
|
||||
assert sig == "255"
|
||||
data = f.read()
|
||||
f.close()
|
||||
if colorkey is None:
|
||||
colorkey = -1
|
||||
elif colorkey < 0:
|
||||
r, g, b = struct.unpack("BBB", self.data[:3])
|
||||
colorkey = b | (g<<8) | (r<<16)
|
||||
return dpy.pixmap(w, h, data, colorkey)
|
||||
|
||||
class Icon:
|
||||
def __init__(self, bitmap, (x, y, w, h), alpha):
|
||||
self.rect = x, y, w, h
|
||||
self.size = w, h
|
||||
self.bitmap = bitmap
|
||||
self.alpha = alpha
|
||||
|
||||
|
||||
class Playback:
|
||||
gameident = 'Playback'
|
||||
|
||||
def __init__(self, filename, mode=('x', 'off', {})):
|
||||
f = gzip.open(filename, 'rb')
|
||||
self.screenmode = mode
|
||||
self.width = None
|
||||
self.deffiles = {}
|
||||
self.defbitmaps = {}
|
||||
self.deficons = {}
|
||||
self.icons = {}
|
||||
self.frames = []
|
||||
inbuf = ''
|
||||
while 1:
|
||||
values, inbuf = decodemessage(inbuf)
|
||||
if not values:
|
||||
# incomplete message
|
||||
data = f.read(8192)
|
||||
if not data:
|
||||
break
|
||||
inbuf += data
|
||||
else:
|
||||
#print values[0],
|
||||
fn = Playback.MESSAGES.get(values[0], self.msg_unknown)
|
||||
fn(self, *values[1:])
|
||||
print '%d frames in file.' % len(self.frames)
|
||||
f.close()
|
||||
assert self.width, "no playfield definition found in file"
|
||||
|
||||
self.dpy = modes.open_dpy(self.screenmode,
|
||||
self.width, self.height, self.gameident)
|
||||
self.dpy.clear() # backcolor is ignored
|
||||
self.sprites = []
|
||||
self.buildicons()
|
||||
self.go(0)
|
||||
|
||||
def buildicons(self):
|
||||
bitmaps = {}
|
||||
for bmpcode, (data, colorkey) in self.defbitmaps.items():
|
||||
if isinstance(data, str):
|
||||
data = zlib.decompress(data)
|
||||
else:
|
||||
data = self.deffiles[data]
|
||||
bitmaps[bmpcode] = loadpixmap(self.dpy, data, colorkey)
|
||||
for icocode, (bmpcode, rect, alpha) in self.deficons.items():
|
||||
self.icons[icocode] = Icon(bitmaps[bmpcode], rect, alpha)
|
||||
|
||||
def go(self, n):
|
||||
self.n = n
|
||||
self.update_sprites(self.frames[n])
|
||||
self.dpy.flip()
|
||||
|
||||
def save(self, filename=None):
|
||||
"shm only!"
|
||||
w, h, data, reserved = self.dpy.getppm((0, 0, self.width, self.height))
|
||||
f = open(filename or ('frame%d.ppm' % self.n), 'wb')
|
||||
print >> f, 'P6'
|
||||
print >> f, w, h
|
||||
print >> f, 255
|
||||
for i in range(0, len(data), 4):
|
||||
f.write(data[i+2]+data[i+1]+data[i])
|
||||
f.close()
|
||||
|
||||
def update_sprites(self, udpdata):
|
||||
sprites = self.sprites
|
||||
unpack = struct.unpack
|
||||
base = 0
|
||||
for j in range(len(sprites)):
|
||||
if sprites[j][0] != udpdata[base:base+6]:
|
||||
removes = sprites[j:]
|
||||
del sprites[j:]
|
||||
removes.reverse()
|
||||
eraser = self.dpy.putppm
|
||||
for reserved, eraseargs in removes:
|
||||
eraser(*eraseargs)
|
||||
break
|
||||
base += 6
|
||||
try:
|
||||
overlayer = self.dpy.overlayppm
|
||||
except AttributeError:
|
||||
getter = self.dpy.getppm
|
||||
setter = self.dpy.putppm
|
||||
#print "%d sprites redrawn" % (len(udpdata)/6-j)
|
||||
for j in range(base, len(udpdata)-5, 6):
|
||||
info = udpdata[j:j+6]
|
||||
x, y, icocode = unpack("!hhh", info[:6])
|
||||
try:
|
||||
ico = self.icons[icocode]
|
||||
sprites.append((info, (x, y, getter((x, y) + ico.size))))
|
||||
setter(x, y, ico.bitmap, ico.rect)
|
||||
except KeyError:
|
||||
#print "bad ico code", icocode
|
||||
pass # ignore sprites with bad ico (probably not defined yet)
|
||||
else:
|
||||
for j in range(base, len(udpdata)-5, 6):
|
||||
info = udpdata[j:j+6]
|
||||
x, y, icocode = unpack("!hhh", info[:6])
|
||||
try:
|
||||
ico = self.icons[icocode]
|
||||
overlay = overlayer(x, y, ico.bitmap, ico.rect, ico.alpha)
|
||||
sprites.append((info, overlay))
|
||||
except KeyError:
|
||||
#print "bad ico code", icocode
|
||||
pass # ignore sprites with bad ico (probably not defined yet)
|
||||
|
||||
def msg_unknown(self, *rest):
|
||||
pass
|
||||
|
||||
def msg_patch_file(self, fileid, position, data, lendata=None, *rest):
|
||||
try:
|
||||
s = self.deffiles[fileid]
|
||||
except KeyError:
|
||||
s = ''
|
||||
if len(s) < position:
|
||||
s += '\x00' * (position-len(s))
|
||||
s = s[:position] + data + s[position+len(s):]
|
||||
self.deffiles[fileid] = s
|
||||
|
||||
def msg_zpatch_file(self, fileid, position, data, *rest):
|
||||
data1 = zlib.decompress(data)
|
||||
self.msg_patch_file(fileid, position, data1, len(data), *rest)
|
||||
|
||||
def msg_md5_file(self, fileid, filename, position, length, checksum, *rest):
|
||||
fn = os.path.join(SOURCEDIR, filename)
|
||||
f = open(fn, 'rb')
|
||||
f.seek(position)
|
||||
data = f.read(length)
|
||||
f.close()
|
||||
assert len(data) == length
|
||||
self.msg_patch_file(fileid, position, data)
|
||||
|
||||
def msg_def_playfield(self, width, height, *rest):
|
||||
self.width, self.height = width, height
|
||||
|
||||
def msg_def_icon(self, bmpcode, icocode, x, y, w, h, alpha=255, *rest):
|
||||
self.deficons[icocode] = bmpcode, (x, y, w, h), alpha
|
||||
|
||||
def msg_def_bitmap(self, bmpcode, data, colorkey=None, *rest):
|
||||
self.defbitmaps[bmpcode] = data, colorkey
|
||||
|
||||
def msg_recorded(self, data):
|
||||
self.frames.append(data)
|
||||
|
||||
MESSAGES = {
|
||||
MSG_PATCH_FILE : msg_patch_file,
|
||||
MSG_ZPATCH_FILE : msg_zpatch_file,
|
||||
MSG_MD5_FILE : msg_md5_file,
|
||||
MSG_DEF_PLAYFIELD: msg_def_playfield,
|
||||
MSG_DEF_ICON : msg_def_icon,
|
||||
MSG_DEF_BITMAP : msg_def_bitmap,
|
||||
MSG_RECORDED : msg_recorded,
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__' and len(sys.argv) > 1:
|
||||
p = Playback(sys.argv[1])
|
@ -64,7 +64,7 @@ class PureMixer:
|
||||
byteorder = self.byteorder
|
||||
# done
|
||||
if (freq, bytes, signed, channels, byteorder) != self.parameters:
|
||||
raise ValueError, 'sound sample conversion failed'
|
||||
raise ValueError('sound sample conversion failed')
|
||||
return data
|
||||
|
||||
def wavesample(self, file):
|
||||
@ -87,7 +87,7 @@ class PureMixer:
|
||||
channels = mixer_channels[:]
|
||||
channels.reverse()
|
||||
for c in channels:
|
||||
if already_seen.has_key(c):
|
||||
if c in already_seen:
|
||||
data1 = ''
|
||||
else:
|
||||
data1 = c.read(bufsize)
|
||||
@ -114,10 +114,10 @@ def byteswap(data, byte):
|
||||
elif byte == 4:
|
||||
typecode = 'i'
|
||||
else:
|
||||
raise ValueError, 'cannot convert endianness for samples of %d bytes' % byte
|
||||
raise ValueError('cannot convert endianness for samples of %d bytes' % byte)
|
||||
import array
|
||||
a = array.array(typecode, data)
|
||||
if a.itemsize != byte:
|
||||
raise ValueError, 'endianness convertion failed'
|
||||
raise ValueError('endianness convertion failed')
|
||||
a.byteswap()
|
||||
return a.tostring()
|
||||
|
123
display/puremixer.py.bak
Normal file
123
display/puremixer.py.bak
Normal file
@ -0,0 +1,123 @@
|
||||
import sys, audioop
|
||||
|
||||
|
||||
class PureMixer:
|
||||
#
|
||||
# An audio mixer in Python based on audioop
|
||||
#
|
||||
# Note that opening the audio device itself is outside the scope of
|
||||
# this module. Anything else could also be done with the mixed data,
|
||||
# e.g. stored on disk, for all this module knows.
|
||||
|
||||
def __init__(self, freq=44100, bits=8, signed=0,
|
||||
channels=1, byteorder=None):
|
||||
"""Open the mixer and set its parameters."""
|
||||
self.freq = freq
|
||||
self.bytes = bits/8
|
||||
self.signed = signed
|
||||
self.channels = channels
|
||||
self.byteorder = byteorder or sys.byteorder
|
||||
self.parameters = (freq, self.bytes, signed, channels, self.byteorder)
|
||||
self.bytespersample = channels*self.bytes
|
||||
self.queue = '\x00' * self.bytes
|
||||
|
||||
def resample(self, data, freq=44100, bits=8, signed=0,
|
||||
channels=1, byteorder=None):
|
||||
"Convert a sample to the mixer's own format."
|
||||
bytes = bits/8
|
||||
byteorder = byteorder or sys.byteorder
|
||||
if (freq, bytes, signed, channels, byteorder) == self.parameters:
|
||||
return data
|
||||
# convert to native endianness
|
||||
if byteorder != sys.byteorder:
|
||||
data = byteswap(data, bytes)
|
||||
byteorder = sys.byteorder
|
||||
# convert unsigned -> signed for the next operations
|
||||
if not signed:
|
||||
data = audioop.bias(data, bytes, -(1<<(bytes*8-1)))
|
||||
signed = 1
|
||||
# convert stereo -> mono
|
||||
while channels > self.channels:
|
||||
assert channels % 2 == 0
|
||||
data = audioop.tomono(data, bytes, 0.5, 0.5)
|
||||
channels /= 2
|
||||
# resample to self.freq
|
||||
if freq != self.freq:
|
||||
data, ignored = audioop.ratecv(data, bytes, channels,
|
||||
freq, self.freq, None)
|
||||
freq = self.freq
|
||||
# convert between 8bits and 16bits
|
||||
if bytes != self.bytes:
|
||||
data = audioop.lin2lin(data, bytes, self.bytes)
|
||||
bytes = self.bytes
|
||||
# convert mono -> stereo
|
||||
while channels < self.channels:
|
||||
data = audioop.tostereo(data, bytes, 1.0, 1.0)
|
||||
channels *= 2
|
||||
# convert signed -> unsigned
|
||||
if not self.signed:
|
||||
data = audioop.bias(data, bytes, 1<<(bytes*8-1))
|
||||
signed = 0
|
||||
# convert to mixer endianness
|
||||
if byteorder != self.byteorder:
|
||||
data = byteswap(data, bytes)
|
||||
byteorder = self.byteorder
|
||||
# done
|
||||
if (freq, bytes, signed, channels, byteorder) != self.parameters:
|
||||
raise ValueError, 'sound sample conversion failed'
|
||||
return data
|
||||
|
||||
def wavesample(self, file):
|
||||
"Read a sample from a .wav file (or file-like object)."
|
||||
import wave
|
||||
w = wave.open(file, 'r')
|
||||
return self.resample(w.readframes(w.getnframes()),
|
||||
freq = w.getframerate(),
|
||||
bits = w.getsampwidth() * 8,
|
||||
signed = w.getsampwidth() > 1,
|
||||
channels = w.getnchannels(),
|
||||
byteorder = 'little')
|
||||
|
||||
def mix(self, mixer_channels, bufsize):
|
||||
"""Mix the next batch buffer.
|
||||
Each object in the mixer_channels list must be a file-like object
|
||||
with a 'read(size)' method."""
|
||||
data = ''
|
||||
already_seen = {}
|
||||
channels = mixer_channels[:]
|
||||
channels.reverse()
|
||||
for c in channels:
|
||||
if already_seen.has_key(c):
|
||||
data1 = ''
|
||||
else:
|
||||
data1 = c.read(bufsize)
|
||||
already_seen[c] = 1
|
||||
if data1:
|
||||
l = min(len(data), len(data1))
|
||||
data = (audioop.add(data[:l], data1[:l], 1) +
|
||||
(data1[l:] or data[l:]))
|
||||
else:
|
||||
try:
|
||||
mixer_channels.remove(c)
|
||||
except ValueError:
|
||||
pass
|
||||
data += self.queue * ((bufsize - len(data)) / self.bytes)
|
||||
self.queue = data[-self.bytes:]
|
||||
return data
|
||||
|
||||
|
||||
def byteswap(data, byte):
|
||||
if byte == 1:
|
||||
return
|
||||
if byte == 2:
|
||||
typecode = 'h'
|
||||
elif byte == 4:
|
||||
typecode = 'i'
|
||||
else:
|
||||
raise ValueError, 'cannot convert endianness for samples of %d bytes' % byte
|
||||
import array
|
||||
a = array.array(typecode, data)
|
||||
if a.itemsize != byte:
|
||||
raise ValueError, 'endianness convertion failed'
|
||||
a.byteswap()
|
||||
return a.tostring()
|
@ -51,7 +51,7 @@ class Display:
|
||||
0x010101)
|
||||
|
||||
def pixmap(self, w, h, data, colorkey=-1):
|
||||
print >> sys.stderr, '.',
|
||||
print('.', end=' ', file=sys.stderr)
|
||||
extent = w*h
|
||||
depth = self.depth
|
||||
if depth >= 24:
|
||||
@ -72,7 +72,7 @@ class Display:
|
||||
elif depth == 24 or depth == 32:
|
||||
p_size = 8, 8, 8
|
||||
else:
|
||||
raise ValueError, 'unsupported screen depth %d' % depth
|
||||
raise ValueError('unsupported screen depth %d' % depth)
|
||||
|
||||
imgdata = []
|
||||
maskdata = []
|
||||
@ -82,9 +82,9 @@ class Display:
|
||||
while plane >= (1<<(8-p_size[color])):
|
||||
src = 0
|
||||
for y in range(h):
|
||||
imgline = 0L
|
||||
maskline = 0L
|
||||
shifter = 1L
|
||||
imgline = 0
|
||||
maskline = 0
|
||||
shifter = 1
|
||||
for x in range(w):
|
||||
if data[src:src+3] == key:
|
||||
# transparent
|
||||
@ -111,7 +111,8 @@ class Display:
|
||||
image.size = w, h
|
||||
return image
|
||||
|
||||
def getppm(self, (x, y, w, h), bkgnd=None):
|
||||
def getppm(self, xxx_todo_changeme, bkgnd=None):
|
||||
(x, y, w, h) = xxx_todo_changeme
|
||||
if bkgnd is None:
|
||||
bkgnd = self.win.create_pixmap(w, h, self.depth)
|
||||
bkgnd.mask = None
|
||||
@ -191,7 +192,8 @@ class Display:
|
||||
from socket import fromfd, AF_INET, SOCK_STREAM
|
||||
return [fromfd(self.dpy.fileno(), AF_INET, SOCK_STREAM)]
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
def taskbar(self, xxx_todo_changeme1):
|
||||
(x, y, w, h) = xxx_todo_changeme1
|
||||
for j in range(y, y+h, 32):
|
||||
for i in range(x, x+w, 32):
|
||||
self.putppm(i, j, self.taskbkgnd,
|
||||
|
202
display/pythonxlibintf.py.bak
Normal file
202
display/pythonxlibintf.py.bak
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
################################################
|
||||
## pygame-based implementation of xshm ##
|
||||
################################################
|
||||
|
||||
import os, sys
|
||||
from Xlib import X, display
|
||||
|
||||
|
||||
# -*-*- SLOOWWW -*-*-
|
||||
import psyco; psyco.full()
|
||||
|
||||
|
||||
class Display:
|
||||
|
||||
def __init__(self, width, height, title):
|
||||
self.dpy = display.Display()
|
||||
self.default_scr = self.dpy.screen()
|
||||
self.root = self.default_scr.root
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.depth = self.default_scr.root_depth
|
||||
|
||||
self.backpixmap = self.root.create_pixmap(width, height, self.depth)
|
||||
self.win = self.root.create_window(
|
||||
0, 0, width, height, 0, self.depth,
|
||||
override_redirec = 0,
|
||||
background_pixel = self.default_scr.black_pixel,
|
||||
backing_store = X.NotUseful,
|
||||
)
|
||||
self.win.map()
|
||||
|
||||
self.gc = self.win.create_gc()
|
||||
self.gc_and = self.win.create_gc()
|
||||
self.gc_or = self.win.create_gc()
|
||||
|
||||
self.gc.change(foreground = self.default_scr.black_pixel)
|
||||
self.gc_and.change(function = X.GXand)
|
||||
self.gc_or .change(function = X.GXor)
|
||||
|
||||
self.selectinput = 0
|
||||
self.keyev = []
|
||||
self.mouseev = []
|
||||
self.motionev = None
|
||||
self.dpy.flush()
|
||||
|
||||
pixel = "\x00\x00\x80"
|
||||
hole = "\x01\x01\x01"
|
||||
self.taskbkgnd = self.pixmap(32, 32,
|
||||
((pixel+hole)*16 + (hole+pixel)*16) * 16,
|
||||
0x010101)
|
||||
|
||||
def pixmap(self, w, h, data, colorkey=-1):
|
||||
print >> sys.stderr, '.',
|
||||
extent = w*h
|
||||
depth = self.depth
|
||||
if depth >= 24:
|
||||
bitmap_pad = 32
|
||||
else:
|
||||
bitmap_pad = 16
|
||||
scanline = ((w+bitmap_pad-1) & ~(bitmap_pad-1)) / 8;
|
||||
if colorkey >= 0:
|
||||
key = (chr(colorkey >> 16) +
|
||||
chr((colorkey>>8) & 0xFF) +
|
||||
chr(colorkey & 0xFF))
|
||||
else:
|
||||
key = None
|
||||
if depth == 15:
|
||||
p_size = 5, 5, 5
|
||||
elif depth == 16:
|
||||
p_size = 5, 6, 5
|
||||
elif depth == 24 or depth == 32:
|
||||
p_size = 8, 8, 8
|
||||
else:
|
||||
raise ValueError, 'unsupported screen depth %d' % depth
|
||||
|
||||
imgdata = []
|
||||
maskdata = []
|
||||
|
||||
for color in range(3):
|
||||
plane = 128
|
||||
while plane >= (1<<(8-p_size[color])):
|
||||
src = 0
|
||||
for y in range(h):
|
||||
imgline = 0L
|
||||
maskline = 0L
|
||||
shifter = 1L
|
||||
for x in range(w):
|
||||
if data[src:src+3] == key:
|
||||
# transparent
|
||||
maskline |= shifter
|
||||
elif ord(data[src+color]) & plane:
|
||||
imgline |= shifter
|
||||
shifter <<= 1
|
||||
src += 3
|
||||
imgdata.append(long2string(imgline, scanline))
|
||||
maskdata.append(long2string(maskline, scanline))
|
||||
plane /= 2
|
||||
|
||||
imgdata = ''.join(imgdata)
|
||||
if colorkey >= 0:
|
||||
maskdata = ''.join(maskdata)
|
||||
mask = self.win.create_pixmap(w, h, depth)
|
||||
mask.put_image(self.gc, 0, 0, w, h, X.XYPixmap, depth, 0, maskdata)
|
||||
else:
|
||||
mask = None
|
||||
imgdata = ''.join(imgdata)
|
||||
image = self.win.create_pixmap(w, h, depth)
|
||||
image.put_image(self.gc, 0, 0, w, h, X.XYPixmap, depth, 0, imgdata)
|
||||
image.mask = mask
|
||||
image.size = w, h
|
||||
return image
|
||||
|
||||
def getppm(self, (x, y, w, h), bkgnd=None):
|
||||
if bkgnd is None:
|
||||
bkgnd = self.win.create_pixmap(w, h, self.depth)
|
||||
bkgnd.mask = None
|
||||
bkgnd.size = w, h
|
||||
bkgnd.copy_area(self.gc, self.backpixmap, x, y, w, h, 0, 0)
|
||||
return bkgnd
|
||||
|
||||
def putppm(self, x, y, image, rect=None):
|
||||
if rect:
|
||||
x1, y1, w1, h1 = rect
|
||||
else:
|
||||
x1 = y1 = 0
|
||||
w1, h1 = image.size
|
||||
if image.mask is None:
|
||||
self.backpixmap.copy_area(self.gc, image, x1, y1, w1, h1, x, y)
|
||||
else:
|
||||
self.backpixmap.copy_area(self.gc_and, image.mask,
|
||||
x1, y1, w1, h1, x, y)
|
||||
self.backpixmap.copy_area(self.gc_or, image,
|
||||
x1, y1, w1, h1, x, y)
|
||||
|
||||
def flip(self):
|
||||
self.win.copy_area(self.gc, self.backpixmap,
|
||||
0, 0, self.width, self.height, 0, 0)
|
||||
self.dpy.flush()
|
||||
self.readXevents()
|
||||
|
||||
def close(self):
|
||||
self.dpy.close()
|
||||
|
||||
def clear(self):
|
||||
self.backpixmap.fill_rectangle(self.gc, 0, 0, self.width, self.height)
|
||||
|
||||
def readXevents(self):
|
||||
n = self.dpy.pending_events()
|
||||
if n:
|
||||
for i in range(n):
|
||||
event = self.dpy.next_event()
|
||||
if event.type == X.KeyPress or event.type == X.KeyRelease:
|
||||
self.keyev.append((event.detail, event.type))
|
||||
elif event.type == X.ButtonPress:
|
||||
self.mouseev.append((event.event_x, event.event_y))
|
||||
elif event.type == X.MotionNotify:
|
||||
self.motionev = event.event_x, event.event_y
|
||||
elif event.type == X.DestroyNotify:
|
||||
raise SystemExit
|
||||
self.readXevents()
|
||||
|
||||
def enable_event(self, mask):
|
||||
self.selectinput |= mask
|
||||
self.win.change_attributes(event_mask=self.selectinput)
|
||||
|
||||
def keyevents(self):
|
||||
if not (self.selectinput & X.KeyReleaseMask):
|
||||
self.enable_event(X.KeyPressMask | X.KeyReleaseMask)
|
||||
self.readXevents()
|
||||
result = self.keyev
|
||||
self.keyev = []
|
||||
return result
|
||||
|
||||
def mouseevents(self):
|
||||
if not (self.selectinput & X.ButtonPressMask):
|
||||
self.enable_event(X.ButtonPressMask)
|
||||
result = self.mouseev
|
||||
self.mouseev = []
|
||||
return result
|
||||
|
||||
def pointermotion(self):
|
||||
result = self.motionev
|
||||
self.motionev = None
|
||||
return result
|
||||
|
||||
def has_sound(self):
|
||||
return 0
|
||||
|
||||
def selectlist(self):
|
||||
from socket import fromfd, AF_INET, SOCK_STREAM
|
||||
return [fromfd(self.dpy.fileno(), AF_INET, SOCK_STREAM)]
|
||||
|
||||
def taskbar(self, (x, y, w, h)):
|
||||
for j in range(y, y+h, 32):
|
||||
for i in range(x, x+w, 32):
|
||||
self.putppm(i, j, self.taskbkgnd,
|
||||
(0, 0, x+w-i, y+h-j))
|
||||
|
||||
|
||||
def long2string(bits, strlen):
|
||||
return ''.join([chr((bits>>n)&0xFF) for n in range(0, 8*strlen, 8)])
|
@ -1,7 +1,7 @@
|
||||
import sys
|
||||
from cStringIO import StringIO
|
||||
import puremixer
|
||||
from music1 import Music
|
||||
from io import StringIO
|
||||
from . import puremixer
|
||||
from .music1 import Music
|
||||
|
||||
|
||||
class Sound:
|
||||
@ -30,10 +30,10 @@ class Sound:
|
||||
if name == self.format:
|
||||
break
|
||||
else:
|
||||
print >> sys.stderr, 'available sound formats:'
|
||||
print('available sound formats:', file=sys.stderr)
|
||||
for name, bits, signed, byteorder in self.Formats:
|
||||
print >> sys.stderr, ' %-8s %s' % (name, nicefmttext(
|
||||
bits, signed, byteorder))
|
||||
print(' %-8s %s' % (name, nicefmttext(
|
||||
bits, signed, byteorder)), file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
import linuxaudiodev
|
||||
@ -41,9 +41,9 @@ class Sound:
|
||||
f = linuxaudiodev.open('w')
|
||||
f.setparameters(self.freq, p['bits'], 1,
|
||||
getattr(linuxaudiodev, 'AFMT_' + self.format))
|
||||
except Exception, e:
|
||||
print >> sys.stderr, "sound disabled: %s: %s" % (
|
||||
e.__class__.__name__, e)
|
||||
except Exception as e:
|
||||
print("sound disabled: %s: %s" % (
|
||||
e.__class__.__name__, e), file=sys.stderr)
|
||||
return
|
||||
self.f = f
|
||||
self.mixer = mixer = puremixer.PureMixer(**p)
|
||||
@ -136,7 +136,7 @@ def nicefmttext(bits, signed, byteorder):
|
||||
return s
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
import modes
|
||||
from . import modes
|
||||
l = ['<font size=-1>Sampling <%s>' % nameval('select', 'fmt')]
|
||||
for name, bits, signed, byteorder in Sound.Formats:
|
||||
l.append('<'+nameval('option', 'fmt', name, default='S16_NE')+'>'+
|
||||
|
148
display/snd_linux.py.bak
Normal file
148
display/snd_linux.py.bak
Normal file
@ -0,0 +1,148 @@
|
||||
import sys
|
||||
from cStringIO import StringIO
|
||||
import puremixer
|
||||
from music1 import Music
|
||||
|
||||
|
||||
class Sound:
|
||||
# Mono only
|
||||
has_sound = has_music = 0 # until initialized
|
||||
|
||||
BUFFERTIME = 0.09
|
||||
FLOPTIME = 0.07
|
||||
|
||||
Formats = [
|
||||
('U8', 8, 0, None),
|
||||
('S8', 8, 1, None),
|
||||
('S16_NE', 16, 1, None),
|
||||
('S16_LE', 16, 1, 'little'),
|
||||
('S16_BE', 16, 1, 'big'),
|
||||
('U16_LE', 16, 0, 'little'),
|
||||
('U16_BE', 16, 0, 'big'),
|
||||
]
|
||||
|
||||
def __init__(self, freq=44100, fmt='S16_NE'):
|
||||
self.f = None
|
||||
self.freq = int(freq)
|
||||
self.format = fmt.upper()
|
||||
self.params = p = {}
|
||||
for name, p['bits'], p['signed'], p['byteorder'] in self.Formats:
|
||||
if name == self.format:
|
||||
break
|
||||
else:
|
||||
print >> sys.stderr, 'available sound formats:'
|
||||
for name, bits, signed, byteorder in self.Formats:
|
||||
print >> sys.stderr, ' %-8s %s' % (name, nicefmttext(
|
||||
bits, signed, byteorder))
|
||||
sys.exit(2)
|
||||
|
||||
import linuxaudiodev
|
||||
try:
|
||||
f = linuxaudiodev.open('w')
|
||||
f.setparameters(self.freq, p['bits'], 1,
|
||||
getattr(linuxaudiodev, 'AFMT_' + self.format))
|
||||
except Exception, e:
|
||||
print >> sys.stderr, "sound disabled: %s: %s" % (
|
||||
e.__class__.__name__, e)
|
||||
return
|
||||
self.f = f
|
||||
self.mixer = mixer = puremixer.PureMixer(**p)
|
||||
buffertime = self.BUFFERTIME
|
||||
self.bufsize = int(mixer.bytespersample*mixer.freq*buffertime +
|
||||
255.5) & ~ 255
|
||||
if self.bufsize > f.bufsize():
|
||||
self.bufsize = f.bufsize()
|
||||
buffertime = self.bufsize / float(freq)
|
||||
self.buffertime = buffertime
|
||||
self.mixer_channels = []
|
||||
self.mixer_accum = {}
|
||||
self.has_sound = 1
|
||||
self.has_music = 1
|
||||
|
||||
def close(self):
|
||||
self.f.close()
|
||||
self.f = None
|
||||
|
||||
def sound(self, f):
|
||||
return self.mixer.wavesample(f.fopen())
|
||||
|
||||
def flop(self):
|
||||
self.mixer_accum = {}
|
||||
if self.f is None:
|
||||
return
|
||||
for i in range(3):
|
||||
bufsize = self.bufsize - self.f.obufcount()
|
||||
if bufsize <= 0:
|
||||
break
|
||||
self.f.write(self.mixer.mix(self.mixer_channels, bufsize))
|
||||
#cnt = getattr(self, 'CNT', 0)
|
||||
#import time
|
||||
#print cnt, time.time()
|
||||
#self.CNT = cnt+1
|
||||
return self.FLOPTIME
|
||||
|
||||
def play(self, sound, lvolume, rvolume):
|
||||
# volume ignored
|
||||
if sound not in self.mixer_accum:
|
||||
self.mixer_channels.append(StringIO(sound))
|
||||
self.mixer_accum[sound] = 1
|
||||
|
||||
def play_musics(self, musics, loop_from):
|
||||
self.cmusics = musics, loop_from, -1
|
||||
if self.mixer_channels[:1] != [self]:
|
||||
self.mixer_channels.insert(0, self)
|
||||
|
||||
def read(self, size):
|
||||
"Provide some more data to self.mixer.poll()."
|
||||
musics, loop_from, c = self.cmusics
|
||||
if c < 0:
|
||||
data = ''
|
||||
else:
|
||||
data = musics[c].mixed.decode(self.mixer, size)
|
||||
if not data:
|
||||
c += 1
|
||||
if c >= len(musics): # end
|
||||
c = loop_from
|
||||
if c >= len(musics):
|
||||
return ''
|
||||
self.cmusics = musics, loop_from, c
|
||||
try:
|
||||
mixed = musics[c].mixed
|
||||
except AttributeError:
|
||||
mixed = musics[c].mixed = Music(musics[c].freezefilename())
|
||||
mixed.openchannel()
|
||||
data = mixed.decode(self.mixer, size)
|
||||
if 0 < len(data) < size:
|
||||
data += self.read(size - len(data))
|
||||
return data
|
||||
|
||||
def fadeout(self, millisec):
|
||||
self.cmusics = [], 0, -1
|
||||
|
||||
|
||||
def imperror():
|
||||
try:
|
||||
import linuxaudiodev
|
||||
except ImportError:
|
||||
if sys.platform.startswith('linux'):
|
||||
return 'linuxaudiodev module not installed'
|
||||
else:
|
||||
return 'only available on Linux'
|
||||
|
||||
def nicefmttext(bits, signed, byteorder):
|
||||
s = '%s %d bits' % (signed and 'signed' or 'unsigned', bits)
|
||||
if byteorder:
|
||||
s += ' %s endian' % byteorder
|
||||
return s
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
import modes
|
||||
l = ['<font size=-1>Sampling <%s>' % nameval('select', 'fmt')]
|
||||
for name, bits, signed, byteorder in Sound.Formats:
|
||||
l.append('<'+nameval('option', 'fmt', name, default='S16_NE')+'>'+
|
||||
nicefmttext(bits, signed, byteorder))
|
||||
l+= ['</select> rate ',
|
||||
'<%s size=5>Hz</font>' % nameval('text', 'freq', default='44100'),
|
||||
'<br>',
|
||||
modes.musichtmloptiontext(nameval)]
|
||||
return '\n'.join(l)
|
@ -1,5 +1,5 @@
|
||||
import sys
|
||||
from modes import musichtmloptiontext as htmloptionstext
|
||||
from .modes import musichtmloptiontext as htmloptionstext
|
||||
from pygame.locals import *
|
||||
import pygame.mixer
|
||||
|
||||
@ -16,8 +16,8 @@ class Sound:
|
||||
def __init__(self):
|
||||
try:
|
||||
pygame.mixer.init()
|
||||
except pygame.error, e:
|
||||
print >> sys.stderr, "sound disabled: %s" % str(e)
|
||||
except pygame.error as e:
|
||||
print("sound disabled: %s" % str(e), file=sys.stderr)
|
||||
else:
|
||||
self.has_sound = 1
|
||||
try:
|
||||
|
82
display/snd_pygame.py.bak
Normal file
82
display/snd_pygame.py.bak
Normal file
@ -0,0 +1,82 @@
|
||||
import sys
|
||||
from modes import musichtmloptiontext as htmloptionstext
|
||||
from pygame.locals import *
|
||||
import pygame.mixer
|
||||
|
||||
if pygame.mixer is None:
|
||||
raise ImportError
|
||||
|
||||
|
||||
#ENDMUSICEVENT = USEREVENT
|
||||
|
||||
|
||||
class Sound:
|
||||
has_sound = has_music = 0 # until initialized
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
pygame.mixer.init()
|
||||
except pygame.error, e:
|
||||
print >> sys.stderr, "sound disabled: %s" % str(e)
|
||||
else:
|
||||
self.has_sound = 1
|
||||
try:
|
||||
from pygame.mixer import music
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
self.has_music = music is not None
|
||||
self.cmusics = None
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
pygame.mixer.stop()
|
||||
except pygame.error:
|
||||
pass
|
||||
if self.has_music:
|
||||
try:
|
||||
pygame.mixer.music.stop()
|
||||
except pygame.error:
|
||||
pass
|
||||
|
||||
def sound(self, f):
|
||||
return pygame.mixer.Sound(f.freezefilename())
|
||||
|
||||
def flop(self):
|
||||
# the events are not processed if pygame is not also the display,
|
||||
# so ENDMUSICEVENT will not arrive -- poll for end of music
|
||||
if self.cmusics and not pygame.mixer.music.get_busy():
|
||||
self.next_music()
|
||||
|
||||
def play(self, sound, lvolume, rvolume):
|
||||
channel = pygame.mixer.find_channel(1)
|
||||
channel.stop()
|
||||
try:
|
||||
channel.set_volume(lvolume, rvolume)
|
||||
except TypeError:
|
||||
channel.set_volume(0.5 * (lvolume+rvolume))
|
||||
channel.play(sound)
|
||||
|
||||
def play_musics(self, musics, loop_from):
|
||||
#dpy_pygame.EVENT_HANDLERS[ENDMUSICEVENT] = self.next_music
|
||||
#pygame.mixer.music.set_endevent(ENDMUSICEVENT)
|
||||
self.cmusics = musics, loop_from, 0
|
||||
self.next_music()
|
||||
|
||||
def next_music(self, e=None):
|
||||
if self.cmusics:
|
||||
musics, loop_from, c = self.cmusics
|
||||
if c >= len(musics): # end
|
||||
c = loop_from
|
||||
if c >= len(musics):
|
||||
pygame.mixer.music.stop()
|
||||
self.cmusics = None
|
||||
return
|
||||
pygame.mixer.music.load(musics[c].freezefilename())
|
||||
pygame.mixer.music.play()
|
||||
self.cmusics = musics, loop_from, c+1
|
||||
|
||||
def fadeout(self, millisec):
|
||||
#print "fadeout:", millisec
|
||||
pygame.mixer.music.fadeout(millisec)
|
||||
self.cmusics = None
|
@ -1,8 +1,8 @@
|
||||
import sys
|
||||
from cStringIO import StringIO
|
||||
import puremixer
|
||||
from io import StringIO
|
||||
from . import puremixer
|
||||
import wingame
|
||||
from music1 import Music
|
||||
from .music1 import Music
|
||||
|
||||
|
||||
class Sound:
|
||||
@ -19,9 +19,9 @@ class Sound:
|
||||
|
||||
try:
|
||||
self.audio = wingame.Audio(1, self.freq, self.bits, self.bufsize)
|
||||
except Exception, e:
|
||||
print >> sys.stderr, "sound disabled: %s: %s" % (
|
||||
e.__class__.__name__, e)
|
||||
except Exception as e:
|
||||
print("sound disabled: %s: %s" % (
|
||||
e.__class__.__name__, e), file=sys.stderr)
|
||||
return
|
||||
self.mixer = puremixer.PureMixer(self.freq, self.bits, self.bits==16,
|
||||
byteorder='little')
|
||||
@ -81,7 +81,7 @@ class Sound:
|
||||
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
import modes
|
||||
from . import modes
|
||||
l = ['<font size=-1>Sampling <%s>' % nameval('select', 'bits')]
|
||||
for bits in (8, 16):
|
||||
l.append('<'+nameval('option', 'bits', str(bits), default='16')+'>'+
|
||||
|
93
display/snd_windows.py.bak
Normal file
93
display/snd_windows.py.bak
Normal file
@ -0,0 +1,93 @@
|
||||
import sys
|
||||
from cStringIO import StringIO
|
||||
import puremixer
|
||||
import wingame
|
||||
from music1 import Music
|
||||
|
||||
|
||||
class Sound:
|
||||
# Mono only
|
||||
has_sound = has_music = 0 # until initialized
|
||||
|
||||
BUFFERTIME = 0.09
|
||||
FLOPTIME = 0.07
|
||||
|
||||
def __init__(self, freq=44100, bits=16):
|
||||
self.freq = int(freq)
|
||||
self.bits = int(bits)
|
||||
self.bufsize = (int(self.BUFFERTIME*self.freq*self.bits/8) + 64) & ~63
|
||||
|
||||
try:
|
||||
self.audio = wingame.Audio(1, self.freq, self.bits, self.bufsize)
|
||||
except Exception, e:
|
||||
print >> sys.stderr, "sound disabled: %s: %s" % (
|
||||
e.__class__.__name__, e)
|
||||
return
|
||||
self.mixer = puremixer.PureMixer(self.freq, self.bits, self.bits==16,
|
||||
byteorder='little')
|
||||
self.mixer_channels = []
|
||||
self.mixer_accum = {}
|
||||
self.has_sound = 1
|
||||
self.has_music = 1
|
||||
|
||||
def stop(self):
|
||||
self.audio.close()
|
||||
|
||||
def sound(self, f):
|
||||
return self.mixer.wavesample(f.fopen())
|
||||
|
||||
def flop(self):
|
||||
self.mixer_accum = {}
|
||||
while self.audio.ready():
|
||||
self.audio.write(self.mixer.mix(self.mixer_channels, self.bufsize))
|
||||
return self.FLOPTIME
|
||||
|
||||
def play(self, sound, lvolume, rvolume):
|
||||
# volume ignored
|
||||
if sound not in self.mixer_accum:
|
||||
self.mixer_channels.append(StringIO(sound))
|
||||
self.mixer_accum[sound] = 1
|
||||
|
||||
def play_musics(self, musics, loop_from):
|
||||
self.cmusics = musics, loop_from, -1
|
||||
self.mixer_channels.insert(0, self)
|
||||
|
||||
def read(self, size):
|
||||
"Provide some more data to self.mixer.poll()."
|
||||
musics, loop_from, c = self.cmusics
|
||||
if c < 0:
|
||||
data = ''
|
||||
else:
|
||||
data = musics[c].mixed.decode(self.mixer, size)
|
||||
if not data:
|
||||
c += 1
|
||||
if c >= len(musics): # end
|
||||
c = loop_from
|
||||
if c >= len(musics):
|
||||
return ''
|
||||
self.cmusics = musics, loop_from, c
|
||||
try:
|
||||
mixed = musics[c].mixed
|
||||
except AttributeError:
|
||||
mixed = musics[c].mixed = Music(musics[c].freezefilename())
|
||||
mixed.openchannel()
|
||||
data = mixed.decode(self.mixer, size)
|
||||
if 0 < len(data) < size:
|
||||
data += self.read(size - len(data))
|
||||
return data
|
||||
|
||||
def fadeout(self, millisec):
|
||||
self.cmusics = [], 0, -1
|
||||
|
||||
|
||||
def htmloptionstext(nameval):
|
||||
import modes
|
||||
l = ['<font size=-1>Sampling <%s>' % nameval('select', 'bits')]
|
||||
for bits in (8, 16):
|
||||
l.append('<'+nameval('option', 'bits', str(bits), default='16')+'>'+
|
||||
'%d bits' % bits)
|
||||
l+= ['</select> rate ',
|
||||
'<%s size=5>Hz</font>' % nameval('text', 'freq', default='44100'),
|
||||
'<br>',
|
||||
modes.musichtmloptiontext(nameval)]
|
||||
return '\n'.join(l)
|
@ -1,5 +1,5 @@
|
||||
import os, sys, random
|
||||
from cStringIO import StringIO
|
||||
from io import StringIO
|
||||
import socket, time
|
||||
|
||||
PLAYERNAMES = ['Bub', 'Bob', 'Boob', 'Beb',
|
||||
@ -34,7 +34,7 @@ class Options:
|
||||
if not attr.startswith('_'):
|
||||
return None
|
||||
else:
|
||||
raise AttributeError, attr
|
||||
raise AttributeError(attr)
|
||||
|
||||
|
||||
class PageServer:
|
||||
@ -81,8 +81,8 @@ class PageServer:
|
||||
self.httpport = port = gamesrv.displaysockport(hs)
|
||||
self.indexurl = 'http://127.0.0.1:%d/%s/' % (port, self.seed)
|
||||
if self.Game:
|
||||
print self.Game.FnDesc,
|
||||
print 'server is ready at', self.indexurl
|
||||
print(self.Game.FnDesc, end=' ')
|
||||
print('server is ready at', self.indexurl)
|
||||
return 1
|
||||
|
||||
def getlocalservers(self):
|
||||
@ -91,8 +91,8 @@ class PageServer:
|
||||
return self.localservers
|
||||
|
||||
def searchlocalservers(self):
|
||||
servers = hostchooser.find_servers().items()
|
||||
servers = filter(self.filterserver, servers)
|
||||
servers = list(hostchooser.find_servers().items())
|
||||
servers = list(filter(self.filterserver, servers))
|
||||
servers.sort()
|
||||
self.localservers = servers
|
||||
|
||||
@ -136,7 +136,8 @@ class PageServer:
|
||||
## self.inetservers[host, port] = info
|
||||
## #print 'hostchooser:', self.inetserverlist, '->', self.inetservers
|
||||
|
||||
def filterserver(self, ((host, port), info)):
|
||||
def filterserver(self, xxx_todo_changeme):
|
||||
((host, port), info) = xxx_todo_changeme
|
||||
for c in host+str(port):
|
||||
if c not in "-.0123456789:@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz":
|
||||
return 0
|
||||
@ -166,15 +167,15 @@ class PageServer:
|
||||
data[self.localhost] = self.localoptions.dict()
|
||||
try:
|
||||
f = open(self.filename, 'w')
|
||||
print >> f, `data`
|
||||
print(repr(data), file=f)
|
||||
f.close()
|
||||
except IOError, e:
|
||||
print >> sys.stderr, "! Cannot save config file: " + str(e)
|
||||
except IOError as e:
|
||||
print("! Cannot save config file: " + str(e), file=sys.stderr)
|
||||
|
||||
def reloadports(self):
|
||||
import msgstruct
|
||||
msgstruct.PORTS.clear()
|
||||
for key, value in self.localoptions.dict().items():
|
||||
for key, value in list(self.localoptions.dict().items()):
|
||||
if key.startswith('port_'):
|
||||
key = key[5:]
|
||||
if key == 'CLIENT' and type(value) == str and ':' in value:
|
||||
@ -230,7 +231,7 @@ class PageServer:
|
||||
|
||||
def indexloader(self, headers, cheat=[], **options):
|
||||
if cheat:
|
||||
import __builtin__
|
||||
import builtins
|
||||
for c in cheat:
|
||||
getattr(__builtin__, '__cheat')(c)
|
||||
else:
|
||||
@ -241,7 +242,7 @@ class PageServer:
|
||||
host = headers['remote host']
|
||||
host = socket.gethostbyname(host)
|
||||
if host != '127.0.0.1':
|
||||
raise HTTPRequestError, "Access denied"
|
||||
raise HTTPRequestError("Access denied")
|
||||
return None, self.indexurl
|
||||
|
||||
## def listloader(self, headers, s=[], **options):
|
||||
@ -257,7 +258,7 @@ class PageServer:
|
||||
|
||||
def newloader(self, headers, **options):
|
||||
if not self.Game:
|
||||
raise HTTPRequestError, "Complete bub-n-bros installation needed"
|
||||
raise HTTPRequestError("Complete bub-n-bros installation needed")
|
||||
locals = {
|
||||
'Game': self.Game,
|
||||
'options': self.globaloptions,
|
||||
@ -269,7 +270,7 @@ class PageServer:
|
||||
def runloader(self, headers, **options):
|
||||
self.globaloptions.metapublish = 'n'
|
||||
self.globaloptions.autoreset = 'n'
|
||||
for key, value in options.items():
|
||||
for key, value in list(options.items()):
|
||||
if len(value) == 1:
|
||||
setattr(self.globaloptions, key, value[0])
|
||||
self.saveoptions()
|
||||
@ -327,9 +328,9 @@ class PageServer:
|
||||
httpport = int(httpport[0])
|
||||
except (ValueError, IndexError):
|
||||
if port:
|
||||
raise HTTPRequestError, "This server is not running HTTP."
|
||||
raise HTTPRequestError("This server is not running HTTP.")
|
||||
else:
|
||||
raise HTTPRequestError, "Sorry, I cannot connect the Java applet to a server using this field."
|
||||
raise HTTPRequestError("Sorry, I cannot connect the Java applet to a server using this field.")
|
||||
return None, 'http://%s:%s/' % (host, httpport)
|
||||
|
||||
# now is a good time to generate the color files if we can
|
||||
@ -337,7 +338,7 @@ class PageServer:
|
||||
'buildcolors.py')
|
||||
if os.path.exists(file):
|
||||
g = {'__name__': '__auto__', '__file__': file}
|
||||
execfile(file, g)
|
||||
exec(compile(open(file, "rb").read(), file, 'exec'), g)
|
||||
|
||||
if port:
|
||||
address = '%s:%s' % (host, port)
|
||||
@ -370,7 +371,7 @@ class PageServer:
|
||||
self.localoptions.port_CLIENT = None
|
||||
self.localoptions.port_LISTEN = None
|
||||
self.localoptions.port_HTTP = None
|
||||
for key, value in options.items():
|
||||
for key, value in list(options.items()):
|
||||
setattr(self.localoptions, key, value[0])
|
||||
self.saveoptions()
|
||||
locals = {
|
||||
@ -451,8 +452,8 @@ class PageServer:
|
||||
except KeyError:
|
||||
try:
|
||||
mode = display.modes.findmode(None, lst)
|
||||
except KeyError, e:
|
||||
print >> sys.stderr, str(e) # no mode!
|
||||
except KeyError as e:
|
||||
print(str(e), file=sys.stderr) # no mode!
|
||||
mode = None
|
||||
currentmodes.append(mode)
|
||||
return currentmodes
|
||||
@ -462,10 +463,10 @@ class PageServer:
|
||||
if dpy.getmodule() is None:
|
||||
return None # redirect to the Java applet
|
||||
if dpy is None or snd is None:
|
||||
raise HTTPRequestError, "No installed graphics or sounds drivers. See the settings page."
|
||||
raise HTTPRequestError("No installed graphics or sounds drivers. See the settings page.")
|
||||
options = self.localoptions
|
||||
result = ['--cfg='+no_quote_worries(self.filename)]
|
||||
for key, value in options.dict().items():
|
||||
for key, value in list(options.dict().items()):
|
||||
if key.startswith('port_') and value:
|
||||
result.append('--port')
|
||||
result.append('%s=%s' % (key[5:], value))
|
||||
@ -476,7 +477,7 @@ class PageServer:
|
||||
('--sound', snd)]:
|
||||
result.append(optname + '=' + mode.name)
|
||||
uid = mode.unique_id() + '_'
|
||||
for key, value in options.dict().items():
|
||||
for key, value in list(options.dict().items()):
|
||||
if key.startswith(uid):
|
||||
result.append('--%s=%s' % (key[len(uid):], value))
|
||||
return result
|
||||
@ -574,7 +575,7 @@ def main(Game, save_url_to=None, quiet=0):
|
||||
srv = PageServer(Game)
|
||||
srv.registerpages()
|
||||
if not srv.opensocket():
|
||||
print >> sys.stderr, "server aborted."
|
||||
print("server aborted.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if quiet:
|
||||
if Game:
|
||||
@ -582,7 +583,7 @@ def main(Game, save_url_to=None, quiet=0):
|
||||
import stdlog
|
||||
f = stdlog.LogFile()
|
||||
if f:
|
||||
print "Logging to", f.filename
|
||||
print("Logging to", f.filename)
|
||||
sys.stdout = sys.stderr = f
|
||||
if save_url_to:
|
||||
data = srv.indexurl + '\n'
|
||||
@ -595,7 +596,7 @@ def main(Game, save_url_to=None, quiet=0):
|
||||
atexit.register(try_to_unlink, save_url_to)
|
||||
try:
|
||||
fno = os.open(save_url_to, os.O_CREAT | os.O_TRUNC | os.O_WRONLY,
|
||||
0600)
|
||||
0o600)
|
||||
if os.write(fno, data) != len(data):
|
||||
raise OSError
|
||||
os.close(fno)
|
||||
@ -619,17 +620,17 @@ def schedule_launch(args):
|
||||
|
||||
def launch(args):
|
||||
# platform-specific hacks
|
||||
print 'Running client -> ', ' '.join(args)
|
||||
print('Running client -> ', ' '.join(args))
|
||||
if 0: # OLD CODE sys.platform == 'darwin': # must start as a UI process
|
||||
import tempfile
|
||||
cmdname = tempfile.mktemp('_BubBob.py')
|
||||
f = open(cmdname, 'w')
|
||||
print >> f, 'import sys, os'
|
||||
print >> f, 'try: os.unlink(%r)' % cmdname
|
||||
print >> f, 'except OSError: pass'
|
||||
print >> f, 'sys.argv[:] = %r' % (args,)
|
||||
print >> f, '__file__ = %r' % cmdname
|
||||
print >> f, 'execfile(%r)' % args[0]
|
||||
print('import sys, os', file=f)
|
||||
print('try: os.unlink(%r)' % cmdname, file=f)
|
||||
print('except OSError: pass', file=f)
|
||||
print('sys.argv[:] = %r' % (args,), file=f)
|
||||
print('__file__ = %r' % cmdname, file=f)
|
||||
print('execfile(%r)' % args[0], file=f)
|
||||
f.close()
|
||||
os.system('/usr/bin/open -a PythonLauncher "%s"' % cmdname)
|
||||
else:
|
||||
@ -692,14 +693,14 @@ else:
|
||||
assert s[len(absroot)] == os.sep
|
||||
relpath = s[len(absroot)+1:]
|
||||
result = os.path.join(ROOTDIR, relpath)
|
||||
print "no_quote_worries %r => %r" % (s, result)
|
||||
print("no_quote_worries %r => %r" % (s, result))
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if (len(sys.argv) != 3 or sys.argv[1] != '--quiet' or
|
||||
not sys.argv[2].startswith('--saveurlto=')):
|
||||
print >> sys.stderr, "This script should only be launched by BubBob.py."
|
||||
print("This script should only be launched by BubBob.py.", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
main(None, sys.argv[2][len('--saveurlto='):], quiet=1)
|
||||
gamesrv.mainloop()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user