summaryrefslogtreecommitdiff
path: root/bubbob/ranking.py
diff options
context:
space:
mode:
Diffstat (limited to 'bubbob/ranking.py')
-rw-r--r--bubbob/ranking.py391
1 files changed, 391 insertions, 0 deletions
diff --git a/bubbob/ranking.py b/bubbob/ranking.py
new file mode 100644
index 0000000..d4a4d22
--- /dev/null
+++ b/bubbob/ranking.py
@@ -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