mirror of
https://github.com/abakh/nbsdgames
synced 2025-04-28 14:09:32 -04:00
290 lines
9.1 KiB
Python
290 lines
9.1 KiB
Python
from __future__ import generators
|
|
import os, random
|
|
import images, gamesrv
|
|
from images import ActiveSprite
|
|
import boards
|
|
from boards import CELL, HALFCELL, bget
|
|
from monsters import Monster
|
|
from player import Dragon, BubPlayer
|
|
from bubbles import Bubble
|
|
import bonuses
|
|
|
|
LocalDir = os.path.basename(os.path.dirname(__file__))
|
|
|
|
localmap = {
|
|
('lem-walk', 1,0) : ('image1.ppm', ( 0, 0, 32, 32)),
|
|
('lem-walk', 1,1) : ('image1.ppm', ( 32, 0, 32, 32)),
|
|
('lem-walk', 1,2) : ('image1.ppm', ( 64, 0, 32, 32)),
|
|
('lem-walk', 1,3) : ('image1.ppm', ( 96, 0, 32, 32)),
|
|
('lem-walk', 1,4) : ('image1.ppm', (128, 0, 32, 32)),
|
|
('lem-walk', 1,5) : ('image1.ppm', (160, 0, 32, 32)),
|
|
('lem-walk', 1,6) : ('image1.ppm', (192, 0, 32, 32)),
|
|
('lem-walk', 1,7) : ('image1.ppm', (224, 0, 32, 32)),
|
|
('lem-fall', 1,0) : ('image1.ppm', (256, 0, 32, 32)),
|
|
('lem-fall', 1,1) : ('image1.ppm', (288, 0, 32, 32)),
|
|
('lem-fall', 1,2) : ('image1.ppm', (320, 0, 32, 32)),
|
|
('lem-fall', 1,3) : ('image1.ppm', (352, 0, 32, 32)),
|
|
|
|
('lem-fall',-1,3) : ('image2.ppm', ( 0, 0, 32, 32)),
|
|
('lem-fall',-1,2) : ('image2.ppm', ( 32, 0, 32, 32)),
|
|
('lem-fall',-1,1) : ('image2.ppm', ( 64, 0, 32, 32)),
|
|
('lem-fall',-1,0) : ('image2.ppm', ( 96, 0, 32, 32)),
|
|
('lem-walk',-1,7) : ('image2.ppm', (128, 0, 32, 32)),
|
|
('lem-walk',-1,6) : ('image2.ppm', (160, 0, 32, 32)),
|
|
('lem-walk',-1,5) : ('image2.ppm', (192, 0, 32, 32)),
|
|
('lem-walk',-1,4) : ('image2.ppm', (224, 0, 32, 32)),
|
|
('lem-walk',-1,3) : ('image2.ppm', (256, 0, 32, 32)),
|
|
('lem-walk',-1,2) : ('image2.ppm', (288, 0, 32, 32)),
|
|
('lem-walk',-1,1) : ('image2.ppm', (320, 0, 32, 32)),
|
|
('lem-walk',-1,0) : ('image2.ppm', (352, 0, 32, 32)),
|
|
|
|
('lem-jail', 0) : ('image4.ppm', ( 0, 0, 32, 32)),
|
|
('lem-jail', 1) : ('image4.ppm', ( 0, 32, 32, 32)),
|
|
('lem-jail', 2) : ('image4.ppm', ( 0, 64, 32, 32)),
|
|
}
|
|
for n in range(16):
|
|
localmap[('lem-crash', n)] = ('image3.ppm', (32*n, 0, 32, 32))
|
|
|
|
music = gamesrv.getmusic(os.path.join(LocalDir, 'music.wav'))
|
|
snd_ouch = gamesrv.getsample(os.path.join(LocalDir, 'ouch.wav'))
|
|
|
|
|
|
class Lemmy:
|
|
right = [('lem-walk', 1,n) for n in range(8)]
|
|
left = [('lem-walk',-1,n) for n in range(8)]
|
|
jailed = [('lem-jail', n) for n in range(3)]
|
|
|
|
|
|
class Lemming(Monster):
|
|
|
|
def __init__(self, lemmings, x, y, dir):
|
|
Monster.__init__(self, Lemmy, x, y, dir, in_list=lemmings.lemlist)
|
|
self.lemmings = lemmings
|
|
|
|
def argh(self, *args, **kwds):
|
|
self.untouchable()
|
|
self.gen = [self.jumpout()]
|
|
|
|
def resetimages(self):
|
|
pass
|
|
|
|
def touched(self, dragon):
|
|
if 20 >= abs(self.x - dragon.x) >= 14:
|
|
if self.x < dragon.x:
|
|
self.dir = -1
|
|
else:
|
|
self.dir = 1
|
|
|
|
def in_bubble(self, bubble):
|
|
self.move(bubble.x, bubble.y)
|
|
Monster.in_bubble(self, bubble)
|
|
return -1
|
|
|
|
def bubbling(self, bubble):
|
|
dx = random.randrange(-3, 4)
|
|
dy = random.randrange(-4, 2)
|
|
counter = 0
|
|
while not hasattr(bubble, 'poplist'):
|
|
if self.y < -CELL and bubble.y > CELL: # bubble wrapped
|
|
self.leaveboard(bubble)
|
|
return
|
|
self.move(bubble.x+dx, bubble.y+dy)
|
|
yield None
|
|
if bubble.poplist is None and bubble.y <= -2*CELL+1:
|
|
self.leaveboard(bubble)
|
|
return
|
|
self.setimages(None)
|
|
self.gen = [self.jumpout()]
|
|
|
|
def jumpout(self):
|
|
# jumping out of the bubble
|
|
self.seticon(images.sprget(self.mdef.jailed[1]))
|
|
dxy = [(random.random()-0.5) * 9.0,
|
|
(random.random()+0.5) * (-5.0)]
|
|
for n in self.parabolic(dxy):
|
|
yield n
|
|
if dxy[1] >= 2.0:
|
|
break
|
|
if dxy[0] < 0:
|
|
self.dir = -1
|
|
else:
|
|
self.dir = 1
|
|
self.touchable = 1
|
|
self.gen.append(self.falling())
|
|
|
|
def falling(self):
|
|
self.setimages(None)
|
|
n = 0
|
|
lemmap = self.lemmings.lemmap
|
|
while not self.onground():
|
|
yield None
|
|
self.move(self.x, (self.y + 4) & ~3,
|
|
lemmap['lem-fall', self.dir, n&3])
|
|
n += 1
|
|
if self.y >= boards.bheight:
|
|
self.kill()
|
|
return
|
|
yield None
|
|
if n <= 33:
|
|
self.gen.append(self.walking())
|
|
else:
|
|
self.play(snd_ouch)
|
|
self.untouchable()
|
|
self.to_front()
|
|
self.gen = [self.die([('lem-crash', n) for n in range(16)], 2)]
|
|
|
|
def walking(self):
|
|
self.setimages(None)
|
|
n = 0
|
|
lemmap = self.lemmings.lemmap
|
|
y0 = self.y // 16
|
|
while self.y == y0*16:
|
|
yield None
|
|
nx = self.x + self.dir*2
|
|
x0 = (nx+15) // 16
|
|
if bget(x0, y0+1) == ' ':
|
|
if bget(x0, y0+2) == ' ':
|
|
y0 += 1 # fall
|
|
elif bget(x0, y0) != ' ':
|
|
self.dir = -self.dir
|
|
self.resetimages()
|
|
continue
|
|
else: # climb
|
|
y0 -= 1
|
|
n2 = 0
|
|
while self.y > y0*16:
|
|
self.step(0, -2)
|
|
if n2:
|
|
n2 -= 1
|
|
else:
|
|
self.seticon(lemmap['lem-walk', self.dir, n&7])
|
|
n += 1
|
|
n2 = 2
|
|
yield None
|
|
self.move(nx, self.y, lemmap['lem-walk', self.dir, n&7])
|
|
n += 1
|
|
yield None
|
|
yield None
|
|
self.gen.append(self.falling())
|
|
|
|
def onground(self):
|
|
if self.y & 15:
|
|
return 0
|
|
x0 = (self.x+15) // 16
|
|
y0 = self.y // 16 + 2
|
|
return bget(x0, y0) != ' ' == bget(x0, y0-1)
|
|
|
|
def leaveboard(self, bubble):
|
|
if hasattr(bubble, 'd'):
|
|
bubble.play(images.Snd.Extra)
|
|
score = self.lemmings.score
|
|
bubber = bubble.d.bubber
|
|
score[bubber] = score.get(bubber, 0) + 1
|
|
bonuses.points(bubble.x, bubble.y, bubble.d, 500)
|
|
self.kill()
|
|
|
|
default_mode = walking
|
|
|
|
|
|
class Lemmings:
|
|
|
|
def bgen(self, limittime = 60.1): # 0:60
|
|
self.score = {}
|
|
for t in boards.initsubgame(music, self.displaypoints):
|
|
yield t
|
|
self.lemmap = {}
|
|
for key in localmap:
|
|
self.lemmap[key] = images.sprget(key)
|
|
|
|
tc = boards.TimeCounter(limittime)
|
|
self.lemlist = []
|
|
self.lemtotal = 0
|
|
for t in self.frame():
|
|
t = boards.normal_frame()
|
|
yield t
|
|
tc.update(t)
|
|
if tc.time == 0.0:
|
|
break
|
|
|
|
tc.restore()
|
|
for s in self.lemlist[:]:
|
|
if s.alive:
|
|
s.kill()
|
|
for s in images.ActiveSprites[:]:
|
|
if isinstance(s, Bubble):
|
|
s.pop()
|
|
for t in boards.result_ranking(self.score.copy(), self.lemtotal):
|
|
yield t
|
|
|
|
def displaypoints(self, bubber):
|
|
return self.score.get(bubber, 0)
|
|
|
|
def frame(self):
|
|
windline = '>>' + '^'*(curboard.width-4) + '<<'
|
|
curboard.winds = [windline] * curboard.height
|
|
|
|
countholes = 0
|
|
ymax = curboard.height-1
|
|
for x in range(2, curboard.width-2):
|
|
if bget(x, ymax) == ' ':
|
|
countholes += 1
|
|
|
|
xrange = []
|
|
try:
|
|
for delta in range(2, curboard.width):
|
|
for x in [delta, curboard.width-delta-1]:
|
|
if x in xrange: raise StopIteration
|
|
xrange.append(x)
|
|
except StopIteration:
|
|
pass
|
|
|
|
for x in xrange:
|
|
if countholes > curboard.width//6 and bget(x, ymax) == ' ':
|
|
curboard.putwall(x, ymax)
|
|
curboard.reorder_walls()
|
|
countholes -= 1
|
|
for y in range(0, ymax):
|
|
if bget(x, y) == ' ':
|
|
break
|
|
curboard.killwall(x, y)
|
|
yield None
|
|
|
|
testing = {}
|
|
def addlemming():
|
|
for x, y in testing.items():
|
|
if bget(x, y) != ' ' == bget(x, y-1):
|
|
if x <= curboard.width//2:
|
|
dir = 1
|
|
else:
|
|
dir = -1
|
|
s = Lemming(self, x*CELL-HALFCELL, (y-2)*CELL, dir)
|
|
self.lemtotal += 1
|
|
if y < ymax:
|
|
testing[x] = y+1
|
|
else:
|
|
del testing[x]
|
|
for x in xrange:
|
|
testing[x] = 1
|
|
addlemming()
|
|
yield None
|
|
while testing:
|
|
addlemming()
|
|
yield None
|
|
|
|
while self.lemlist:
|
|
yield None
|
|
|
|
# This game is suitable for at least min_players players
|
|
min_players = 1
|
|
|
|
def run():
|
|
global curboard
|
|
from boards import curboard
|
|
boards.replace_boardgen(Lemmings().bgen())
|
|
|
|
def setup():
|
|
for key, (filename, rect) in localmap.items():
|
|
filename = os.path.join(LocalDir, filename)
|
|
images.sprmap[key] = (filename, rect)
|
|
setup()
|