Sokoban/logic/generate.py
2021-03-23 15:38:37 +01:00

197 lines
5.8 KiB
Python

from random import randrange as r
import map.air
import map.box
import map.dot
import map.player
import map.wall
class Generate:
"""Declaring variables that will be used several times in the Generate class"""
grid = []
coordb = {}
coordh = {}
coordp = {}
size = 0
@classmethod
def base(cls,minsize,maxsize):
"""Create an empty grid"""
cls.grid = []
cls.coordb = {}
cls.coordh = {}
cls.coordp = {}
cls.size = r(minsize,maxsize+1)
for i in range(cls.size):
cls.grid.append([])
for i in range(cls.size):
cls.grid[0].insert(i,map.wall.Wall._character)
cls.grid[cls.size-1].insert(i,map.wall.Wall._character)
for i in range(1,cls.size-1):
for z in range(1,cls.size-1):
cls.grid[i].insert(z,map.air.Air._character)
for i in range(1,cls.size-1):
cls.grid[i].insert(0,map.wall.Wall._character)
cls.grid[i].insert(cls.size-1,map.wall.Wall._character)
@classmethod
def fill(cls,difficulty,minb,maxb):
"""Fill the empty grid created above with randoms probabilities"""
holes = 0
boxes = r(minb,maxb+1)
size = len(cls.grid)
x = r(2,size-3)
y = r(2,size-3)
cls.grid[x][y] = map.player.Player._character
cls.coordp["player"] = [x,y]
if size%2 == 0:
wall = size/2
else:
wall = (size-1)/2
wall = wall*difficulty
while wall != 0:
x = r(1,size-1)
y = r(1,size-1)
if cls.grid[x][y] != map.player.Player._character:
cls.grid[x][y] = map.wall.Wall._character
wall -= 1
cpt = 0
while boxes != 0:
x = r(2,size-3)
y = r(2,size-3)
if cls.grid[x][y] != map.player.Player._character and cls.grid[x][y] != map.wall.Wall._character:
cls.grid[x][y] = map.box.Box._character
cpt +=1
cls.dicFill(x,y,cpt,2)
boxes -= 1
holes += 1
cpt = 0
while holes != 0:
x = r(2,size-3)
y = r(2,size-3)
if cls.grid[x][y] != map.player.Player._character and cls.grid[x][y] != map.wall.Wall._character and cls.grid[x][y] != map.box.Box._character:
cls.grid[x][y] = map.dot.Dot._character
cpt += 1
cls.dicFill(x,y,cpt,3)
holes -= 1
@classmethod
def dicFill(cls,x,y,cpt,a):
"""Fill the boxes and holes dictionnaries (easier to get their positions after)"""
if a == 2:
box = 'box'+str(cpt)
cls.coordb[box] = [x,y]
if a == 3:
hole = 'hole'+str(cpt)
cls.coordh[hole] = [x,y]
@classmethod
def verify(cls,minb):
"""Check if the grid is playable"""
cptb = 0
cpth = 0
cptp = 0
for i in range(len(cls.grid)):
for y in range(len(cls.grid)):
if cls.grid[i][y] == map.box.Box._character:
cptb += 1
if cls.grid[i][y] == map.dot.Dot._character:
cpth += 1
if cls.grid[i][y] == map.player.Player._character:
cptp += 1
if cptp != 1:
return False
if cpth != cptb:
return False
if minb > cptb:
return False
if cls.verifAround(map.wall.Wall._character,cls.coordb) == False:
return False
if cls.verifAround(map.wall.Wall._character,cls.coordb,2) == False:
return False
if cls.verifAround(map.wall.Wall._character,cls.coordh) == False:
return False
if cls.verifAround(map.wall.Wall._character,cls.coordp) == False:
return False
cls.verifAir()
return True
@classmethod
def verifAir(cls):
"""Check if there's an air place surrounded by walls"""
for x in range(len(cls.grid)):
for y in range(len(cls.grid[x])):
if cls.grid[x][y] == map.air.Air._character:
cpt = 0
if cls.grid[x][y+1] == map.wall.Wall._character:
cpt += 1
if cls.grid[x][y-1] == map.wall.Wall._character:
cpt += 1
if cls.grid[x+1][y] == map.wall.Wall._character:
cpt += 1
if cls.grid[x-1][y] == map.wall.Wall._character:
cpt += 1
if cpt == 4:
cls.grid[x][y] = map.wall.Wall._character
@classmethod
def verifAround(cls,char,d,rng=1):
"""Check if a box or a hole is surrounded by walls"""
cpt = 0
for i in d.values():
x = i[0]
y = i[1]
if cls.grid[x][y+rng] == char:
cpt += 1
if cls.grid[x][y-rng] == char:
cpt += 1
if cls.grid[x+rng][y] == char:
cpt += 1
if cls.grid[x+rng][y+rng] == char:
cpt += 1
if cls.grid[x+rng][y-rng] == char:
cpt += 1
if cls.grid[x-rng][y] == char:
cpt += 1
if cls.grid[x-rng][y+rng] == char:
cpt += 1
if cls.grid[x-rng][y-rng] == char:
cpt += 1
if cpt > 1 :
return False
return True
@classmethod
def gridGen(cls,minsize,maxsize,minb,maxb,difficulty):
"""The main function of the class which return a random generated grid"""
c = False
while c == False:
cls.base(minsize,maxsize)
cls.fill(difficulty,minb,maxb)
c = cls.verify(minb)
return cls.grid