mirror of
https://github.com/abakh/nbsdgames
synced 2025-04-28 14:09:32 -04:00
1214 lines
45 KiB
Python
1214 lines
45 KiB
Python
from __future__ import generators
|
|
import random, math, time
|
|
import gamesrv
|
|
import images
|
|
import boards
|
|
import bubbles
|
|
from boards import *
|
|
from images import ActiveSprite
|
|
from mnstrmap import GreenAndBlue, LetterBubbles, PlayerBubbles
|
|
from mnstrmap import DigitsMisc
|
|
|
|
KEEPALIVE = 5*60 # seconds
|
|
CheatDontDie = 0
|
|
|
|
|
|
class Dragon(ActiveSprite):
|
|
priority = 1
|
|
mdef = PlayerBubbles
|
|
fly_counter = 0
|
|
## glueddown = None
|
|
|
|
DCAP = {
|
|
'hspeed': 1,
|
|
'firerate': 2,
|
|
'shootthrust': 8.0,
|
|
'infinite_shield': 1,
|
|
'shield': 50,
|
|
'gravity': 0.21,
|
|
'bubbledelay': 0,
|
|
'shootbubbles': (),
|
|
'pinball': 0,
|
|
## 'nojump': 0,
|
|
'autofire': 0,
|
|
'ring': 0,
|
|
'hotstuff': 0,
|
|
'left2right': 1,
|
|
'slippy': 0,
|
|
'vslippy': 0.0,
|
|
'lookforward': 1,
|
|
'fly': 0,
|
|
'jumpdown': 0,
|
|
'flower': 1,
|
|
'bigflower': None,
|
|
'overlayglasses': 0,
|
|
'teleport': 0,
|
|
'breakwalls': 0,
|
|
'carrying': (),
|
|
'key_left': 'key_left',
|
|
'key_right': 'key_right',
|
|
'key_jump': 'key_jump',
|
|
'key_fire': 'key_fire',
|
|
}
|
|
SAVE_CAP = {'hspeed': 1,
|
|
'firerate': 2,
|
|
'shootthrust': 8.0 / 1.5,
|
|
'flower': -1}
|
|
|
|
def __init__(self, bubber, x, y, dir, dcap=DCAP):
|
|
self.bubber = bubber
|
|
self.dir = dir
|
|
icobubber = dcap.get('bubbericons', bubber)
|
|
ActiveSprite.__init__(self, icobubber.icons[0, dir], x, y)
|
|
self.fire = 0
|
|
self.up = 0.0
|
|
self.watermoveable = 0
|
|
self.dcap = dcap.copy()
|
|
self.dcap.update(self.bubber.pcap)
|
|
BubPlayer.DragonList.append(self)
|
|
self.gen.append(self.normal_movements())
|
|
self.overlaysprite = None
|
|
self.overlayyoffset = 4
|
|
self.hatsprite = None
|
|
self.hatangle = 1
|
|
self.isdying = 0
|
|
self.lifegained = 0
|
|
self.playing_fish = False
|
|
if BubPlayer.SuperSheep:
|
|
self.become_monster('Sheep', immed=1)
|
|
elif BubPlayer.SuperFish:
|
|
self.become_fish()
|
|
|
|
def kill(self):
|
|
try:
|
|
BubPlayer.DragonList.remove(self)
|
|
except ValueError:
|
|
pass
|
|
try:
|
|
self.bubber.dragons.remove(self)
|
|
except ValueError:
|
|
pass
|
|
ActiveSprite.kill(self)
|
|
if self.hatsprite is not None:
|
|
if self.hatsprite.alive:
|
|
self.hatsprite.kill()
|
|
self.hatsprite = None
|
|
|
|
def die(self):
|
|
if (self in BubPlayer.DragonList and not self.dcap['shield']
|
|
and not CheatDontDie):
|
|
BubPlayer.DragonList.remove(self)
|
|
self.gen = [self.dying()]
|
|
self.play(images.Snd.Die)
|
|
#wasting = boards.curboard.wastingplay
|
|
#if wasting is not None:
|
|
# wasting[self.bubber] = len(wasting)
|
|
|
|
def dying(self, can_loose_letter=1):
|
|
self.isdying = 1
|
|
if self.hatsprite is not None:
|
|
if self.hatsprite.alive:
|
|
dxy = [3*self.dir, -7]
|
|
self.hatsprite.gen = [self.hatsprite.parabolic(dxy)]
|
|
self.hatsprite = None
|
|
lst = [bonus for timeout, bonus in self.dcap['carrying']
|
|
if hasattr(bonus, 'buildoutcome')]
|
|
#if random.random() > 0.2]
|
|
if lst:
|
|
# loose some bonuses
|
|
from bonuses import BonusMaker
|
|
for bonus in lst:
|
|
self.bubber.givepoints(-bonus.points)
|
|
BonusMaker(self.x, self.y, [bonus.nimage],
|
|
outcome=bonus.buildoutcome())
|
|
elif self.bubber.letters and random.random() > 0.59 and can_loose_letter:
|
|
# loose a letter
|
|
lst = range(6)
|
|
random.shuffle(lst)
|
|
for l in lst:
|
|
lettername = bubbles.extend_name(l)
|
|
if lettername in self.bubber.letters:
|
|
s = self.bubber.letters[lettername]
|
|
del self.bubber.letters[lettername]
|
|
if isinstance(s, ActiveSprite):
|
|
s.kill()
|
|
scoreboard()
|
|
s = bubbles.LetterBubble(self.bubber.pn, l)
|
|
s.move(self.x, self.y)
|
|
break
|
|
icons = self.getcurrenticons()
|
|
for i in range(2, 32):
|
|
mode = 5 + ((i>>1) & 3)
|
|
self.seticon(icons[mode, self.dir])
|
|
yield None
|
|
self.kill()
|
|
if not self.bubber.dragons:
|
|
self.bubber.bubberdie()
|
|
# self.bubber.badpoints = self.bubber.points // 3
|
|
|
|
def killing(self):
|
|
self.kill()
|
|
if 0:
|
|
yield None
|
|
|
|
def carrybonus(self, bonus, timeout=500):
|
|
timeout += BubPlayer.FrameCounter
|
|
lst = list(self.dcap['carrying'])
|
|
lst.append((timeout, bonus))
|
|
lst.sort()
|
|
self.dcap['carrying'] = lst
|
|
|
|
def listcarrybonuses(self):
|
|
return [bonus for timeout, bonus in self.dcap['carrying']]
|
|
|
|
## def moebius(self):
|
|
## self.dir = -self.dir
|
|
## self.dcap['left2right'] *= -1
|
|
|
|
def monstervisible(self):
|
|
return not self.dcap['ring'] and not self.dcap['shield']
|
|
|
|
def getcurrenticons(self, imgtransform=''):
|
|
if self.playing_fish:
|
|
imgtransform = 'fish'
|
|
icobubber = self.dcap.get('bubbericons', self.bubber)
|
|
try:
|
|
return icobubber.transformedicons[imgtransform]
|
|
except KeyError:
|
|
icons = icobubber.transformedicons[imgtransform] = {}
|
|
icobubber.loadicons(imgtransform)
|
|
return icons
|
|
|
|
def normal_movements(self):
|
|
yfp = 0.0
|
|
hfp = 0
|
|
angryticks = 0
|
|
mytime = 0
|
|
privatetime = 0
|
|
while 1:
|
|
dcap = self.dcap
|
|
self.poplist = [self]
|
|
carrying = dcap['carrying']
|
|
while carrying and carrying[0][0] < BubPlayer.FrameCounter:
|
|
timeout, bonus = carrying.pop(0)
|
|
if bonus.endaction:
|
|
bonus.endaction(self)
|
|
del bonus
|
|
|
|
bubber = self.bubber
|
|
wannafire = bubber.getkey(dcap, 'key_fire')
|
|
wannajump = bubber.getkey(dcap, 'key_jump')
|
|
wannago = bubber.wannago(dcap)
|
|
bottom_up = self.bottom_up()
|
|
onground1 = (onground,underground)[bottom_up]
|
|
|
|
if dcap['autofire']:
|
|
wannafire = 1
|
|
if dcap['pinball']:
|
|
wannajump = 1
|
|
if dcap['pinball'] > 1:
|
|
if self.up:
|
|
self.up *= 0.982 ** dcap['pinball']
|
|
if dcap['hotstuff']:
|
|
if not wannago:
|
|
if self.dir * (random.random()-0.07) < 0:
|
|
wannago = -1
|
|
else:
|
|
wannago = 1
|
|
wannafire = 1
|
|
if self.fire > (11 // dcap['hotstuff']):
|
|
self.fire = 0
|
|
## if dcap['hotstuff'] > 1 and random.random() < 0.4:
|
|
## from bubbles import FireDrop
|
|
## FireDrop(self.x + HALFCELL, self.y + HALFCELL)
|
|
if wannago:
|
|
self.dir = wannago * dcap['lookforward']
|
|
if self.x & 1:
|
|
self.step(self.dir, 0)
|
|
if dcap['slippy']:
|
|
vx = dcap['vslippy']
|
|
if wannago:
|
|
vx += wannago * 0.05
|
|
else:
|
|
vx *= 0.95
|
|
if vx < 0.0:
|
|
wannago = -1
|
|
else:
|
|
wannago = 1
|
|
dcap['vslippy'] = vx
|
|
mytime = (mytime+dcap['lookforward']) % 12
|
|
hfp += abs(vx)
|
|
else:
|
|
hfp += dcap['hspeed']
|
|
|
|
## if self.glueddown:
|
|
## if wannajump or not dcap['nojump']:
|
|
## del self.glueddown
|
|
## else:
|
|
## # glued gliding movements
|
|
## self.step(self.x & 1, self.y & 1)
|
|
## if wannago:
|
|
## mytime = (mytime+dcap['lookforward']) % 12
|
|
## else:
|
|
## hfp = 0
|
|
## while hfp > 0 and self.glueddown:
|
|
## gx, gy = self.glueddown
|
|
## dx = wannago*gy
|
|
## dy = -wannago*gx
|
|
## x0 = (self.x + gx + dx) // CELL + 1
|
|
## y0 = (self.y + gy + dy) // CELL + 1
|
|
## if ' ' == bget(x0+dx, y0+dy) == bget(x0+dx-gx, y0+dy-gy):
|
|
## self.step(2*dx, 2*dy)
|
|
## # detached from this wall?
|
|
## x1 = (self.x + gx + dx) // CELL + 1
|
|
## y1 = (self.y + gy + dy) // CELL + 1
|
|
## if (' ' == bget(x1-dx+gx, y1-dy+gy)
|
|
## == bget(x0 +gx, y0 +gy)
|
|
## == bget(x0+dx+gx, y0+dy+gy)):
|
|
## if bget(x0-dx+gx, y0-dy+gy) != ' ':
|
|
## # rotate around the corner
|
|
## self.glueddown = -dx, -dy
|
|
## self.step(2*gx, 2*gy)
|
|
## else:
|
|
## del self.glueddown
|
|
## elif bget(x0-gx, y0-gy) == ' ':
|
|
## # attach to the wall into which we are running
|
|
## if (self.x*dx | self.y*dy) % CELL != 0:
|
|
## if ((((self.x-2*dx)*dx | (self.y-2*dy)*dy) &
|
|
## ((self.x-4*dx)*dx | (self.y-4*dy)*dy))
|
|
## % CELL == 0):
|
|
## self.step(-2*dx, -2*dy)
|
|
## else:
|
|
## del self.glueddown
|
|
## else:
|
|
## self.glueddown = dx, dy
|
|
## else:
|
|
## del self.glueddown
|
|
## self.vertical_warp()
|
|
## hfp -= 0.82 # slightly faster than usual
|
|
# normal left or right movements
|
|
breakwalls = dcap['breakwalls']
|
|
while hfp > 0:
|
|
hfp -= 1
|
|
dir = 0
|
|
if wannago == -1:
|
|
x0 = (self.x+1)//CELL
|
|
y0 = (self.y+4 - bottom_up*(CELL+4)) // CELL + 1
|
|
y0bis = (self.y+CELL-1) // CELL + 1 - bottom_up
|
|
if bget(x0,y0) == ' ' == bget(x0,y0bis):
|
|
dir = -1
|
|
elif breakwalls:
|
|
self.breakwalls(x0, y0bis, -1)
|
|
elif wannago == 1:
|
|
x0 = (self.x-3)//CELL + 2
|
|
y0 = self.y // CELL + 1 - bottom_up
|
|
y0bis = (self.y+CELL-1) // CELL + 1 - bottom_up
|
|
if bget(x0,y0) == ' ' == bget(x0,y0bis):
|
|
dir = +1
|
|
elif breakwalls:
|
|
self.breakwalls(x0, y0bis, 1)
|
|
self.step(2*dir, 0)
|
|
if dir:
|
|
mytime = (mytime+dcap['lookforward']) % 12
|
|
else:
|
|
f = - dcap['vslippy'] * (dcap['slippy']+1)/3.0
|
|
dcap['vslippy'] = max(min(f, 10.0), -10.0)
|
|
hfp = 0
|
|
onbubble = None
|
|
if not dcap['infinite_shield']:
|
|
touching = images.touching(self.x+1, self.y+1, 30, 30)
|
|
touching.reverse()
|
|
for s in touching:
|
|
if s.touched(self):
|
|
onbubble = s
|
|
elif bubber.key_left or bubber.key_right or bubber.key_jump or bubber.key_fire:
|
|
dcap['infinite_shield'] = 0
|
|
|
|
dir = self.dir
|
|
icons = self.getcurrenticons('vflip' * bottom_up)
|
|
|
|
if self.playing_fish:
|
|
mode = self.one_fish_frame(onground1, bottom_up)
|
|
elif self.up:
|
|
# going up
|
|
mode = 9
|
|
self.up -= dcap['gravity']
|
|
if (self.up,-self.up)[bottom_up] < 4.0:
|
|
self.up = 0.0
|
|
mode = 10
|
|
else:
|
|
ny = self.y + yfp - self.up
|
|
self.move(self.x, int(ny))
|
|
yfp = ny - self.y
|
|
self.vertical_warp()
|
|
if wannago and dcap['teleport']:
|
|
for t in self.teleport(wannago, icons, 0):
|
|
yield t
|
|
else:
|
|
# going down or staying on ground
|
|
if wannajump and onbubble:
|
|
ground = True
|
|
onbubble.dragon_jumped = True, bottom_up
|
|
else:
|
|
ground = onground1(self.x, self.y)
|
|
if ground:
|
|
if wannajump:
|
|
self.play(images.Snd.Jump)
|
|
if dcap['jumpdown'] and not onbubble:
|
|
self.step(0, (1, -1)[bottom_up])
|
|
mode = 10
|
|
bubber.emotic(self, 4)
|
|
else:
|
|
yfp = 0.0
|
|
self.up = (7.5,-7.5)[bottom_up]
|
|
mode = 9
|
|
else:
|
|
mode = mytime // 4
|
|
if wannago and dcap['teleport']:
|
|
for t in self.teleport(wannago, icons):
|
|
yield t
|
|
else:
|
|
mode = 10
|
|
if dcap['fly']:
|
|
self.fly_counter += 1
|
|
if self.fly_counter < dcap['fly']:
|
|
ny = self.y
|
|
else:
|
|
del self.fly_counter
|
|
ny = self.y+(1,-1)[bottom_up]
|
|
else:
|
|
ny = (self.y+(4,-1)[bottom_up]) & ~3
|
|
nx = self.x
|
|
if nx < 32:
|
|
nx += 2
|
|
elif nx > boards.bwidth - 64:
|
|
nx -= 2
|
|
self.move(nx, ny)
|
|
self.vertical_warp()
|
|
if wannago and dcap['teleport']:
|
|
for t in self.teleport(wannago, icons, 0):
|
|
yield t
|
|
|
|
if wannafire and not self.fire:
|
|
self.firenow()
|
|
self.hatangle = 1
|
|
if self.fire:
|
|
if self.fire <= 5:
|
|
mode = 3
|
|
self.hatangle = 2
|
|
elif self.fire <= 10:
|
|
mode = 4
|
|
self.hatangle = 3
|
|
self.fire += 1
|
|
if self.fire >= 64 // dcap['firerate']:
|
|
self.fire = 0
|
|
|
|
s = dcap['shield']
|
|
if s:
|
|
if dcap['infinite_shield'] and s < 20:
|
|
s += 4
|
|
s -= 1
|
|
if dcap['overlayglasses']:
|
|
self.overlayyoffset = ({3: 2, 4: 0,
|
|
9: 3, 10: 5}.get(mode, 4)
|
|
+ self.playing_fish * 2)
|
|
elif s & 2:
|
|
mode = 11
|
|
dcap['shield'] = s
|
|
if dcap['ring']:# and random.random() > 0.1:
|
|
if dcap['ring'] > 1:
|
|
mode = 12
|
|
else:
|
|
mode = 11
|
|
self.seticon(icons[mode, dir])
|
|
self.watermoveable = not wannajump
|
|
|
|
privatetime += BubPlayer.PlayersPrivateTime
|
|
while privatetime >= 100:
|
|
yield None
|
|
privatetime -= 100
|
|
|
|
if self.angry:
|
|
if angryticks == 0:
|
|
s = ActiveSprite(icons[11, self.dir], self.x, self.y)
|
|
s.gen.append(s.die([None], speed=10))
|
|
angryticks = 6
|
|
angryticks -= 1
|
|
#if BubPlayer.Moebius and BubPlayer.FrameCounter % 5 == 0:
|
|
# s = ActiveSprite(icons[11, -self.dir],
|
|
# boards.bwidth - 2*CELL - self.x, self.y)
|
|
# s.gen.append(s.die([None], speed=2))
|
|
|
|
def teleport(self, wannago, icons, max_delta_y=CELL):
|
|
#if self.dcap['shield']:
|
|
# return
|
|
from bonuses import Bonus, Megabonus
|
|
best_dx = boards.bwidth
|
|
centerx = self.x + self.ico.w // 2
|
|
basey = (self.y + self.ico.h + 8) & ~15
|
|
for s in images.ActiveSprites:
|
|
if (isinstance(s, Bonus) and s.touchable
|
|
and abs(s.y+s.ico.h - basey) <= max_delta_y
|
|
and s.is_on_ground()):
|
|
dx = (s.x + (wannago < 0 and s.ico.w)) - centerx
|
|
if dx*wannago > 0:
|
|
dx = abs(dx) + CELL
|
|
if dx < best_dx:
|
|
best_dx = dx
|
|
best = s
|
|
if not (42 <= best_dx < boards.bwidth):
|
|
return
|
|
self.play(images.Snd.Shh)
|
|
self.up = 0.0
|
|
s = best
|
|
dx = best_dx
|
|
basey = s.y+s.ico.h
|
|
desty = basey - self.ico.h
|
|
dy_dx = float(desty - self.y) / dx
|
|
self.dir = wannago
|
|
ico = images.make_darker(icons[0, wannago], True)
|
|
# speed up
|
|
fx = self.x
|
|
fy = self.y
|
|
curdx = 0.0
|
|
stepx = 2.0
|
|
t = 0
|
|
while 1:
|
|
if curdx < 0.5*dx:
|
|
stepx *= 1.13
|
|
else:
|
|
stepx /= 1.13
|
|
fx += wannago * stepx
|
|
fy += dy_dx * stepx
|
|
curdx += stepx
|
|
if curdx >= dx or stepx < 2.0:
|
|
fx += wannago * (dx - curdx)
|
|
break
|
|
self.move(int(fx), int(fy), ico)
|
|
# make the target bonus bounce a bit
|
|
if s.alive:
|
|
dy = (t & 7) * 4
|
|
if dy > 16:
|
|
dy = 32-dy
|
|
s.move(s.x, basey - s.ico.h - dy)
|
|
t += 1
|
|
yield None
|
|
self.move(int(fx), desty)
|
|
self.dcap['shield'] = 50
|
|
|
|
def breakwalls(self, x, y0, dir):
|
|
if self.dcap['breakwalls'] > BubPlayer.FrameCounter:
|
|
return # wait before breaking more walls
|
|
if not (2 <= x < boards.curboard.width-2):
|
|
return
|
|
ys = []
|
|
for y in (y0, y0-1):
|
|
if 0 <= y < boards.curboard.height and bget(x, y) == '#':
|
|
ys.append(y)
|
|
if len(ys) == 2:
|
|
from bonuses import DustStar
|
|
dir *= self.dcap['hspeed']
|
|
for y in ys:
|
|
w = boards.curboard.killwall(x, y)
|
|
s = ActiveSprite(w.ico, w.x, w.y)
|
|
dxy = [dir+random.random()-0.5,
|
|
-random.random()*3.0]
|
|
DustStar(w.x, w.y, dxy[0], dxy[1], big=0)
|
|
s.gen.append(s.parabolic(dxy))
|
|
self.dcap['breakwalls'] = BubPlayer.FrameCounter + 40
|
|
|
|
def enter_new_board(self):
|
|
self.playing_fish = False
|
|
self.lifegained = 0
|
|
|
|
def become_fish(self):
|
|
self.playing_fish = True
|
|
icons = self.getcurrenticons()
|
|
self.seticon(icons[11, self.dir])
|
|
|
|
def one_fish_frame(self, onground1, bottom_up):
|
|
if self.bubber.getkey(self.dcap, 'key_jump'):
|
|
# swimming up
|
|
self.step(0, (-2, 2)[bottom_up])
|
|
else:
|
|
if random.random() < 0.05:
|
|
bubbles.FishBubble(self)
|
|
if not onground1(self.x, self.y):
|
|
# swimming down
|
|
ny = (self.y+(2,-1)[bottom_up]) & ~1
|
|
self.move(self.x, ny)
|
|
self.vertical_warp()
|
|
return ((BubPlayer.FrameCounter // 3) % 6) * 0.5
|
|
|
|
def to_front(self):
|
|
ActiveSprite.to_front(self)
|
|
if self.dcap['overlayglasses']:
|
|
ico = images.sprget(('glasses', self.dir))
|
|
y = self.y + self.overlayyoffset
|
|
if self.overlaysprite is None or not self.overlaysprite.alive:
|
|
self.overlaysprite = images.ActiveSprite(ico, self.x, y)
|
|
else:
|
|
self.overlaysprite.to_front()
|
|
self.overlaysprite.move(self.x, y, ico)
|
|
self.overlaysprite.gen = [self.overlaysprite.die([None])]
|
|
|
|
def bottom_up(self):
|
|
return self.dcap['gravity'] < 0.0
|
|
|
|
def watermove(self, x, y):
|
|
# for WaterCell.flooding()
|
|
if self in BubPlayer.DragonList and self.watermoveable:
|
|
self.watermoveable = 0
|
|
self.move(x, y)
|
|
self.up = 0.0
|
|
if self.dcap['shield'] < 6:
|
|
self.dcap['shield'] = 6
|
|
if self.fire <= 10:
|
|
self.fire = 11
|
|
|
|
def become_monster(self, clsname, big=0, immed=0):
|
|
if self in BubPlayer.DragonList:
|
|
BubPlayer.DragonList.remove(self)
|
|
|
|
import monsters, mnstrmap
|
|
mcls = getattr(monsters, clsname)
|
|
mdef = getattr(mnstrmap, clsname)
|
|
m = mcls(mdef, self.x, self.y, self.dir, in_list=self.bubber.dragons)
|
|
m.become_monster(self.bubber, self.dcap, big, immed)
|
|
self.seticon(m.ico)
|
|
self.gen = [self.killing()]
|
|
|
|
def become_bubblingeyes(self, bubble):
|
|
if self in BubPlayer.DragonList:
|
|
self.bubber.emotic(self, 4)
|
|
BubPlayer.DragonList.remove(self)
|
|
|
|
import bubbles
|
|
bubble.to_front()
|
|
m = bubbles.BubblingEyes(self.bubber, self.dcap, bubble)
|
|
self.bubber.dragons.append(m)
|
|
self.gen = [self.killing()]
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
def firenow(self):
|
|
self.fire = 1
|
|
#if boards.curboard.wastingplay is None:
|
|
shootbubbles = self.dcap['shootbubbles']
|
|
special_bubbles = shootbubbles and shootbubbles.pop()
|
|
thrustfactors = None
|
|
N = self.dcap['flower']
|
|
if N == 1:
|
|
angles = [0]
|
|
elif N > 1:
|
|
angles = [i*(2.0*math.pi/N) for i in range(N)]
|
|
self.dcap['flower'] = N*2//3
|
|
elif N > -16: # triple fire, possibly cumulative
|
|
angles = [0]
|
|
for i in range(1, -N+1):
|
|
angles.append(i * 0.19)
|
|
angles.append(i * -0.19)
|
|
else: # heptuple fire
|
|
c = 0.17
|
|
a = math.sqrt(1-c+c*c)
|
|
alpha = math.atan2(math.sqrt(3)/2*c, 1-c/2)
|
|
b = math.sqrt(1+c+c*c)
|
|
beta = math.atan2(math.sqrt(3)/2*c, 1+c/2)
|
|
angles = [0, 0, 0, alpha, -alpha, beta, -beta]
|
|
thrustfactors = [1, 1-c, 1+c, a, a, b, b]
|
|
dir = self.dir
|
|
x = self.x
|
|
## if self.glueddown:
|
|
## gx, gy = self.glueddown
|
|
## dir = dir*gy
|
|
## if not dir:
|
|
## dir = 1
|
|
## delta = self.dir*gx * math.pi/2
|
|
## angles = [angle-delta for angle in angles]
|
|
## x -= 16
|
|
if self.dcap['hotstuff'] > 1:
|
|
base = (random.random()-0.5)*math.pi
|
|
angles = [a + base for a in angles]
|
|
if self.dcap['bigflower'] is not None:
|
|
N = 45
|
|
angle = BubPlayer.FrameCounter - self.dcap['bigflower']
|
|
if not (0 <= angle < N):
|
|
self.dcap['bigflower'] = BubPlayer.FrameCounter
|
|
angle = 0
|
|
angles = [-angle * (2.0*math.pi/N) * self.dir]
|
|
thrustfactors = None
|
|
self.fire = max(1, 64 // self.dcap['firerate'] - 2)
|
|
if self.dcap['autofire'] >= 1:
|
|
self.dcap['autofire'] -= 1
|
|
if not thrustfactors:
|
|
thrustfactors = [None] * len(angles)
|
|
import bonuses
|
|
for angle, thrustfactor in zip(angles, thrustfactors):
|
|
args = (self, x + 4*dir, self.y, dir,
|
|
special_bubbles, angle, thrustfactor,
|
|
self.dcap['shootthrust'])
|
|
bonuses.record_shot(args)
|
|
bubbles.DragonBubble(*args)
|
|
#else:
|
|
# from monsters import DragonShot
|
|
# DragonShot(self)
|
|
|
|
class BubPlayer(gamesrv.Player):
|
|
# global state
|
|
FrameCounter = 0
|
|
PlayerList = []
|
|
DragonList = []
|
|
MonsterList = []
|
|
LimitScore = 0
|
|
LimitScoreColor = None
|
|
LimitTime = None
|
|
PlayersPrivateTime = 100
|
|
SuperSheep = False
|
|
SuperFish = False
|
|
#HighScore = 0
|
|
#HighScoreColor = None
|
|
|
|
INIT_BOARD_CAP = {
|
|
#'LatestLetsGo': -999,
|
|
'BubblesBecome': None,
|
|
'MegaBonus': None,
|
|
'BaseFrametime': 1.0,
|
|
'LeaveBonus': None,
|
|
## 'Moebius': 0,
|
|
'OverridePlayerIcon': None,
|
|
'DisplayPoints': None,
|
|
'SuperSheep': False,
|
|
'SuperFish' : False,
|
|
}
|
|
TRANSIENT_DATA = ('_client', 'key_left', 'key_right',
|
|
'key_jump', 'key_fire', 'pn', 'nameicons',
|
|
'icons', 'transformedicons',
|
|
'standardplayericon', 'iconnames')
|
|
|
|
FISH_MODE_MAP = {0: ('', 0), # swim
|
|
0.5: ('', 1),
|
|
1: ('', 2),
|
|
1.5: ('', 3),
|
|
2: ('', 2),
|
|
2.5: ('', 1),
|
|
3: ('', 4), # lancer de bulle
|
|
4: ('', 5),
|
|
5: ('', 3), # mort
|
|
6: ('cw', 3),
|
|
7: ('rot180', 3),
|
|
8: ('ccw', 3),
|
|
9: ('', 3), # saut, montant
|
|
10: ('', 3), # saut, descend
|
|
11: ('', 6), # shielded
|
|
12: 'black',
|
|
}
|
|
|
|
def __init__(self, n):
|
|
self.pn = n
|
|
self.icons = {}
|
|
self.transformedicons = {'': self.icons}
|
|
self.standardplayericon = images.sprget(GreenAndBlue.players[n][3])
|
|
self.iconnames = {
|
|
(0, -1): GreenAndBlue.players[n][0], # walk
|
|
(0, +1): GreenAndBlue.players[n][3],
|
|
(1, -1): GreenAndBlue.players[n][1],
|
|
(1, +1): GreenAndBlue.players[n][4],
|
|
(2, -1): GreenAndBlue.players[n][2],
|
|
(2, +1): GreenAndBlue.players[n][5],
|
|
(3, -1): GreenAndBlue.players[n][6], # lancer de bulle
|
|
(3, +1): GreenAndBlue.players[n][8],
|
|
(4, -1): GreenAndBlue.players[n][7],
|
|
(4, +1): GreenAndBlue.players[n][9],
|
|
(5, -1): GreenAndBlue.players[n][0], # mort
|
|
(5, +1): GreenAndBlue.players[n][0],
|
|
(6, -1): GreenAndBlue.players[n][11],
|
|
(6, +1): GreenAndBlue.players[n][10],
|
|
(7, -1): GreenAndBlue.players[n][12],
|
|
(7, +1): GreenAndBlue.players[n][12],
|
|
(8, -1): GreenAndBlue.players[n][10],
|
|
(8, +1): GreenAndBlue.players[n][11],
|
|
(9, -1): GreenAndBlue.jumping_players[n][2], # saut, montant
|
|
(9, +1): GreenAndBlue.jumping_players[n][3],
|
|
(10,-1): GreenAndBlue.jumping_players[n][0], # saut, descend
|
|
(10,+1): GreenAndBlue.jumping_players[n][1],
|
|
(11,-1): 'shield-left', # shielded
|
|
(11,+1): 'shield-right',
|
|
(12,-1): 'black', # totally invisible
|
|
(12,+1): 'black',
|
|
}
|
|
self.nameicons = []
|
|
self.team = -1
|
|
self.reset()
|
|
|
|
def reset(self):
|
|
self.letters = {}
|
|
#self.bonbons = 0
|
|
self.points = 0
|
|
self.nextextralife = gamesrv.game.extralife
|
|
self.lives = boards.get_lives()
|
|
self.lifegained = 0
|
|
#self.badpoints = 0
|
|
self.pcap = {}
|
|
self.dragons = []
|
|
self.keepalive = None
|
|
self.stats = {'bubble': 0, 'die': 0}
|
|
|
|
def loadicons(self, flip):
|
|
icons = self.transformedicons[flip]
|
|
if flip == 'fish':
|
|
for dir in (-1, 1):
|
|
for key, value in self.FISH_MODE_MAP.items():
|
|
if value == 'black':
|
|
flip = ''
|
|
else:
|
|
flip, index = value
|
|
value = GreenAndBlue.fish[self.pn][index]
|
|
if dir > 0:
|
|
flip = flip or 'hflip'
|
|
icons[key, dir] = images.sprget((flip, value))
|
|
else:
|
|
for key, value in self.iconnames.items():
|
|
icons[key] = images.sprget((flip, value))
|
|
|
|
def setplayername(self, name):
|
|
name = name.strip()
|
|
for t in [0, 1]:
|
|
if name.endswith('(%d)' % (t+1)):
|
|
self.team = t
|
|
name = name[:-3].strip()
|
|
#print "New player in team", t, "with name", name
|
|
break
|
|
else:
|
|
self.team = -1
|
|
#print "New player with no team:", name
|
|
icons = [images.sprcharacterget(c) for c in name]
|
|
self.nameicons = [ico for ico in icons if ico is not None][:16]
|
|
self.nameicons.reverse()
|
|
scoreboard()
|
|
|
|
def playerjoin(self):
|
|
n = self.pn
|
|
if not self.icons:
|
|
self.loadicons(flip='')
|
|
self.keepalive = None
|
|
if self.points or self.letters:
|
|
print 'New player continues at position #%d.' % n
|
|
else:
|
|
print 'New player is at position #%d.' % n
|
|
self.reset()
|
|
self.key_left = 0
|
|
self.key_right = 0
|
|
self.key_jump = 0
|
|
self.key_fire = 0
|
|
players = [p for p in BubPlayer.PlayerList
|
|
if p.isplaying() and p is not self]
|
|
self.enterboard(players)
|
|
scoreboard()
|
|
#if BubPlayer.LatestLetsGo < BubPlayer.FrameCounter - 30:
|
|
images.Snd.LetsGo.play()
|
|
#BubPlayer.LatestLetsGo = BubPlayer.FrameCounter
|
|
|
|
def playerleaves(self):
|
|
print 'Closing position #%d.' % self.pn
|
|
self.savecaps()
|
|
self.zarkoff()
|
|
self.keepalive = time.time() + KEEPALIVE
|
|
scoreboard()
|
|
|
|
def sameteam(self, other):
|
|
return self.team != -1 and self.team == other.team
|
|
|
|
def enterboard(self, players):
|
|
players = [p for p in players if not p.sameteam(self)]
|
|
leftplayers = [p for p in players if p.start_left]
|
|
rightplayers = [p for p in players if not p.start_left]
|
|
self.start_left = (len(leftplayers) + random.random() <
|
|
len(rightplayers) + random.random())
|
|
self.lifegained = 0
|
|
|
|
def savecaps(self):
|
|
self.pcap = {}
|
|
dragons = self.dragons
|
|
if dragons:
|
|
for key, minimum in Dragon.SAVE_CAP.items():
|
|
self.pcap[key] = max(minimum,
|
|
max([d.dcap[key] for d in dragons]))
|
|
|
|
def zarkoff(self):
|
|
for d in self.dragons[:]:
|
|
d.kill()
|
|
del self.dragons[:]
|
|
|
|
def zarkon(self):
|
|
if self.key_left + self.key_right >= 1999997:
|
|
for dragon in self.dragons:
|
|
self.emotic(dragon, 6)
|
|
self.key_left = self.key_right = 900000
|
|
if self.key_left: self.key_left -= 1
|
|
if self.key_right: self.key_right -= 1
|
|
if self.key_jump: self.key_jump -= 1
|
|
if self.key_fire: self.key_fire -= 1
|
|
#if self.badpoints and not (self.FrameCounter & 7):
|
|
# percent = (int(self.points*0.0000333)+1) * 100
|
|
# decr = min(self.badpoints, percent)
|
|
# self.badpoints -= decr
|
|
# self.givepoints(-decr)
|
|
if boards.curboard and not self.dragons and self.lives != 0:
|
|
#wasting = boards.curboard.wastingplay
|
|
#if wasting is not None and self in wasting:
|
|
# return
|
|
if self.start_left:
|
|
x0 = 3*CELL
|
|
dir = 1
|
|
else:
|
|
x0 = boards.bwidth - 5*CELL
|
|
dir = -1
|
|
y = boards.bheight - 3*CELL
|
|
for x in [x0, x0+4*dir, x0+8*dir, x0+12*dir, x0+16*dir,
|
|
x0-4*dir, x0-8*dir, x0]:
|
|
if onground(x,y):
|
|
for d in BubPlayer.DragonList:
|
|
if d.y == y and abs(d.x-x) <= 5:
|
|
break
|
|
else:
|
|
break
|
|
self.dragons.append(Dragon(self, x, y, dir))
|
|
for key in self.pcap.keys():
|
|
if key not in ('teleport', 'jumpdown'):
|
|
del self.pcap[key]
|
|
|
|
def kLeft(self):
|
|
if self.key_left <= 1:
|
|
self.key_left = 1000000
|
|
def kmLeft(self):
|
|
self.key_left = (self.key_left == 1000000)
|
|
def kRight(self):
|
|
if self.key_right <= 1:
|
|
self.key_right = 1000000
|
|
def kmRight(self):
|
|
self.key_right = (self.key_right == 1000000)
|
|
def kJump(self):
|
|
if self.key_jump <= 1:
|
|
self.key_jump = 1000000
|
|
def kmJump(self):
|
|
self.key_jump = (self.key_jump == 1000000)
|
|
def kFire(self):
|
|
if self.key_fire <= 1:
|
|
self.key_fire = 1000000
|
|
def kmFire(self):
|
|
self.key_fire = (self.key_fire == 1000000)
|
|
|
|
def bubberdie(self):
|
|
self.stats['die'] += 1
|
|
if self.lives is not None and self.lives > 0:
|
|
self.lives -= 1
|
|
scoreboard()
|
|
|
|
def getkey(self, dcap, key_name):
|
|
return getattr(self, dcap[key_name])
|
|
|
|
def setkey(self, dcap, key_name, value):
|
|
setattr(self, dcap[key_name], value)
|
|
|
|
def wannago(self, dcap):
|
|
return dcap['left2right'] * cmp(self.getkey(dcap, 'key_right'),
|
|
self.getkey(dcap, 'key_left'))
|
|
|
|
def turn_single_shot(self, dcap):
|
|
for name in ('key_left', 'key_right'):
|
|
n = self.getkey(dcap, name)
|
|
if n < 999997 and n != 1:
|
|
self.setkey(dcap, name, 0)
|
|
wannago = self.wannago(dcap)
|
|
for name in ('key_left', 'key_right'):
|
|
self.setkey(dcap, name, 0)
|
|
return wannago
|
|
|
|
def givepoints(self, points):
|
|
self.points += points
|
|
if self.points < 0:
|
|
self.points = 0
|
|
while self.points >= self.nextextralife:
|
|
if self.lives is not None and self.lives > 0:
|
|
if gamesrv.game.lifegainlimit is None or self.lifegained < gamesrv.game.lifegainlimit:
|
|
if self.dragons:
|
|
dragon = random.choice(self.dragons)
|
|
dragon.play(images.Snd.Extralife)
|
|
else:
|
|
images.Snd.Extralife.play()
|
|
self.lives += 1
|
|
self.lifegained += 1
|
|
self.nextextralife += gamesrv.game.extralife
|
|
if self.LimitScoreColor is not None and self.points >= self.LimitScore:
|
|
boards.replace_boardgen(boards.game_over(), 1)
|
|
#if self.points > BubPlayer.HighScore:
|
|
# BubPlayer.HighScore = self.points
|
|
# BubPlayer.HighScoreColor = self.pn
|
|
scoreboard()
|
|
|
|
def giveletter(self, l, promize=100000):
|
|
|
|
#logf = open('log', 'a')
|
|
#print >> logf 'giveletter %d:' % self.pn, l
|
|
#logf.close()
|
|
|
|
lettername = bubbles.extend_name(l)
|
|
if lettername not in self.letters:
|
|
self.letters[lettername] = 1
|
|
## nimage = getattr(LetterBubbles, lettername)
|
|
## x0, y0 = self.infocoords()
|
|
## s = images.ActiveSprite(images.sprget(nimage[1]), x0+l*(CELL-1), y0 - 3*CELL)
|
|
## s.gen.append(s.cyclic([nimage[1], nimage[2], nimage[1], nimage[0]], 7))
|
|
scoreboard()
|
|
if len(self.letters) == 6:
|
|
import monsters
|
|
monsters.argh_em_all()
|
|
import bonuses
|
|
if self.dragons:
|
|
for i in range(3):
|
|
dragon = random.choice(self.dragons)
|
|
bonuses.starexplosion(dragon.x, dragon.y, 1)
|
|
for lettername in self.letters:
|
|
dragon = random.choice(self.dragons)
|
|
nimages = getattr(LetterBubbles, lettername)
|
|
bonuses.Parabolic2(dragon.x, dragon.y, nimages)
|
|
dragon = random.choice(self.dragons)
|
|
dragon.play(images.Snd.Extralife)
|
|
music = [images.music_old]
|
|
boards.replace_boardgen(boards.last_monster_killed(460, music))
|
|
self.givepoints(promize)
|
|
|
|
def emotic(self, dragon, strenght):
|
|
bottom_up = hasattr(dragon, 'bottom_up') and dragon.bottom_up()
|
|
vshift = getattr(dragon, 'up', 0.0)
|
|
for i in range(7):
|
|
angle = math.pi/6 * i
|
|
dx, dy = -math.cos(angle), -math.sin(angle)
|
|
nx = random.randrange(3,12)*dx
|
|
ny = random.randrange(3,9)*dy - 12
|
|
if bottom_up:
|
|
dy = -dy
|
|
ny = -ny
|
|
e = ActiveSprite(images.sprget(('vflip'*bottom_up, ('emotic', i))),
|
|
int(dragon.x + 8 + nx),
|
|
int(dragon.y + 8 + ny - vshift))
|
|
e.gen.append(e.straightline((3.3+random.random())*dx, (2.3+random.random())*dy))
|
|
e.gen.append(e.die([None], strenght))
|
|
|
|
|
|
def upgrade(p):
|
|
p.__class__ = BubPlayer
|
|
p.key_left = 0
|
|
p.key_right = 0
|
|
p.key_jump = 0
|
|
p.key_fire = 0
|
|
p.dragons = []
|
|
|
|
|
|
def xyiconumber(digits, x, y, pts, lst, width=7):
|
|
if pts >= 10**width:
|
|
pts = 10**width-1
|
|
for l in range(width):
|
|
ico = images.sprget(digits[pts % 10])
|
|
lst.append((x + (ico.w+1)*(width-1-l), y, ico))
|
|
pts = pts//10
|
|
if not pts:
|
|
break
|
|
return lst[-1][0]
|
|
|
|
def scoreboard(reset=0, inplace=0, compresslimittime=0):
|
|
endgame = 1
|
|
if reset:
|
|
for p in BubPlayer.PlayerList:
|
|
if inplace:
|
|
for s in p.letters.values():
|
|
if isinstance(s, ActiveSprite):
|
|
s.kill()
|
|
if len(p.letters) == 6:
|
|
p.letters.clear()
|
|
for key in p.letters:
|
|
p.letters[key] = 2
|
|
brd = boards.curboard
|
|
if not brd or not gamesrv.sprites_by_n:
|
|
return
|
|
lst = []
|
|
bubblesshown = {}
|
|
plist = []
|
|
teamslist = [[], []]
|
|
teamspoints = [0, 0]
|
|
for p in BubPlayer.PlayerList:
|
|
if p.isplaying():
|
|
if p.lives != 0:
|
|
endgame = 0
|
|
else:
|
|
if not p.keepalive:
|
|
continue
|
|
if p.keepalive < time.time():
|
|
p.reset()
|
|
continue
|
|
if BubPlayer.DisplayPoints is not None:
|
|
points = BubPlayer.DisplayPoints(p)
|
|
else:
|
|
points = p.points
|
|
if p.team == -1:
|
|
plist.append((points, p, None))
|
|
else:
|
|
teamslist[p.team].append((points,p))
|
|
teamspoints[p.team] += points
|
|
teamslist[0].sort()
|
|
teamslist[1].sort()
|
|
plist.append((teamspoints[0], None, teamslist[0]))
|
|
plist.append((teamspoints[1], None, teamslist[1]))
|
|
plist.sort()
|
|
x0 = boards.bwidth
|
|
y0 = boards.bheight
|
|
for score, p, t in plist:
|
|
if p:
|
|
if p.lives == 0:
|
|
ico = images.sprget(GreenAndBlue.gameover[p.pn][0])
|
|
elif p.icons:
|
|
if p.isplaying():
|
|
mode = 0
|
|
else:
|
|
mode = 11
|
|
ico = BubPlayer.OverridePlayerIcon or p.icons[mode, -1]
|
|
lst.append((x0+9*CELL-ico.w, y0-ico.h, ico))
|
|
#if boards.curboard.wastingplay is None:
|
|
for l in range(6):
|
|
name = bubbles.extend_name(l)
|
|
if name in p.letters:
|
|
x, y = x0+l*(CELL-1), y0-3*CELL
|
|
imglist = getattr(LetterBubbles, name)
|
|
ico = images.sprget(imglist[1])
|
|
if gamesrv.game.End in (0, 1):
|
|
s = p.letters[name]
|
|
if (isinstance(s, ActiveSprite) and
|
|
BubPlayer.FrameCounter <= s.timeout):
|
|
s.move(x, y)
|
|
bubblesshown[s] = 1
|
|
continue
|
|
if s == 1:
|
|
s = ActiveSprite(ico, x, y)
|
|
s.setimages(s.cyclic([imglist[0], imglist[1],
|
|
imglist[2], imglist[1]]))
|
|
s.timeout = BubPlayer.FrameCounter + 500
|
|
p.letters[name] = s
|
|
bubblesshown[s] = 1
|
|
continue
|
|
lst.append((x, y, ico))
|
|
## else:
|
|
## ico = images.sprget(Bonuses.blue_sugar)
|
|
## lst.append((x0+12, y0-3*CELL-8, ico))
|
|
## xyiconumber(DigitsMisc.digits_white, x0-19, y0-3*CELL+5,
|
|
## p.bonbons, lst)
|
|
xyiconumber(GreenAndBlue.digits[p.pn], x0+2, y0-18, score, lst)
|
|
if p.lives is not None and p.lives > 0:
|
|
xyiconumber(DigitsMisc.digits_white, x0+7*CELL, y0-18,
|
|
p.lives, lst, width=2)
|
|
x = x0+13*HALFCELL
|
|
for ico in p.nameicons:
|
|
x -= 7
|
|
lst.append((x, y0-35, ico))
|
|
y0 -= 7*HALFCELL
|
|
else: # Team
|
|
for pscore, p in t:
|
|
if p.lives == 0:
|
|
ico = images.sprget(GreenAndBlue.gameover[p.pn][0])
|
|
elif p.icons:
|
|
if p.isplaying():
|
|
mode = 0
|
|
else:
|
|
mode = 11
|
|
ico = BubPlayer.OverridePlayerIcon or p.icons[mode, -1]
|
|
lst.append((x0+9*CELL-ico.w, y0-ico.h, ico))
|
|
for l in range(6):
|
|
name = bubbles.extend_name(l)
|
|
if name in p.letters:
|
|
x, y = x0+l*(CELL-1), y0-2*CELL
|
|
imglist = getattr(LetterBubbles, name)
|
|
ico = images.sprget(imglist[1])
|
|
if gamesrv.game.End in (0, 1):
|
|
s = p.letters[name]
|
|
if (isinstance(s, ActiveSprite) and
|
|
BubPlayer.FrameCounter <= s.timeout):
|
|
s.move(x, y)
|
|
bubblesshown[s] = 1
|
|
continue
|
|
if s == 1:
|
|
s = ActiveSprite(ico, x, y)
|
|
s.setimages(s.cyclic([imglist[0], imglist[1],
|
|
imglist[2], imglist[1]]))
|
|
s.timeout = BubPlayer.FrameCounter + 500
|
|
p.letters[name] = s
|
|
bubblesshown[s] = 1
|
|
continue
|
|
lst.append((x, y, ico))
|
|
x = x0+13*HALFCELL
|
|
for ico in p.nameicons:
|
|
x -= 7
|
|
lst.append((x, y0-19, ico))
|
|
y0 -= 4*HALFCELL
|
|
if t != []:
|
|
xyiconumber(GreenAndBlue.digits[t[-1][1].pn], x0+2, y0-18, score, lst)
|
|
ico = images.sprget(('hat', p.team, -1, 1))
|
|
lst.append((x0+9*CELL-ico.w, y0-ico.h+16, ico))
|
|
y0 -= 5*HALFCELL
|
|
for p in BubPlayer.PlayerList:
|
|
for name, s in p.letters.items():
|
|
if isinstance(s, ActiveSprite) and s not in bubblesshown:
|
|
p.letters[name] = 2
|
|
s.kill()
|
|
compressable = len(lst)
|
|
#if BubPlayer.HighScoreColor is not None:
|
|
# x = xyiconumber(GreenAndBlue.digits[BubPlayer.HighScoreColor],
|
|
# x0+2*CELL, HALFCELL, BubPlayer.HighScore, lst)
|
|
# ico = images.sprget(GreenAndBlue.players[BubPlayer.HighScoreColor][3])
|
|
# lst.append((x-5*HALFCELL, 1, ico))
|
|
if BubPlayer.LimitScoreColor is not None:
|
|
xyiconumber(GreenAndBlue.digits[BubPlayer.LimitScoreColor],
|
|
x0+2*CELL, HALFCELL, BubPlayer.LimitScore, lst)
|
|
if BubPlayer.LimitTime is not None:
|
|
seconds = int(BubPlayer.LimitTime)
|
|
xyiconumber(DigitsMisc.digits_white, x0+2*CELL, HALFCELL,
|
|
seconds // 60, lst, width=3)
|
|
ico = images.sprget('colon')
|
|
lst.append((x0+5*CELL-1, HALFCELL+1, ico))
|
|
seconds = seconds % 60
|
|
ico = images.sprget(DigitsMisc.digits_white[seconds // 10])
|
|
lst.append((x0+6*CELL, HALFCELL, ico))
|
|
ico = images.sprget(DigitsMisc.digits_white[seconds % 10])
|
|
lst.append((x0+6*CELL+ico.w, HALFCELL, ico))
|
|
ymin = HALFCELL + ico.h
|
|
elif compresslimittime:
|
|
ico = images.sprget(DigitsMisc.digits_white[0])
|
|
ymin = HALFCELL + ico.h
|
|
else:
|
|
ymin = 0
|
|
if not brd.bonuslevel:
|
|
if brd.num < 99:
|
|
xyiconumber(DigitsMisc.digits_white, 2, 2, brd.num+1, lst, width=2)
|
|
else:
|
|
xyiconumber(DigitsMisc.digits_white, 2, 2, brd.num+1, lst, width=3)
|
|
|
|
# compress the scoreboard vertically if it doesn't fit
|
|
ymin += HALFCELL
|
|
if y0 < ymin:
|
|
factor = float(boards.bheight-ymin) / (boards.bheight-y0)
|
|
shift = ymin - y0*factor + 0.5
|
|
for i in range(compressable):
|
|
x, y, ico = lst[i]
|
|
lst[i] = x, int((y+ico.h)*factor+shift)-ico.h, ico
|
|
|
|
brd.writesprites('scoreboard', lst)
|
|
|
|
if gamesrv.game.End in (0, 1):
|
|
gamesrv.game.End = endgame
|
|
|
|
|
|
# initialize global board data
|
|
def reset_global_board_state():
|
|
for key, value in BubPlayer.INIT_BOARD_CAP.items():
|
|
setattr(BubPlayer, key, value)
|
|
reset_global_board_state()
|