mirror of
https://github.com/abakh/nbsdgames.git
synced 2025-02-02 15:07:27 -05:00
392 lines
12 KiB
Python
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
|