1
0
mirror of https://github.com/abakh/nbsdgames.git synced 2025-02-02 15:07:27 -05:00
nbsdgames/bubbob/ranking.py
2022-02-03 13:46:22 +03:30

392 lines
12 KiB
Python

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