nbsdgames/bubbob/player.py
2022-02-03 13:46:22 +03:30

1214 lines
45 KiB
Python

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 = list(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 list(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 list(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 list(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 list(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 list(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 list(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 list(BubPlayer.INIT_BOARD_CAP.items()):
setattr(BubPlayer, key, value)
reset_global_board_state()