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