summaryrefslogtreecommitdiff
path: root/bubbob/levels/rnglevel
diff options
context:
space:
mode:
Diffstat (limited to 'bubbob/levels/rnglevel')
-rw-r--r--bubbob/levels/rnglevel1282
1 files changed, 0 insertions, 1282 deletions
diff --git a/bubbob/levels/rnglevel b/bubbob/levels/rnglevel
deleted file mode 100644
index 7a3186b..0000000
--- a/bubbob/levels/rnglevel
+++ /dev/null
@@ -1,1282 +0,0 @@
-from random import *
-from math import *
-
-import boarddef
-from boarddef import LNasty, LMonky, LGhosty, LFlappy
-from boarddef import LSpringy, LOrcy, LGramy, LBlitzy
-from boarddef import RNasty, RMonky, RGhosty, RFlappy
-from boarddef import RSpringy, ROrcy, RGramy, RBlitzy
-
-def cmp(a, b):
- return (a > b) - (a < b)
-
-def flat(mean,var):
- return randrange(mean-var,mean+var+1)
-
-def dice(n,sides,orig=1):
- result = 0
- for i in range(n):
- result += orig+randrange(sides)
- return result
-
-def fish(mu):
- def fact(n):
- r = 1.
- for i in range(1,n+1):
- r *= i
- return r
- scale = fact(0)/exp(-mu)
- dens = []
- while 1:
- x = len(dens)
- dens.append(int(scale*exp(-mu)*pow(mu,x)/fact(x)+0.5))
- if x > mu and dens[-1] == 0:
- break
- table = []
- x = 0
- for d in dens:
- for i in range(d):
- table.append(x)
- x += 1
- return choice(table)
-
-
-class RandomLevel(boarddef.Level):
- WIDTH = 32
- HEIGHT = 28
- MAXTRY = 1000
- # parameters of the 'mess generator'
- # mess_prob : the probability that a cell turn into a wall
-
- def __init__(self,num):
- if hasattr(self.__class__, 'walls'):
- #print 'Reusing previously generated level'
- #print self.__class__.walls
- self.walls = self.__class__.walls
- boarddef.Level.__init__(self,num)
- return
-
- #print 'Generating a new level'
- self.reset(fill=False)
-
- self.windmap = [ [' ' for x in range(self.WIDTH)] for y in range(self.HEIGHT) ]
-
- if hasattr(self, 'auto'):
- self.generate()
- self.do_bonuses()
-
- for gw in self.genwalls:
- gw[0](self,*gw[1:])
-
- if hasattr(self, 'mlist'):
- self.do_monsters()
-
- self.dig_vertical_walls()
- self.do_walls()
- self.walls = self.__class__.walls
- #print self.walls
-
- self.do_winds()
- self.winds = self.__class__.winds
-
- boarddef.Level.__init__(self,num)
-
- def reset(self, fill=False):
- if fill:
- w = '#'
- f = 0
- else:
- w = ' '
- f = 1
- # map for the walls
- self.wmap = [ [w for x in range(self.WIDTH)] for y in range(self.HEIGHT) ]
- # map of the free cells
- self.fmap = [ [f for x in range(self.WIDTH)] for y in range(self.HEIGHT) ]
-
- def setw(self,x,y,c='#'):
- if x > self.WIDTH-1 or x < 0 or y > self.HEIGHT-1 or y < 0:
- return
- if self.fmap[y][x]:
- self.wmap[y][x] = c
- self.fmap[y][x] = 0
-
- def getw(self,x,y):
- if x > self.WIDTH-1 or x < 0 or y > self.HEIGHT-1 or y < 0:
- return '#'
- return self.wmap[y][x]
-
- def clrw(self,x,y):
- if x > self.WIDTH-1 or x < 0 or y > self.HEIGHT-1 or y < 0:
- return
- self.wmap[y][x] = ' '
- self.fmap[y][x] = 1
-
- def lockw(self,x,y,c=0):
- if x > self.WIDTH-1 or x < 0 or y > self.HEIGHT-1 or y < 0:
- return
- self.fmap[y][x] = c
-
- def setwind(self,x,y,c=' '):
- if x > self.WIDTH-1 or x < 0 or y > self.HEIGHT-1 or y < 0:
- return
- self.windmap[y][x] = c
-
- def getwind(self,x,y):
- if x > self.WIDTH-1 or x < 0 or y > self.HEIGHT-1 or y < 0:
- return ' '
- return self.windmap[y][x]
-
- def wind_rect(self,x,y,w,h,ccw=0):
- "Set a wind in a rectangle which will move the bubbles cw or ccw"
- if w < 1 or h < 1:
- return
- if ccw == 1:
- for dx in range(w):
- self.setwind(x+dx+1, y, '<')
- self.setwind(x+dx, y+h, '>')
- for dy in range(h):
- self.setwind(x, y+dy, 'v')
- self.setwind(x+w, y+dy+1, '^')
- else:
- for dx in range(w):
- self.setwind(x+dx, y, '>')
- self.setwind(x+dx+1, y+h, '<')
- for dy in range(h):
- self.setwind(x, y+dy+1, '^')
- self.setwind(x+w, y+dy, 'v')
-
- def mirror(self):
- "Mirror the level vertically."
- for y in range(self.HEIGHT):
- for x in range(self.WIDTH//2):
- self.wmap[y][x] = self.wmap[y][self.WIDTH-x-1]
-
- def dig_well_until_space(self, x=1, yadj=1):
- "Digs a well either up or down and stops when it encounters first empty wall space."
- if yadj == 1:
- y = 0
- else:
- yadj = -1
- y = self.HEIGHT-1
- while (y < self.HEIGHT) and (y >= 0):
- self.clrw(x,y)
- self.clrw(x+1,y)
- y += yadj
- if ((self.getw(x,y) == ' ') and (self.getw(x+1,y) == ' ')):
- break
-
- def enlarge_tiny_holes(self):
- "Makes one-block size holes wider."
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- if self.wmap[y][x] == ' ':
- single = 0
- for dx in range(x-1,x+2):
- for dy in range(y-1,y+2):
- if self.getw(dy,dx) == '#':
- single = single + 1
- if single == 8:
- if x > (self.WIDTH // 2):
- self.clrw(x-1,y)
- else:
- self.clrw(x+1,y)
-
- def make_space(self, gens=-1):
- "Removes walls from a level, to make it more playable."
- if gens == -1:
- gens = randint(0,62)+1
- if gens & 1: # top
- for x in range(self.WIDTH):
- self.clrw(x,1)
- if random() < 0.5:
- self.clrw(x,2)
- if gens & 2: # bottom
- for x in range(self.WIDTH):
- self.clrw(x,self.HEIGHT-1)
- if random() < 0.5:
- self.clrw(x,self.HEIGHT-2)
- if gens & 4: # middle
- y = randint(0,self.HEIGHT//10) + (self.HEIGHT//2)
- for x in range(self.WIDTH):
- self.clrw(x,y)
- if random() < 0.5:
- self.clrw(x,y-1)
- if random() < 0.5:
- self.clrw(x,y+1)
- if gens & 8: # left
- x = randint(0,self.WIDTH//4)
- self.dig_well_until_space(x, 1)
- self.dig_well_until_space(x, -1)
- if gens & 16: # right
- x = randint(0,self.WIDTH//4)
- self.dig_well_until_space(self.WIDTH-x-2, 1)
- self.dig_well_until_space(self.WIDTH-x-2, -1)
- if gens & 32: # center
- self.dig_well_until_space(self.WIDTH//2, 1)
- self.dig_well_until_space(self.WIDTH//2, -1)
-
- def generate_wind1(self, rndchoice=1, choices=[' ',' ',' ','x','>','<','^','^','v'], xsize=-1,ysize=-1):
- """Makes a random wind pattern. Parameters:
- 0: if 1=randomly select from choices, else select in order
- 1: a list of the choices that are allowed.
- 2: horizontal size of wind blocks
- 3: vertical size of wind blocks
- """
- choicenum = 0
- if xsize == -1:
- xsize = randint(1, self.WIDTH)
- if ysize == -1:
- ysize = randint(1, self.HEIGHT)
- if xsize < 1:
- xsize = 1
- elif xsize > self.WIDTH:
- xsize = self.WIDTH
- if ysize < 1:
- ysize = 1
- elif ysize > self.HEIGHT:
- ysize = self.HEIGHT
- for x in range((self.WIDTH//xsize)+1):
- for y in range((self.HEIGHT//ysize)+1):
- if rndchoice == 1:
- wdir = choice(choices)
- else:
- wdir = choices[choicenum]
- choicenum = (choicenum + 1) % len(choices)
- for dx in range(xsize+1):
- for dy in range(ysize+1):
- self.setwind(x*xsize+dx,y*ysize+dy,wdir)
- # make sure that the special bubbles can come into screen
- for x in range(self.WIDTH):
- self.setwind(x, 0, ' ')
- self.setwind(x, self.HEIGHT-1, ' ')
-
- def wind_sidewalls(self):
- """Make sure the left and side walls have updraft next to them
- """
- for y in range(self.HEIGHT):
- self.setwind(0,y,'^')
- self.setwind(self.WIDTH-1,y,'^')
-
- def wind_wallblocking(self, winddirs):
- """Sets up wind depending on the number of walls around each place.
- winddirs is an array of 16 wind chars.
- directions with walls count as: 1=N, 2=E, 4=S, 8=W
- 16th place is used if there is wall at the position.
- """
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- walld = 0
- if self.getw(x,y) == '#':
- walld = 16
- else:
- if self.getw(x,y-1) == '#':
- walld = walld + 1
- if self.getw(x+1,y) == '#':
- walld = walld + 2
- if self.getw(x,y+1) == '#':
- walld = walld + 4
- if self.getw(x-1,y) == '#':
- walld = walld + 8
- wnd = winddirs[walld]
- self.setwind(x,y,wnd)
-
- def wind_wallblocking256(self, winddirs):
- """Sets up wind depending on the number of walls around each position.
- winddirs is an array of 257 wind chars (one of ' x<>^v-'), where '-' means
- to use '>' or '<', pointing towards center of level.
- directions with walls count as: 1=N, 2=NE, 4=E, 8=SE, 16=S, 32=SW, 64=W, 128=NW
- 257th place is use if there is wall at the position.
- """
- mdirs = [(0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1)]
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- windd = 0
- if self.getw(x,y) == '#':
- windd = 256
- else:
- for d in range(8):
- dx = x + mdirs[d][0]
- dy = y + mdirs[d][1]
- if self.getw(dx, dy) == '#':
- windd = (1 << d)
- wd = choice(winddirs[windd])
- if wd == '-':
- if x < self.WIDTH // 2:
- wd = '>'
- else:
- wd = '<'
- self.setwind(x,y, wd)
-
- def generate_wind(self, gens = -1):
- """Chooses one of the wind pattern generators and uses that to generate the winds.
- 0: choose what generator to use.
- """
- if gens == -1:
- gens = choice([1,1,2,3,4,4,4,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19])
- if gens == 1: # totally random pattern
- self.generate_wind1()
- elif gens == 2: # wind "layers"
- self.generate_wind1(0, ['x','^','^','^'],self.WIDTH,1)
- self.wind_sidewalls()
- elif gens == 3: # "wiggly" winds
- self.generate_wind1(1, ['^','<','^','>'],1,1)
- self.wind_sidewalls()
- elif gens == 4: # "normal" wind pattern
- self.wind_sidewalls()
- dx = (self.WIDTH//2)
- if random() < 0.7:
- dy = 1 # usual height where bubbles collect
- else:
- dy = randint(1, self.HEIGHT-1)
- for x in range(dx-3, dx+3):
- self.setwind(x,dy,'x')
- for x in range(dx-2):
- self.setwind(x,dy,'>')
- self.setwind(self.WIDTH-x-1,dy,'<')
- elif gens == 5: # bubbles are stopped by horizontal walls
- self.wind_sidewalls()
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT-2):
- if self.getw(x,y) == '#':
- if self.getw(x,y+1) == ' ':
- self.setwind(x,y+1,'x')
- elif gens == 6: # bubbles move next the walls, rotating cw or ccw
- if random() < 0.5: #clockwise
- winddirs = [' ','>','v','v','<',' ','<','<','^','>',' ','v','^','>','^','x','x']
- else:
- winddirs = [' ','<','^','<','>',' ','^','<','v','v',' ','v','>','>','^','x','x']
- self.wind_wallblocking(winddirs)
- elif gens == 7: # bubbles move up in column(s) that zig-zag left and right
- wid = choice([self.WIDTH, randint(2, self.WIDTH), randint(2, self.WIDTH)])
- xofs = (self.WIDTH % wid) // 2
- ofs = choice([0,1])
- for dx in range(0, self.WIDTH-wid+1, wid):
- for x in range(wid):
- for y in range(self.HEIGHT):
- if (y+ofs) & 1:
- self.setwind(x+dx+xofs,y,'<')
- if x == 0:
- self.setwind(x+dx+xofs,y,'^')
- else:
- self.setwind(x+dx+xofs,y,'>')
- if x == wid-1:
- self.setwind(x+dx+xofs,y,'^')
- elif gens == 8: # bubbles move towards the map centerline at random height
- for x in range(self.WIDTH):
- y = randint(1, self.HEIGHT-1)
- if x < (self.WIDTH//2):
- self.setwind(x,y,'>')
- else:
- self.setwind(x,y,'<')
- self.setwind(x,0,'v')
- self.setwind(x,self.HEIGHT-1,'^')
- for y in range(self.HEIGHT):
- self.setwind(self.WIDTH//2,y,'x')
- elif gens == 9: # bubbles move towards the side walls at random height
- for x in range(self.WIDTH):
- y = randint(1, self.HEIGHT-1)
- if y & 1:
- self.setwind(x,y,'>')
- else:
- self.setwind(x,y,'<')
- self.setwind(x,0,'v')
- self.setwind(x,self.HEIGHT-1,'^')
- for y in range(self.HEIGHT):
- self.setwind(0,y,'x')
- self.setwind(self.WIDTH-1,y,'x')
- elif gens == 10: # bubbles move up-down
- ofs = choice([0,1])
- dir_l = choice(['>', '>', '<'])
- dir_r = choice(['<', '<', '>'])
- for x in range(self.WIDTH):
- if x < (self.WIDTH // 2):
- self.setwind(x, 0, dir_r)
- self.setwind(x,self.HEIGHT-1,dir_l)
- else:
- self.setwind(x, 0, dir_l)
- self.setwind(x,self.HEIGHT-1,dir_r)
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- if (x+ofs) & 1:
- self.setwind(x,y+1,'^')
- else:
- self.setwind(x,y-1,'v')
- elif gens == 11: # bubbles rotate
- self.wind_sidewalls()
- for z in range(20):
- wid = randint(2,self.WIDTH//2)
- hei = randint(2,self.HEIGHT//2)
- y = randint(1, self.HEIGHT - hei - 1)
- x = randint(1, self.WIDTH - wid - 1)
- ok = 1
- for dx in range(wid):
- if self.getwind(x+dx+1, y) != ' ':
- ok = 0
- if self.getwind(x+dx, y+hei) != ' ':
- ok = 0
- for dy in range(hei):
- if self.getwind(x, y+dy) != ' ':
- ok = 0
- if self.getwind(x+wid, y+dy+1) != ' ':
- ok = 0
- if ok == 1:
- self.wind_rect(x,y,wid,hei, random() < 0.5)
- elif gens == 12: # bubbles gravitate towards a certain spot
- dx = randint(1,self.WIDTH-1)
- dy = randint(1,self.HEIGHT-1)
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- ax = abs(dx - x)
- ay = abs(dy - y)
- sx = cmp(dx - x, 0)
- sy = cmp(dy - y, 0)
- winds = [' ',' ',' ']
- if ax < 2 and ay < 2:
- winds = ['x']
- else:
- if sx < 0:
- winds += ['<']
- elif sx > 0:
- winds += ['>']
- else:
- if sy > 0:
- winds = ['v']
- elif sy < 0:
- winds = ['^']
- else:
- winds = ['x']
- if sy < 0:
- winds += ['^']
- elif sy > 0:
- winds += ['v']
- else:
- if sx > 0:
- winds = ['>']
- elif sx < 0:
- winds = ['<']
- else:
- winds = ['x']
- self.setwind(x,y,choice(winds))
- elif gens == 13: # bubbles stop at some random positions
- self.generate_wind1(1, [' ',' ',' ',' ',' ',' ',' ','x'],1,1)
- self.wind_sidewalls()
- elif gens == 14: # bubbles move cw and ccw in alternating rectangles
- m = max(self.WIDTH // 2, self.HEIGHT // 2)
- cwofs = choice([0,1])
- thk = choice([1,1,2,2,3,4,randint(1,m//2)])
- for dx in range(m):
- cw = ((dx // thk) + cwofs) % 2
- self.wind_rect(dx,dx, self.WIDTH-(dx*2), self.HEIGHT-(dx*2), cw)
- elif gens == 15: # bubbles move cw or ccw in rectangles
- m = max(self.WIDTH // 2, self.HEIGHT // 2)
- cw = choice([0,1])
- for dx in range(m):
- self.wind_rect(dx,dx, self.WIDTH-(dx*2), self.HEIGHT-(dx*2), cw)
- elif gens == 16:
- xs = randint(2, (self.WIDTH//2)-1)
- ys = randint(2, (self.HEIGHT//2)-1)
- rx = (self.WIDTH // xs) + 1
- ry = (self.HEIGHT // ys) + 1
- cwchanges = choice([0,0,0,0,0,0,0,0,1,1,1,1,2,2,3])
- if cwchanges == 0:
- cw = random() < 0.5
- for x in range(rx):
- if cwchanges == 1:
- cw = random() < 0.5
- for y in range(ry):
- if cwchanges == 2:
- cw = random() < 0.5
- maxd = max((xs // 2), (ys // 2))
- for d in range(maxd):
- if cwchanges == 3:
- cw = random() < 0.5
- self.wind_rect(xs*x+d, ys*y+d, xs-2*d-1, ys-2*d-1, cw)
- elif gens == 17: # bubbles bounce between walls
- if random() < 0.5: # horizontal
- winddirs = [' ',' ','<','<',' ',' ','<','<','>','>',' ',' ','>','>',' ',' ','x']
- else: # vertical
- winddirs = [' ','v',' ','v','^',' ','^',' ',' ','v',' ','v','^',' ','^',' ','x']
- self.wind_wallblocking(winddirs)
- elif gens == 18: # generate winds based on a random 3x3 matrix ruleset
- winddirs = []
- for z in range(257):
- winddirs.append(choice([' ',' ',' ','x','^','v','-']))
- winddirs[0] = ' '
- winddirs[256] = choice(['x',' '])
- self.wind_wallblocking256(winddirs)
- elif gens == 19: # bubbles will move downwards in a zig-zag pattern
- y = 0
- x1 = randint(0, self.WIDTH-1)
- while y < self.HEIGHT:
- x2 = randint(0, self.WIDTH-1)
- if x1 < x2:
- self.setwind(x1,y, '>')
- else:
- self.setwind(x1,y, '<')
- dy = choice([1,1,1,2])
- self.setwind(x2,y, 'v')
- y += dy
- x1 = x2
-
- def smooth(self, threshold, rev):
- """Remove wall blocks that are surrounded by 4 empty places.
- 0: probability which a wall cell is turned into space
- 1: smooth away walls or smooth away empty spaces?
- """
- # make a copy of self.wmap and adds '#' at the end of line, for
- # the overflowing indexing below: [x-1] and [x+1]
- tmpwmap = [ line + ['#'] for line in self.wmap ]
- if rev == 0:
- chr = ' '
- else:
- chr = '#'
- for x in range(self.WIDTH):
- for y in range(1,self.HEIGHT-1):
- count = 0
- if tmpwmap[y+1][x] == chr:
- count = count + 1
- if tmpwmap[y-1][x] == chr:
- count = count + 1
- if tmpwmap[y][x+1] == chr:
- count = count + 1
- if tmpwmap[y][x-1] == chr:
- count = count + 1
- if (count >= 4) and (random() < threshold):
- if rev == 0:
- self.clrw(x,y)
- else:
- self.setw(x,y)
-
- def mess(self, threshold):
- """Random fill of the board with walls.
- Only one argument, the probability that
- a cell turns out to be a wall.
- """
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- if random() < threshold:
- self.setw(x,y)
-
- def zigzag_lr(self):
- """Generate the level with random left-right zig-zags.
- """
- first = 1
- self.reset(fill=False)
- y = choice([0,0,2,3,3,4])
- while y < (self.HEIGHT-2):
- if first == 1:
- first = 0
- x1 = x2 = randint(2, self.WIDTH-3)
- else:
- x2 = randint(2, self.WIDTH-3)
- while (x2 > (x1-3)) and (x2 < (x1+3)):
- x2 = randint(2, self.WIDTH-3)
- for dx in range(min(x1,x2+1), max(x1,x2+1)):
- self.setw(dx,y)
- dy = choice([2,2,3,3,3,4])
- for dy in range(dy+1):
- self.setw(x2,y+dy)
- y = y + dy
- x1 = x2
-
- def zigzag_ud(self):
- """Generate the level with random up-down zig-zags.
- """
- first = 1
- self.reset(fill=False)
- x = -1
- while x < self.WIDTH:
- if first == 1:
- first = 0
- y1 = y2 = randint(2, self.HEIGHT-1)
- else:
- y2 = randint(2, self.HEIGHT-1)
- while (y2 > (y1-2)) and (y2 < (y1+2)):
- y2 = randint(2, self.HEIGHT-1)
- for dy in range(min(y1,y2+1), max(y1,y2+1)):
- self.setw(x,dy)
- dx = choice([3,4,4,4,5,6])
- for dx in range(dx+1):
- self.setw(x+dx,y2)
- x = x + dx
- y1 = y2
-
- def zigzag(self):
- """Generate a level with a random zig-zag form.
- """
- if random() < 0.5:
- self.zigzag_lr()
- else:
- self.zigzag_ud()
-
- def platforms(self, xxx_todo_changeme, xxx_todo_changeme1, full=1):
- """Place random platforms.
- args is a tuple with the following fields:
- 0: a tuple containing the number of platforms and
- the minum space between two platforms,
- 1: a tuple indicating in order:
- - the rng for the number of holes per platform
- - the rng for the width of the holes,
- 2: a flag indicating whether the platform should cross
- the whole level or not.
- """
- (nplat, space) = xxx_todo_changeme
- (rng_holes, rng_width) = xxx_todo_changeme1
- plat = []
- for i in range(nplat):
- ntry = 100
- while ntry:
- y = randint(0,self.HEIGHT-1)
- found = 0
- for old in plat:
- if abs(old-y) <= space:
- found = 1
- break
- if not found:
- plat.append(y)
- break
- ntry -= 1
- if not ntry:
- continue # ignore platform
- if full:
- x = 0
- w = self.WIDTH
- else:
- x = randint(0,self.WIDTH-1)
- w = randint(0,self.WIDTH-1)
- s = choice([-1,1])
- if s == -1:
- w = min(w,x)
- x -= w
- else:
- w = min(w,self.WIDTH-x)
- for x1 in range(x,x+w):
- self.setw(x1,y)
- for i in range(rng_holes()):
- hx = randint(x,x+w)
- hw = rng_width()
- for h in range(hx-hw//2,hx+hw//2):
- self.clrw(h,y)
-
- def remove_joined_blocks(self):
- """Removes randomly placed, random sized blocks of walls.
- The blocks are usually joined, or if not, they're offset so that
- it's possible to move from one block to another by jumping.
- """
- self.reset(fill=True)
- nrooms = randint(1, 4)
- while nrooms:
- nrooms -= 1;
- x = 0
- while x < self.WIDTH:
- wid = randint(2,8)
- hei = randint(2,6)
- y = randint(2, self.HEIGHT - hei - 1)
- for dx in range(wid):
- for dy in range(hei):
- self.clrw(x+dx, y+dy)
- x += wid + choice([-2,-2,-1,-1,0]);
-
- def discrete_blocks(self, blocks = -1):
- """Put certain size blocks randomly, but so that they don't touch each other.
- """
- self.reset(fill=False)
- if blocks == -1:
- if random() < 0.75:
- blocks = [(4,2),(2,4)] # CompactLevels, level 16
- if random() < 0.30:
- blocks.append((2,2))
- if random() < 0.20:
- blocks.append((6,2))
- if random() < 0.10:
- blocks.append((8,2))
- else:
- blocks = []
- while len(blocks) == 0:
- for bz in range(10):
- if random() < 0.3:
- blocks.append((bz+1,1))
- ntry = 300
- while ntry:
- ntry -= 1
- doput = 1
- block = choice(blocks)
- wid = block[0]
- hei = block[1]
- x = randint(0,self.WIDTH-wid-2)
- y = randint(1,self.HEIGHT-hei-3)
- for dx in range(x,x+wid+2):
- for dy in range(y,y+hei+2):
- if self.getw(dx,dy) == '#':
- doput = 0
- if doput:
- for dx in range(x+1,x+wid+1):
- for dy in range(y+1,y+hei+1):
- self.setw(dx,dy)
-
- def lines(self, rng_len, nlines, rng_angle=None):
- """Generate a set of lines in any direction. It takes three
- arguments, a rng for the length the lines, the number of lines,
- and a rng for the angle.
- """
- if rng_angle is None:
- rng_angle = lambda : choice([0]+[pi/i for i in range(3,21)]+[-pi/i for i in range(3,21)])
- for i in range(nlines):
- len = rng_len()
- angle = rng_angle()
- ntry = self.MAXTRY
- while ntry:
- sx = randint(0,self.WIDTH-1)
- sy = randint(0,self.HEIGHT-1)
- dx = int(sx + len*cos(angle) + 0.5)
- dy = int(sy + len*sin(angle) + 0.5)
- if dx < self.WIDTH and dy < self.HEIGHT and dx >= 0 and dy >= 0:
- break
- ntry -= 1
- if ntry == 0:
- break
- if abs(dx-sx) > abs(dy-sy):
- for x in range(dx-sx+1):
- y = (2*(dy-sy)*x//(dx-sx)+1)//2
- self.setw(sx+x,sy+y)
- else:
- for y in range(dy-sy+1):
- x = (2*(dx-sx)*y//(dy-sy)+1)//2
- self.setw(sx+x,sy+y)
-
- def rooms(self, rng_radius, rng_e, n_rooms):
- """Generate rooms. It takes the following arguments:
- 0: the rng for the radius of the room
- 1: the rng for the excentricity of the room
- 2: the number of rooms
- """
- for i in range(n_rooms):
- cx = randint(0,self.WIDTH-1)
- cy = randint(0,self.HEIGHT-1)
- r = rng_radius()
- e = rng_e()*1.0
- left = cx-int(r*e+0.5)
- right = cx+int(r*e+0.5)
- top = cy-int(r/e+0.5)
- bottom = cy+int(r/e+0.5)
- for x in range(left,right+1):
- self.setw(x,top)
- self.setw(x,bottom)
- for y in range(top,bottom+1):
- self.setw(left,y)
- self.setw(right,y)
- for x in range(left+1,right):
- for y in range(top+1,bottom):
- self.lockw(x,y)
-
- def holes(self, rng_radius, rng_e, n_holes, rng_rect):
- """Generate a set of holes in the level. It takes four args:
- 0: the rng for the radius of the holes
- 1: the rng for the excentricity of the holes
- 2: the number of holes
- 3: the rng for the shape of the hole 0 for circular, 1 for rectangular
- """
- for i in range(n_holes):
- cx = randint(0,self.WIDTH-1)
- cy = randint(0,self.HEIGHT-1)
- r = rng_radius()
- e = rng_e()*1.0
- rect = rng_rect()
- for x in range(cx-int(r*e+0.5),cx+int(r*e+0.5)+1):
- for y in range(cy-int(r/e+0.5),cy+int(r/e+0.5)+1):
- if not rect and (((x-cx)/e)**2+((y-cy)*e)**2) > r**2:
- continue
- self.clrw(x,y)
-
- def grids(self, horizchance, vertchance):
- """Generate a level with a grid of horizontal and vertical lines
- 0: gaussian chance of each horizontal line part
- 1: gaussian chance of each vertical line part
- """
- self.reset(fill=False)
- xsize = choice([3,3,3,4,4,4,4,5,6])
- ysize = choice([2,3,3,4,4,4,4,5])
- xofs = choice([-1,0,1])
- yofs = choice([-1,0,1])
- for x in range((self.WIDTH//xsize)+1):
- for y in range((self.HEIGHT//ysize)+1):
- dx = x*xsize + xofs
- dy = y*ysize + yofs
- if gauss(0,1) > horizchance:
- for i in range(0,xsize+1):
- self.setw(dx+i,dy)
- if gauss(0,1) > vertchance:
- for i in range(0,ysize+1):
- self.setw(dx,dy+i)
-
- def pegs(self, pegchance, posadj, thick):
- """Generate a level by putting pegs
- 0: gaussian level of a peg appearance
- 1: gaussian level of peg position adjustment
- """
- self.reset(fill=False)
- xdist = choice([3,3,3,4,4,5]) # distance between pegs
- ydist = choice([2,3,3,3,4,5]) # distance between pegs
- if not thick:
- xdist = xdist - randint(0,1)
- ydist = ydist - randint(0,1)
- xadj = randint(0,4) - 2
- yadj = randint(0,4) - 2
- for x in range(self.WIDTH // xdist):
- for y in range(self.HEIGHT // ydist):
- if gauss(0,1) > pegchance:
- dx = x * xdist + xadj
- dy = y * ydist + yadj
- if gauss(0,1) > posadj:
- dx = dx + randint(0,2) - 1
- dy = dy + randint(0,2) - 1
- self.setw(dx,dy)
- if thick:
- self.setw(dx+1,dy)
- self.setw(dx,dy+1)
- self.setw(dx+1,dy+1)
-
- def mondrian(self, x1=2,y1=2,x2=-1,y2=-1, horiz=-1, mindepth=3):
- """Generate a level that looks a bit like a Piet Mondrian painting, or
- different sized rectangles stacked on top of each other.
- 0-3: the size of the area to be split
- 4: whether the first split is horizontal or vertical
- 5: minimum number of splits to do
- """
- if horiz == -1:
- horiz = choice([0,1])
- if x2 == -1:
- x2 = self.WIDTH-2
- if y2 == -1:
- y2 = self.HEIGHT-2
- if (abs(x2-x1) < 6) or (abs(y2-y1) < 5):
- return
- mindepth = mindepth - 1
- if horiz == 1:
- horiz = 0
- dy = randint(y1+2,y2-2)
- for dx in range(min(x1,x2),max(x1,x2)):
- self.setw(dx,dy)
- if (random() < 0.75) or (mindepth > 0):
- self.mondrian(x1,y1,x2,dy, horiz, mindepth)
- if (random() < 0.75) or (mindepth > 0):
- self.mondrian(x1,dy,x2,y2, horiz, mindepth)
- else:
- horiz = 1
- dx = randint(x1+3,x2-3)
- for dy in range(min(y1,y2),max(y1,y2)):
- self.setw(dx,dy)
- if (random() < 0.75) or (mindepth > 0):
- self.mondrian(x1,y1,dx,y2, horiz, mindepth)
- if (random() < 0.75) or (mindepth > 0):
- self.mondrian(dx,y1,x2,y2, horiz, mindepth)
-
- def bouncers(self, length, diradj, rev):
- """Generate a level using a down and left or right moving walker
- 0: how many steps does the walker take
- 1: gaussian level, how often to change moving from left to right
- 2: fill empty level with wall or reverse?
- """
- if rev == 0:
- self.reset(fill=True)
- else:
- self.reset(fill=False)
- x = randint(0,self.WIDTH-2)
- y = randint(0,self.HEIGHT-2)
- lorr = choice([1, -1]) # move left or right
- for i in range(length):
- if rev == 0:
- self.clrw(x,y)
- self.clrw(x+1,y)
- self.clrw(x,y+1)
- self.clrw(x+1,y+1)
- else:
- self.setw(x,y)
- self.setw(x+1,y)
- x = x + lorr
- y = y + 1
- if y > self.HEIGHT:
- y = 0
- if x > self.WIDTH - 2:
- x = self.WIDTH - 2
- lorr = -lorr
- elif x < 0:
- x = 0
- lorr = -lorr
- if gauss(0,1) > diradj:
- lorr = -lorr
-
-
- def walkers(self, length, minturn, maxturn, isbig):
- """Generate a level with a walker
- 0: length of the walker: how many steps it walks
- 1: minimum length it walks straight, before turning
- 2: maximum length it walks straight, before turning
- 3: is the trail is 1 or 2 blocks high
- """
- # We start from a full wall
- self.reset(fill=True)
- x = randint(0,self.WIDTH-2)
- y = randint(0,self.HEIGHT-2)
- dir = randint(0,4)
- dlen = 0
- for i in range(length):
- self.clrw(x,y)
- self.clrw(x+1,y)
- if isbig == 1:
- self.clrw(x,y+1)
- self.clrw(x+1,y+1)
- dlen = dlen + 1
- if dir == 0:
- x = x - 2
- if x < 0:
- x = self.WIDTH-2
- elif dir == 1:
- y = y - 1
- if y < 0:
- y = self.HEIGHT
- elif dir == 2:
- x = x + 2
- if x > (self.WIDTH - 2):
- x = 0
- else:
- y = y + 1
- if y > self.HEIGHT:
- y = 0
- if dlen > randint(minturn, maxturn):
- # turn 90 degrees
- dir = (dir + choice([1,3])) % 4
- dlen = 0
-
- def rivers(self, n_flow, side_threshold, side_shift):
- """Generate flow paths by digging a big wall. The arguments are:
- 0: the number of parallel flow to dig in the wall
- 1: side_threshold is a gausian level for doing a step aside
- 2: side_shift is the maximal size of the side step.
- """
- # We start from a full wall
- self.reset(fill=True)
- for x in [0, self.WIDTH-2]+[randint(3,self.WIDTH-5) for f in range(max(0, n_flow-2))]:
- for y in range(self.HEIGHT):
- self.clrw(x,y)
- self.clrw(x+1,y)
- g = gauss(0,1)
- if abs(g) > side_threshold:
- # We want to move aside, let's find which side is the best:
- if self.WIDTH//4 < x < 3*self.WIDTH//4:
- side = random() > 0.5
- t = random()
- if t > x*4/self.WIDTH:
- side = 1
- elif t > (self.WIDTH-x)*4/self.WIDTH:
- side = -1
- side_step = randint(1,side_shift)
- if side > 0:
- for i in range(x+2, min(x+2+side_step,self.WIDTH-1)):
- self.clrw(i,y)
- x = max(0,min(x+side_step, self.WIDTH-2))
- else:
- for i in range(max(x-side_step,0),x):
- self.clrw(i,y)
- x = max(x-side_step, 0)
-
- def platforms_reg(self):
- """Generate random platforms at regular y-intervals.
- """
- self.reset(fill=False)
- yadjs = [-2,-1,0,0,0,0,0,0,0,0,1,2]
- y = randint(2,4)
- yinc = randint(2,6)
- yincadj = choice(yadjs)
- ymax = self.HEIGHT-choice([1,1,1,1,1,2,2,2,3,3,4])-1
- while y < ymax:
- holes = randint(choice([0,1,1,1,1]),7)
- for x in range(0, self.WIDTH):
- self.setw(x,y)
- for i in range(holes):
- x = randint(0, self.WIDTH-2)
- self.clrw(x,y)
- self.clrw(x+1,y)
- y = y + yinc
- yinc = yinc + yincadj
- if yinc < 2:
- yinc = 2
- yincadj = choice(yadjs)
- if yinc > 6:
- yinc = 6
- yincadj = choice(yadjs)
-
- def startplatform(self):
- "Make sure there's free space with wall underneath for dragon start positions"
- hei = choice([1,1,1,2,2,3])
- lft = choice([0,1])
- wid = choice([3,3,3,4,5])
- for x in range(lft, wid):
- self.setw(x,self.HEIGHT-1)
- self.setw(self.WIDTH-x-1,self.HEIGHT-1)
- for y in range(hei+1):
- self.clrw(x,self.HEIGHT-2-y)
- self.clrw(self.WIDTH-x-1,self.HEIGHT-2-y)
-
- def openstartway(self):
- "Make sure there is a way from the starting position to the center of the level. Reduces player frustrations."
- gen = choice([0,0,0,1])
- if gen == 0: # horizontal open space to middle of level
- ypos = choice([1,1,1,1,1,2,2,3,4,randint(1,self.HEIGHT//2)])
- hei = choice([1,1,1,2])
- for x in range(self.WIDTH//2):
- for y in range(hei):
- self.clrw(x, self.HEIGHT-1-ypos-y)
- ypos = choice([1,1,1,1,1,2,2,3,4,randint(1,self.HEIGHT//2)])
- hei = choice([1,1,1,2])
- for x in range(self.WIDTH//2):
- for y in range(hei):
- self.clrw(self.WIDTH-x-1, self.HEIGHT-1-ypos-y)
- elif gen == 1: # open way diagonally to NW or NS, third of a way to the level width
- ypos = choice([1,1,1,1,1,2,2,3,4])
- wid = choice([2,2,2,2,2,3,3,4])
- for x in range(self.WIDTH//3):
- for z in range(wid):
- self.clrw(x+z, self.HEIGHT-1-x-ypos)
- ypos = choice([1,1,1,1,1,2,2,3,4])
- wid = choice([2,2,2,2,2,3,3,4])
- for x in range(self.WIDTH//2):
- for z in range(wid):
- self.clrw(self.WIDTH-x-1-z, self.HEIGHT-1-x-ypos)
-
- def close(self):
- "Just close the level with floor and roof"
- for x in range(self.WIDTH):
- self.setw(x,0)
- self.setw(x,self.HEIGHT)
-
- def largest_vertical_hole(self, x):
- "Returns the (start, stop) of the largest range of holes in column x."
- if not (0 <= x < self.WIDTH):
- return (0, 0)
- ranges = []
- best = 0
- length = 0
- for y in range(self.HEIGHT+1):
- if y < self.HEIGHT and self.getw(x,y) == ' ':
- length += 1
- elif length > 0:
- if length > best:
- del ranges[:]
- best = length
- if length == best:
- ranges.append((y-length, y))
- length = 0
- return choice(ranges or [(0, 0)])
-
- def dig_vertical_walls(self):
- "Check that no vertical wall spans the whole height of the level"
- vwall = []
- for x in range(self.WIDTH):
- spaces = 0
- for y in range(self.HEIGHT-1): # ignore bottom line spaces
- spaces += self.getw(x,y) == ' '
- if spaces == 0 or (random() < 0.4**spaces):
- vwall.append(x)
- shuffle(vwall)
- for x in vwall:
- # look for the longest continuous space in each of the two
- # adjacent columns, and extend these to the current column
- def dig(y1, y2):
- for y in range(y1, y2):
- self.clrw(x, y)
- return y1 < y2 and y1 < self.HEIGHT-1
- progress = False
- for col in [x-1, x+1]:
- y1, y2 = self.largest_vertical_hole(col)
- progress |= dig(y1, y2)
- while not progress:
- progress |= dig(randint(0, self.HEIGHT-1),
- randint(0, self.HEIGHT-1))
-
- def prevent_straight_fall(self):
- """Make platforms that prevent falling straight from top to bottom, but
- still leave space for moving.
- """
- falls = []
- for x in range(self.WIDTH):
- for y in range(self.HEIGHT):
- if self.getw(x,y) == '#':
- break
- else:
- falls = falls + [x]
- y = oldy = -10
- for x in falls:
- while (y < oldy+2) and (y > oldy-2):
- y = randint(2, self.HEIGHT-2)
- for dy in range(y-1,y+2):
- for dx in range(x-3, x+4):
- self.clrw(dx,dy)
- self.setw(x-1,y)
- self.setw(x+1,y)
- self.setw(x,y)
- oldy = y
-
- def do_monsters(self):
- """Create monsters based on the requested settings.
- mlist is a list of monster setting. Each item is a tuple with:
- 0: the list of monster to uses (each item might be a tuple)
- 1: the rng for the number of monsters to pick in the list.
- """
- current = 'a'
- for ms in self.mlist:
- n_monsters = ms[1]()
- for idx in range(n_monsters):
- setattr(self,current,choice(ms[0]))
- # self.__class__.__dict__[current] = choice(ms[0])
- ntry = self.MAXTRY
- while ntry:
- x = randint(0,self.WIDTH-2)
- y = randint(0,self.HEIGHT-1)
-
- if self.getw(x,y) == self.getw(x+1,y) == ' ':
- self.wmap[y][x] = current
- break
- ntry -= 1
- current = chr(ord(current)+1)
-
- def do_walls(self):
- "Build the actual walls map for the game."
- self.__class__.walls = ''
- for y in range(self.HEIGHT-1):
- self.__class__.walls += '##'
- for x in range(self.WIDTH):
- self.__class__.walls += self.wmap[y][x]
- self.__class__.walls += '##\n'
- self.__class__.walls += '##'
- for x in range(self.WIDTH):
- if self.getw(x,0) == '#' or self.getw(x,self.HEIGHT-1) == '#':
- self.__class__.walls += '#'
- else:
- self.__class__.walls += ' '
- self.__class__.walls += '##\n'
-
- def do_winds(self):
- "Build the actual wind map for the game."
- self.__class__.winds = ''
- for y in range(self.HEIGHT):
- self.__class__.winds += '>>'
- for x in range(self.WIDTH):
- self.__class__.winds += self.windmap[y][x]
- self.__class__.winds += '<<' + '\n'
-
- def do_bonuses(self):
- self.__class__.letter = choice([0,1])
- self.__class__.fire = choice([0,1])
- self.__class__.lightning = choice([0,1])
- self.__class__.water = choice([0,1])
- self.__class__.top = choice([0,1])
-
- def generate(self):
- "Generate random level settings."
- assert 0, "--- THIS IS NO LONGER REALLY USED ---"
- self.mlist = [([
- LNasty, LMonky, LGhosty, LFlappy, LSpringy, LOrcy, LGramy, LBlitzy,
- RNasty, RMonky, RGhosty, RFlappy, RSpringy, ROrcy, RGramy, RBlitzy,
- ],lambda : flat(12,4))]
- gens = choice([512,512,256,256,128,128,64,64,32,32,16,16,16,16,16,16,20,20,8,8,8,8,4,4,4,4,2,2,2,2,1,1,3,5,6,7])
- self.genwalls = []
- if gens & 512:
- print('Using grids generator')
- self.genwalls.append((RandomLevel.grids,
- uniform(0.0, 0.1),
- uniform(0.0, 0.1)))
- if gens & 256:
- # generate using pegs
- print('Using the pegs generator')
- self.genwalls.append((RandomLevel.pegs,
- uniform(0.1,0.2),
- uniform(0.45,0.7),
- choice([0,1,1,1])))
- if gens & 128:
- # generate using a bouncer
- nr = choice([0,0,1])
- print('Using the bouncer generator')
- self.genwalls.append((RandomLevel.bouncers,
- dice(1, 100) + 250 - nr*200, # length
- uniform(0.7, 1.7),
- nr))
- if gens & 64:
- # generate using a walker
- print('Using the walker generator')
- nr = dice(1, 3) + 2
- self.genwalls.append((RandomLevel.walkers,
- dice(2, 100) + 100, # length
- nr, nr + dice(2, 3), # straight walk min, max len
- choice([0,1])))
- if gens & 32:
- # generate rivers
- print('Using the rivers generator')
- self.genwalls.append((RandomLevel.rivers,
- randrange(2,(self.WIDTH-4)/5), # the number of rivers
- uniform(0.7, 1.7), # the side stepping threshold
- 6)) # the max side stepping size
- if gens & 16:
- # generate rooms
- print('Using the romms generator')
- nr = choice([1,2,2,2,3,3,4,5])
- self.genwalls.append((RandomLevel.rooms,
- lambda : flat(9-nr,2), # the half size of the room
- lambda : uniform(0.8,1.2), # the excentricity of the room
- nr)) # the number of rooms
- if gens & 8:
- # generate a holes generator
- # as this is interesting only if the level is filled somehow
- print('Using the holes generator')
- self.genwalls.append((RandomLevel.mess,1-uniform(0.2,0.5)))
- nh = choice([1,1,2,2,2,3,3,3,4,5])
- self.genwalls.append((RandomLevel.holes,
- lambda : flat(9-nh,2), # radius of the holes
- lambda : uniform(0.9,1.1), # excentricity
- nh, # number of holes
- lambda : choice([0,0,0,1]))) # circle or rectangle
- if gens & 4:
- # generate a lines generator
- print('Using the lines generator')
- self.genwalls.append((RandomLevel.lines,
- lambda : dice(7,3), # line length
- dice(2,3))) # number of lines
- if gens & 2:
- # generate a platforms generator
- print('Using the platforms generator')
- nplat = dice(2,4,0)
- if nplat: space = flat((self.HEIGHT-1)/nplat/2,(self.HEIGHT-1)/nplat/2-1)
- else: space = 1
- nholes = lambda : dice(1,3,0)
- wholes = lambda : dice(2,3)
- full = randrange(2)
- self.genwalls.append((RandomLevel.platforms,
- (nplat,space), # number of platform and spacing
- (nholes,wholes), # number of holes and width
- full)) # full width platform
- if gens & 1:
- # generate a mess generator
- print('Using the mess generator')
- if gens & ~2:
- offset = 0
- scale = 0.05
- else:
- offset = 0.05
- scale = 0.10
- self.genwalls.append((RandomLevel.mess,offset+random()*scale))
- if random() < 0.2:
- self.genwalls.append((RandomLevel.close,))
- if random() < 0.90:
- self.genwalls.append((RandomLevel.startplatform,))
- self.genwalls.append((RandomLevel.generate_wind, ))
-
-
-Levels = []
-for i in range(25):
- class level(RandomLevel):
- auto = 1
- Levels.append(level)
-
-class levelfinal(RandomLevel):
- genwalls = [(RandomLevel.platforms,(4,3),(lambda:flat(1,1),lambda:flat(4,2)),1)]
-Levels.append(levelfinal)