summaryrefslogtreecommitdiff
path: root/bubbob/bb.py
diff options
context:
space:
mode:
Diffstat (limited to 'bubbob/bb.py')
-rwxr-xr-xbubbob/bb.py345
1 files changed, 345 insertions, 0 deletions
diff --git a/bubbob/bb.py b/bubbob/bb.py
new file mode 100755
index 0000000..c0ab351
--- /dev/null
+++ b/bubbob/bb.py
@@ -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()