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 = next(bgen) 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 list(results.values()): maximum += n maximum = maximum or 1 ranking = [] teamrank = [0, 0] teamplayers = [[], []] for p, n in list(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, list(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 list(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 list(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 list(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