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 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
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]
def onground(self): for b in self.bricks: if b.gen: # brick still moving return 0 for px, py in self.brick_positions(): if bget(px // CELL, py // CELL + 1) >= '#': return 1 return 0
def moving(self): import boards dx = dy = 0 turned = None was_clear = 0 while 1: if dx or dy: frontx = self.x + CELL + dx * (CELL + 1) fronty = self.y + CELL + dy * (CELL + 1) clear = (bget((frontx + dy) // CELL, (fronty - dx) // CELL) == ' ' and bget((frontx - dy) // CELL, (fronty + dx) // CELL) == ' ') if clear: blocked = 0 else: blocked = (was_clear or (self.x <= 2 * CELL and dx < 0) or (self.x >= boards.bwidth - 4 * CELL and dx > 0)) else: blocked = 1 if blocked: if turned: dx, dy = turned turned = None continue self.lastmove = None else: if turned: self.resetimages(dx, dy) turned = None self.lastmove = dx, dy self.step(2 * dx, 2 * dy) self.vertical_warp() was_clear = clear yield None if self.wannadx != dx or self.wannady != dy: if ((self.wannadx and not (self.y % CELL)) or (self.wannady and not (self.x % CELL))): turned = dx, dy dx = self.wannadx dy = self.wannady
def moved(self, old_position): for b in self.bricks: b.set(' ') try: for px, py in self.brick_positions(): if bget(px // CELL, py // CELL) != ' ': self.restore_position(old_position) return 0 for b, (px, py) in zip(self.bricks, self.brick_positions()): b.follow(px, py) finally: for b in self.bricks: b.set('!') # note: we need '!' < '#' return 1
def rdig(x1, y1, x2, y2, reversed, holes=holes): # digs the rectangle (x1,y1,x2,y2) and marks it as # processed. Also recursively mark as processed all existing # holes that are pacman-connected to the rectangle. xrange = range(x1, x2) yrange = range(y1, y2) if not reversed: xrange.reverse() yrange.reverse() if len(xrange) > len(yrange): xylist = [(x, y) for x in xrange for y in yrange] else: xylist = [(x, y) for y in yrange for x in xrange] t = 0 for x, y in xylist: if bget(x, y) == '#': curboard.killwall(x, y) if t == 0: yield None t = 2 else: t -= 1 holes.setdefault((x, y), 0) fill = [] for x in range(x1, x2 - 1): for y in range(y1, y2 - 1): fill.append((x, y)) for x, y in fill: if ((x, y) in holes and (x, y + 1) in holes and (x + 1, y) in holes and (x + 1, y + 1) in holes): if (holes[x, y] == 0 or holes[x, y + 1] == 0 or holes[x + 1, y] == 0 or holes[x + 1, y + 1] == 0): holes[x, y] = 1 holes[x, y + 1] = 1 holes[x + 1, y] = 1 holes[x + 1, y + 1] = 1 fill.append((x + 1, y)) fill.append((x - 1, y)) fill.append((x, y + 1)) fill.append((x, y - 1))
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 digwalls(self): import boards holes = {} for x in range(2, boards.width - 2): y = boards.height - 1 if bget(x, 0) == '#' or bget(x, y) == '#': if bget(x, 0) == ' ': curboard.putwall(x, 0) if bget(x, y) == ' ': curboard.putwall(x, y) curboard.reorder_walls() for y in range(1, boards.height - 1): if bget(x, y) == ' ': holes[x, y] = 0 if x % 7 == 0: yield None # 'holes' maps coordinates (x,y) to 0 (not processed) # or 1 (processed). # All processed holes are pacman-connected. def rdig(x1, y1, x2, y2, reversed, holes=holes): # digs the rectangle (x1,y1,x2,y2) and marks it as # processed. Also recursively mark as processed all existing # holes that are pacman-connected to the rectangle. xrange = range(x1, x2) yrange = range(y1, y2) if not reversed: xrange.reverse() yrange.reverse() if len(xrange) > len(yrange): xylist = [(x, y) for x in xrange for y in yrange] else: xylist = [(x, y) for y in yrange for x in xrange] t = 0 for x, y in xylist: if bget(x, y) == '#': curboard.killwall(x, y) if t == 0: yield None t = 2 else: t -= 1 holes.setdefault((x, y), 0) fill = [] for x in range(x1, x2 - 1): for y in range(y1, y2 - 1): fill.append((x, y)) for x, y in fill: if ((x, y) in holes and (x, y + 1) in holes and (x + 1, y) in holes and (x + 1, y + 1) in holes): if (holes[x, y] == 0 or holes[x, y + 1] == 0 or holes[x + 1, y] == 0 or holes[x + 1, y + 1] == 0): holes[x, y] = 1 holes[x, y + 1] = 1 holes[x + 1, y] = 1 holes[x + 1, y + 1] = 1 fill.append((x + 1, y)) fill.append((x - 1, y)) fill.append((x, y + 1)) fill.append((x, y - 1)) def joined(x1, y1, x2, y2, holes=holes, boards=boards): # returns # 1 if the rectangle (x1,y1,x2,y2) is pac-connected to # some already-processed holes # 0 if it is not # -1 if (x1,y1,x2,y2) is out of the screen if x1 < 2 or y1 < 1 or x2 > boards.width - 2 or y2 > boards.height - 1: return -1 accum1 = accum2 = 0 for x in range(x1, x2): if holes.get((x, y1 - 1)): accum1 += 1 if accum1 == 2: return 1 else: accum1 = 0 if holes.get((x, y2)): accum2 += 1 if accum2 == 2: return 1 else: accum2 = 0 accum1 = accum2 = 0 for y in range(y1, y2): if holes.get((x1 - 1, y)): accum1 += 1 if accum1 == 2: return 1 else: accum1 = 0 if holes.get((x2, y)): accum2 += 1 if accum2 == 2: return 1 else: accum2 = 0 return 0 if not holes: holes[boards.width // 2, boards.height // 2] = 0 holeslist = holes.keys() random.shuffle(holeslist) startx, starty = holeslist.pop() # make the hole larger (2x2) towards the center of the board if startx > boards.width // 2: startx -= 1 if starty > boards.height // 2: starty -= 1 # initial 2x2 hole for t in rdig(startx, starty, startx + 2, starty + 2, 0): yield t dlist = [ (0, 0, 1, 0, 0, -1), (0, 0, 1, 0, 0, 0), # right (0, 0, 0, 1, -1, 0), (0, 0, 0, 1, 0, 0), # bottom (-1, 0, 0, 0, -1, -1), (-1, 0, 0, 0, -1, 0), # left (0, -1, 0, 0, -1, -1), (0, -1, 0, 0, 0, -1), # top ] while holeslist: random.shuffle(dlist) pending = holeslist holeslist = [] progress = 0 for x, y in pending: if holes[x, y] != 0: continue for dx1, dy1, dx2, dy2, dx, dy in dlist: x1 = x + dx y1 = y + dy x2 = x1 + 2 y2 = y1 + 2 result = 0 while result == 0: result = joined(x1, y1, x2, y2) if result == 1: # rectangle (x1,y1,x2,y2) is good for t in rdig( x1, y1, x2, y2, dx1 < 0 or dy1 < 0 or dx2 < 0 or dy2 < 0): yield t progress = 1 break x1 += dx1 y1 += dy1 x2 += dx2 y2 += dy2 else: # rectangle (x1,y1,x2,y2) is too large for the screen # failure continue break else: # no successful direction found from this point holeslist.append((x, y)) # try again later if not progress: # deadlocked situation, add a new random hole x = random.randrange(2, boards.width - 2) y = random.randrange(1, boards.height - 1) holeslist.insert(0, (x, y)) holes.setdefault((x, y), 0) yield None # pattern transformation: # X. .. # ... --> ... # .X .X progress = 1 while progress: progress = 0 for y in range(1, boards.height - 1): for x in range(3, boards.width - 3): if (' ' == bget(x, y) == bget(x + 1, y) == bget(x - 1, y) == bget(x, y + 1) == bget(x, y - 1)): if '#' == bget(x - 1, y - 1) == bget(x + 1, y + 1): curboard.killwall(x - 1, y - 1) progress = 1 elif '#' == bget(x + 1, y - 1) == bget(x - 1, y + 1): curboard.killwall(x + 1, y - 1) progress = 1 yield None
def anywall(x1, y1, x2, y2): for tx in range(x1, x2): for ty in range(y1, y2): if bget(tx, ty) == '#': return 1 return 0
def frame(self): heights = {1: curboard.height, curboard.width - 2: curboard.height} ymax = curboard.height - 1 maxheight = curboard.height * 3 // 4 for x in range(2, curboard.width - 2): if bget(x, ymax) == ' ': curboard.putwall(x, ymax) height = 1 for y in range(ymax - 1, -1, -1): if bget(x, y) == '#': if height == maxheight: curboard.killwall(x, y) else: height += 1 heights[x] = height xlist = range(2, curboard.width - 2) random.shuffle(xlist) for x in xlist: h = heights[x] x1 = x2 = x while heights[x1 - 1] == h: x1 -= 1 while heights[x2] == h: x2 += 1 parts = (x2 - x1) // 8 if not parts: continue left = 0 if heights[x1 - 1] > h: x1 -= 1 left += 1 right = parts + 1 if heights[x2] > h: x2 += 1 right -= 1 for p in range(left, right): x = x1 + ((x2 - x1 - 1) * p + parts // 2) // parts y = ymax for i in range(2): while bget(x, y) == '#': y -= 1 if y >= 3: curboard.putwall(x, y) heights[x] += 1 curboard.reorder_walls() walls_by_pos = curboard.walls_by_pos moves = 1 s = 8.0 while moves: moves = 0 for y in range(curboard.height - 3, -1, -1): for x in range(2, curboard.width - 2): if ((y, x) in walls_by_pos and (y + 1, x) not in walls_by_pos): y0 = y while (y0 - 1, x) in walls_by_pos: y0 -= 1 w = curboard.killwall(x, y0, 0) curboard.putwall(x, y + 1, w) moves = 1 curboard.reorder_walls() for i in range(int(s) + 2): yield None s *= 0.95 self.ready = 1 while 1: yield None
def stopping(self): self.move(self.x, -self.ico.h) positions = [(py // CELL, px // CELL) for px, py in self.brick_positions() if py >= 0] positions.sort() positions = [(px, py) for py, px in positions] for b in self.bricks: b.stop(self.tetris) if b.ty < 0: b.remove() self.bricks = [] staticbricks = self.tetris.staticbricks pts = 500 while 1: for px, py in positions: y = py x1 = px while (x1 - 1, y) in staticbricks: x1 -= 1 if bget(x1 - 1, y) != '#': continue x2 = px while (x2, y) in staticbricks: x2 += 1 if bget(x2, y) != '#': continue if x2 - x1 < 2: continue # full line ico = images.sprget(Bubble.exploding_bubbles[0]) self.tetris.score[self.bubber] = self.tetris.score.get( self.bubber, 0) + 1 xlist = range(x1, x2) for x in xlist: s = ActiveSprite(ico, x * CELL + random.randrange(CELL) - CELL, y * CELL + random.randrange(CELL) - CELL) s.gen.append(s.die(Bubble.exploding_bubbles)) s = staticbricks[x, y] points(x * CELL + HALFCELL, y * CELL + HALFCELL, s, pts) s.remove() if pts == 500: self.play(images.Snd.Fruit) elif pts == 4000: self.play(images.Snd.Extralife) else: self.play(images.Snd.Extra) pts *= 2 for y in range(py - 1, -1, -1): if not [x for x in xlist if (x, y) in staticbricks]: break for t in range(4): yield None if [x for x in xlist if (x, y + 1) in staticbricks]: break for x in xlist: if (x, y) in staticbricks: staticbricks[x, y].shiftdown() yield None break else: break if self.tetris.ready < 2: self.gen.append(self.playing_bubble(self))