mirror of
https://github.com/abakh/nbsdgames
synced 2025-05-24 16:59:33 -04:00
1277 lines
45 KiB
Plaintext
1277 lines
45 KiB
Plaintext
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 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, (nplat, space), (rng_holes, rng_width), 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.
|
|
"""
|
|
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):
|
|
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)
|