1. import sys, pygame, math, random
  2.  
  3. from pygame.locals import *
  4. pygame.init()
  5.  
  6. #random_seed = 238572983412674123
  7. #random.seed(random_seed)
  8.  
  9. #people, houses
  10.  
  11.  
  12. hmap = []
  13. for i in range(100):
  14.     hmap.append(0)
  15.  
  16. br, bcr = [0, 42], [ [0, 0, 100], [0, 0, 255] ] #water colour range for height map
  17. sr, scr = [42, 45], [ [255, 204, 51], [255, 225, 80] ] #sand colour range for height map
  18. gr, gcr = [45, 55], [ [0, 240, 0], [0, 200, 0] ] #grass colour range for height map
  19. tr, tcr = [55, 64], [ [0, 160, 0], [0, 100, 0] ] #tree colour range for height map
  20. rr, rcr = [64, 100], [ [150,150,150], [255, 255, 255] ] #mountain/rock/snow colour range for height map
  21.  
  22. rs = [ [br, bcr], [sr, scr], [gr, gcr], [tr, tcr], [rr, rcr] ]
  23.  
  24. for i in range(100):
  25.     for j in range(len(rs)):
  26.         r, c = rs[j][0], rs[j][1]
  27.         if i >= r[0] and i < r[1]:
  28.             c1, c2 = c[0], c[1]
  29.             per = ( (i-r[0])/(r[1]-r[0]) )
  30.             rgb = [ c1[0] + ( (c2[0]-c1[0]) * per),
  31.                     c1[1] + ( (c2[1]-c1[1]) * per),
  32.                     c1[2] + ( (c2[2]-c1[2]) * per) ]
  33.             hmap[i] = rgb
  34.            
  35. width, height = 300, 300
  36. scale = 3
  37. maps = [1, 1]
  38.  
  39. dimensions = (width*scale*maps[0], height*scale*maps[1])
  40.  
  41. screen = pygame.display.set_mode(dimensions)
  42.  
  43. mapImg = pygame.Surface(dimensions)
  44. overlay = pygame.Surface(dimensions).convert_alpha()
  45. overlay.fill( (0,0,0,0) )
  46.  
  47. sky = pygame.Surface((width*scale, height*scale)).convert_alpha()
  48. sky.fill( (0,0,0,0) )
  49.  
  50. def drawScreen():
  51.     screen.blit(mapImg, (0, 0))
  52.     screen.blit(overlay, (0, 0))
  53.     screen.blit(sky, (0, 0))
  54.     pygame.display.flip()
  55.  
  56. def isValid(x, y):
  57.     if x >= 0 and x < width*maps[0] and y >= 0 and y < height*maps[1]:
  58.         return True
  59.     return False
  60.  
  61. bordersOn = True
  62. border = [0, 0, 0]
  63. borderDiff = 0
  64. def drawPixel(target, x, y, col, borders, lighting):
  65.     xf, yf = x*scale, y*scale
  66.     xt, yt = (x*scale)+scale, (y*scale)+scale
  67.    
  68.     for rx in range(xf, xt):
  69.         for ry in range(yf, yt):
  70.             tcol = col
  71.             border = [col[0]-100, col[1]-100, col[2]-100]
  72.             if bordersOn and (col[0] > 0 or col[1] > 0):
  73.                 if (rx == xf and borders[3]): #West (Left)
  74.                     tcol = border
  75.                 elif (rx == xt-1 and borders[1]): #East (Right)
  76.                     tcol = border
  77.                 elif (ry == yf and borders[0]): #North (Up)
  78.                     tcol = border
  79.                 elif (ry == yt-1 and borders[2]): #South (Down)
  80.                     tcol = border
  81.  
  82.             for i in range(len(tcol)):
  83.                 if tcol[i] > 255:
  84.                     tcol[i] = 255
  85.                 elif tcol[i] < 0:
  86.                     tcol[i] = 0
  87.                    
  88.             target.set_at((rx, ry), tcol)
  89.  
  90. def getBorders(x, y, rdiff):
  91.     borders = [False, False, False, False] #North, East, South, West
  92.     if isValid(x, y):
  93.         h = wmap[x][y][0]
  94.         col = hmap[h]
  95.  
  96.         for o in range(-1, 2, 2):
  97.             ps = [ [x+o, y], [x, y+o] ]
  98.             for i in range(len(ps)):
  99.                 p = ps[i]
  100.  
  101.                 if isValid(p[0], p[1]):
  102.                    
  103.                     col2 = hmap[wmap[p[0]][p[1]][0]]
  104.                     diff = math.fabs(col[0]-col2[0]) + math.fabs(col[1]-col2[1]) + math.fabs(col[2]-col2[2])
  105.                     if diff > rdiff and bordersOn:
  106.                         if p[0] < x: #West
  107.                             borders[3] = False
  108.                         elif p[0] > x: #East
  109.                             borders[1] = True
  110.                         elif p[1] < y: #North
  111.                             borders[0] = False
  112.                         elif p[1] > y: #South
  113.                             borders[2] = True
  114.     return borders
  115.  
  116. wmap = []
  117.  
  118. for x in range(width*maps[0]):
  119.     tab = []
  120.     for y in range(height*maps[1]):
  121.         h = random.randint(0,99)
  122.        
  123.         tab.append([h, 0])
  124.     wmap.append(tab)
  125.  
  126. def getDist(x1, y1, x2, y2):
  127.     return math.sqrt( ((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)) )
  128.  
  129. smooth = 3
  130. sharp = 1
  131. def smoothmapImg():
  132.     for x in range(width*scale):
  133.         for y in range(height*scale):
  134.             col = mapImg.get_at((x, y))
  135.             col = [col[0]*sharp, col[1]*sharp, col[2]*sharp]
  136.             n = sharp
  137.             for ox in range(-smooth, smooth+1):
  138.                 for oy in range(-smooth, smooth+1):
  139.                     if (x+ox) >= 0 and (x+ox) < width*scale and (y+oy) >= 0 and (y+oy) < height*scale:
  140.                         tempc = mapImg.get_at((x+ox, y+oy))
  141.                         col = [col[0] + tempc[0], col[1]+tempc[1], col[2]+tempc[2] ]
  142.                         n = n + 1
  143.             col[0] = math.floor(col[0]/n)
  144.             col[1] = math.floor(col[1]/n)
  145.             col[2] = math.floor(col[2]/n)
  146.             mapImg.set_at((x, y), col)
  147.                
  148.  
  149. def drawWorld(surface, offsetx, offsety):
  150.     for x in range(width*maps[0]):
  151.         for y in range(height*maps[1]):
  152.             h = wmap[x][y][0]
  153.             col = hmap[h]
  154.  
  155.             lighting = wmap[x][y][1]
  156.            
  157.             drawPixel(surface, x, y, col, getBorders(x, y, borderDiff), lighting)
  158.     drawScreen()
  159.  
  160.  
  161. def drawArea(surface, fpos, tpos):
  162.     for x in range(fpos[0], tpos[0]+1):
  163.         for y in range(fpos[1], tpos[1]+1):
  164.             h = wmap[x][y][0]
  165.             col = hmap[h]
  166.  
  167.             lighting = wmap[x][y][1]
  168.            
  169.             drawPixel(surface, x, y, col, getBorders(x, y, borderDiff), lighting)
  170.     drawScreen()
  171.  
  172. def addHotspot(x, y, h, intensity, dist):
  173.     for ox in range(-dist, dist+1):
  174.         for oy in range(-dist, dist+1):
  175.             if (ox*ox)+(oy*oy) <= dist*dist and isValid(x+ox, y+oy):
  176.                 per = 100- ((( (ox*ox) + (oy*oy) )/(dist*dist))*100)
  177.                 i = math.ceil( (intensity/100)*per )
  178.                 wmap[x+ox][y+oy].append([h, i])
  179.  
  180. drange = [30, 70]
  181. def generateHotspot(x, y):
  182.     #print("Hotspot position: ",x,",",y)
  183.     pos = [x, y]
  184.     h = random.randint(0, 99)
  185.     intensity = random.randint(6, 13)
  186.     dist = random.randint(drange[0], drange[1])
  187.     addHotspot(pos[0], pos[1], h, intensity, dist)
  188.  
  189. def genHotspots(offsetx, offsety):
  190.     avgdrange = (drange[0]+drange[1])/2
  191.     hotspot_amt = math.ceil( (width*height)/(math.pi*avgdrange*avgdrange) )
  192.     hotroot = math.ceil(math.sqrt(hotspot_amt))
  193.     wpart, hpart = width/hotroot, height/hotroot
  194.     hotroot = hotroot*2
  195.     for x in range(0, hotroot):
  196.        
  197.         for y in range(0, hotroot):
  198.             rx = ( (x*wpart) + wpart )/2
  199.             ry = ( (y*hpart) + hpart)/2
  200.             offset = [random.randint(0, math.floor(wpart))-(wpart/2), random.randint(0, math.floor(hpart))-(hpart/2)]
  201.             generateHotspot(math.floor(rx+offset[0])+offsetx, math.floor(ry+offset[1])+offsety)
  202.            
  203.     print(hotspot_amt, ", ", hotroot)
  204.  
  205.  
  206. def getAverageHeight(x, y, sens, hotspots, circular):
  207.     nlist = []
  208.     total = 0
  209.     n = 0
  210.     if isValid(x, y) and hotspots == True:
  211.         if len(wmap[x][y]) > 2:
  212.             for i in range(2, len(wmap[x][y])):
  213.                 hotspot = wmap[x][y][i]
  214.                 total = total + (hotspot[0]*hotspot[1])
  215.                 n = n + hotspot[1]
  216.     for ox in range(-sens, sens+1):
  217.         for oy in range(-sens, sens+1):
  218.             if isValid(x+ox, y+oy):
  219.                 if circular:
  220.                     if getDist(x, y, x+ox, y+oy) <= sens:
  221.                         total = total + wmap[x+ox][y+oy][0]
  222.                         n = n + 1
  223.                 else:
  224.                     total = total + wmap[x+ox][y+oy][0]
  225.                     n = n + 1
  226.     h = 0
  227.     if n != 0:
  228.         h = math.floor(total/n)
  229.         if h > 99:
  230.             h = 99
  231.     return h
  232.  
  233.    
  234.  
  235. def smoothWorld(offset, amt, sens, hotspots):
  236.     todo = []
  237.     for x in range(width*amt[0]):
  238.         for y in range(height*amt[1]):
  239.             wmap[x+offset[0]][y+offset[1]][0] = getAverageHeight(x+offset[0], y+offset[1], sens, hotspots, False)
  240.  
  241. def smoothArea(offset, fpos, tpos, sens, hotspots, circ):
  242.     for x in range(fpos[0], tpos[0]+1):
  243.         for y in range(fpos[1], tpos[1]+1):
  244.             if isValid(x, y):
  245.                 wmap[x+offset[0]][y+offset[1]][0] = getAverageHeight(x+offset[0], y+offset[1], sens, hotspots, circ)
  246.  
  247. def getTotalAverageHeight():
  248.     total = 0
  249.     n = 0
  250.     for x in range(width):
  251.         for y in range(height):
  252.             total = total + wmap[x][y][0]
  253.             n = n + 1
  254.    
  255.     return math.floor(total/n)
  256.  
  257. def createWorld(surface, offsetx, offsety):
  258.     genHotspots(offsetx, offsety)
  259.     #drawWorld(surface, offsetx, offsety)
  260.  
  261.     print("Smoothing world, pass 1")
  262.     smoothWorld([offsetx, offsety], [1,1], 2, True)
  263.     #drawWorld(surface, offsetx, offsety)
  264.  
  265.     print("Smoothing world, pass 2")
  266.     smoothWorld([offsetx, offsety], [1,1], 2, False)
  267.     #drawWorld(surface, offsetx, offsety)
  268.  
  269.     print("Smoothing world, pass 3")
  270.     smoothWorld([offsetx, offsety], [1,1], 3, True)
  271.     #drawWorld(surface, offsetx, offsety)
  272.  
  273.     print("Smoothing world, pass 4")
  274.     smoothWorld([offsetx, offsety], [1,1], 4, False)
  275.     #drawWorld(surface, offsetx, offsety)
  276.  
  277. createWorld(mapImg, 0, 0)
  278. drawWorld(mapImg, 0, 0)
  279. #createWorld(mapImg, width, 0)
  280. #createWorld(mapImg, width, height)
  281. #createWorld(mapImg, 0, height)
  282.  
  283. def joinWorlds():
  284.     print("Smoothing all maps, pass 1")
  285.     smoothWorld([0,0], maps, 4, True)
  286.     drawWorld(mapImg, 0, 0)
  287.  
  288.     print("Smoothing all maps, pass 2")
  289.     smoothWorld([0,0], maps, 3, False)
  290.     drawWorld(mapImg, 0, 0)
  291.  
  292. #joinWorlds()
  293. print("Done!")
  294. print("Finding village locations...")
  295.  
  296. villageHouses = 7
  297. villageSize = 40
  298. houseSize = 2
  299. def findVillageLocations(size):
  300.     locations = []
  301.     for x in range(width):
  302.         for y in range(height):
  303.             h = wmap[x][y][0]
  304.             if h >= gr[0] and h < gr[1]:
  305.                 ah = getAverageHeight(x, y, size, False, True)
  306.                 if ah >= h-2 and ah <= h+2:
  307.                     canCreate = True
  308.                     for i in range(len(locations)):
  309.                         if getDist(locations[i][0], locations[i][1], x, y) < size*2:
  310.                             canCreate = False
  311.                     if canCreate:
  312.                         locations.append([x, y])
  313.     return locations
  314.  
  315. class House:
  316.     def __init__(self, village, x, y, size):
  317.         self.village = village
  318.         self.x = x
  319.         self.y = y
  320.         self.size = size
  321.  
  322.     def draw(self):
  323.         for ox in range(-self.size, self.size+1):
  324.             for oy in range(-self.size, self.size+1):
  325.                 if getDist(self.x, self.y, self.x+ox, self.y+oy) <= self.size:
  326.                     drawPixel(overlay, self.x+ox, self.y+oy, [140, 123, 55, 255], [True, True, False, False], 0)
  327.  
  328. class Village:
  329.     def __init__(self, loc, size, hamt, hsize):
  330.         houses = []
  331.         n = 0
  332.         while len(houses) < hamt and n < 50:
  333.             pos = [random.randint(loc[0]-size, loc[0]+size), random.randint(loc[1]-size, loc[1]+size)]
  334.             dist = getDist(loc[0], loc[1], pos[0], pos[1])
  335.             if dist <= size and isValid(pos[0], pos[1]):
  336.                 canCreate = True
  337.                 for i in range(len(houses)):
  338.                     house = houses[i]
  339.                     if getDist(pos[0], pos[1], house.x, house.y) < hsize*2:
  340.                         canCreate = False
  341.                 ph = wmap[pos[0]][pos[1]][0]
  342.                 if canCreate and ph >= gr[0] and ph < gr[1]:
  343.                     houses.append(House(self, pos[0], pos[1], hsize))
  344.             n = n + 1
  345.         self.houses = houses
  346.         self.x = loc[0]
  347.         self.y = loc[1]
  348.         self.size = size
  349.  
  350.     def draw(self):
  351.         for i in range(len(self.houses)):
  352.             self.houses[i].draw()
  353.                                  
  354.  
  355.  
  356. #locs = findVillageLocations(villageSize)
  357.  
  358. #print("Creating villages... (",len(locs),")")
  359. #villages = []
  360. #for i in range(len(locs)):
  361. #    v = Village(locs[i], villageSize, villageHouses, houseSize)
  362. #    v.draw()
  363. #    villages.append(v)
  364.  
  365. print("Done!")
  366. drawScreen()
  367.  
  368. curSens = 2
  369. def getTilePosition(pos):
  370.     return [math.floor(pos[0]/scale), math.floor(pos[1]/scale)]
  371.  
  372. def raiseArea(amt, fpos, tpos, circ):
  373.     centre = [(fpos[0]+tpos[0])/2, (fpos[1]+tpos[1])/2]
  374.     for x in range(fpos[0], tpos[0]+1):
  375.         for y in range(fpos[1], tpos[1]+1):
  376.             if isValid(x, y):
  377.                 if (circ != 0 and getDist(x, y, centre[0], centre[1]) <= circ) or (circ == 0):
  378.                     wmap[x][y][0] = wmap[x][y][0] + amt
  379.                     if wmap[x][y][0] > 99:
  380.                         wmap[x][y][0] = 99
  381.                     if wmap[x][y][0] < 0:
  382.                         wmap[x][y][0] = 0
  383.  
  384. mouseMode = 0
  385. # 0 = smooth
  386. # 1 = raise
  387. # 2 = lower
  388. # 3 = hotspot_add
  389. # 4 = hotspot_remove
  390. mouseHotspots = False
  391. mouseCirc = True
  392. mouseArea = 2
  393.  
  394. mouseHeight = 49
  395. mouseIntensity = 7
  396.  
  397. scrollMode = 0
  398. # 0 = brush size
  399. # 1 = sensitivity
  400. # 2 = height
  401. # 3 = intensity
  402.  
  403. mticks = pygame.time.get_ticks()
  404. kticks = pygame.time.get_ticks()
  405. while 1:
  406.     for event in pygame.event.get():
  407.         if event.type == QUIT:
  408.             sys.exit()
  409.         if event.type == pygame.MOUSEBUTTONDOWN:
  410.             if event.button == 4: #scroll up
  411.                 if scrollMode == 0:
  412.                     mouseArea = mouseArea + 1
  413.                     print("Brush size: ", mouseArea)
  414.                 elif scrollMode == 1:
  415.                     curSens = curSens + 1
  416.                     print("Cursor sensitivity: ", curSens)
  417.                 elif scrollMode == 2:
  418.                     mouseHeight = mouseHeight + 1
  419.                     print("Mouse height (hotspot): ", mouseHeight)
  420.                 elif scrollMode == 3:
  421.                     mouseIntensity = mouseIntensity + 1
  422.                     print("Mouse intensity (hotspot): ", mouseIntensity)
  423.             elif event.button == 5: #scroll down
  424.                 if scrollMode == 0:
  425.                     mouseArea = mouseArea - 1
  426.                     if mouseArea < 0:
  427.                         mouseArea = 0
  428.                     print("Brush size: ", mouseArea)
  429.                 elif scrollMode == 1:
  430.                     curSens = curSens - 1
  431.                     if curSens < 0:
  432.                         curSens = 0
  433.                     print("Cursor sensitivity: ", curSens)
  434.                 elif scrollMode == 2:
  435.                     mouseHeight = mouseHeight - 1
  436.                     if mouseHeight < 0:
  437.                         mouseHeight = 0
  438.                     print("Mouse height (hotspot): ", mouseHeight)
  439.                 elif scrollMode == 3:
  440.                     mouseIntensity = mouseIntensity - 1
  441.                     if mouseIntensity < 0:
  442.                         mouseIntensity = 0
  443.                     print("Mouse intensity (hotspot): ", mouseIntensity)
  444.    
  445.     if pygame.time.get_ticks() - kticks >= 100:
  446.         keys = pygame.key.get_pressed()
  447.         if keys[pygame.K_1]:
  448.             mouseMode = 0
  449.             print("Mouse set to smooth")
  450.         elif keys[pygame.K_2]:
  451.             mouseMode = 1
  452.             print("Mouse set to raise")
  453.         elif keys[pygame.K_3]:
  454.             mouseMose = 2
  455.             print("Mouse set to lower")
  456.         elif keys[pygame.K_4]:
  457.             mouseMode = 3
  458.             print("Mouse mode set to hotspot! (one use)")
  459.         if keys[pygame.K_q]:
  460.             mouseHotspots = (mouseHotspots == False)
  461.             print("Smoothing hotspots set to ", str(mouseHotspots))
  462.         if keys[pygame.K_w]:
  463.             mouseCirc = (mouseCirc == False)
  464.             print("Circular brush set to ", str(mouseCirc))
  465.         if keys[pygame.K_a]:
  466.             scrollMode = 0
  467.             print("Scroll mode set to brush size")
  468.         elif keys[pygame.K_s]:
  469.             scrollMode = 1
  470.             print("Scroll mode set to sensitivity")
  471.         elif keys[pygame.K_d]:
  472.             scrollMode = 2
  473.             print("Scroll mode set to height (hotspot)")
  474.         elif keys[pygame.K_f]:
  475.             scrollMode = 3
  476.             print("Scroll mode set to intensity")
  477.         if keys[pygame.K_z]:
  478.             print("Smoothing world...")
  479.             smoothWorld([0,0], maps, curSens, mouseHotspots)
  480.             print("Drawing world...")
  481.             drawWorld(mapImg, 0, 0)
  482.             print("Done!")
  483.        
  484.         kticks = pygame.time.get_ticks()
  485.            
  486.     if pygame.time.get_ticks() - mticks >= 50:
  487.         prsd = pygame.mouse.get_pressed()
  488.         if prsd[2] or prsd[0]:
  489.             if mouseMode == 0:
  490.                 #print("SMOOTHING_TILE")
  491.                 pos = getTilePosition(pygame.mouse.get_pos())
  492.                 #offset, fpos, tpos, sens, hostpots, circular
  493.                 smoothArea([0,0], [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea], curSens, mouseHotspots, mouseCirc)
  494.                 #surface, fpos, tpos
  495.                 drawArea(mapImg, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea])
  496.             elif mouseMode == 1:
  497.                 pos = getTilePosition(pygame.mouse.get_pos())
  498.                 circ = 0
  499.                 if mouseCirc:
  500.                     circ = curSens
  501.                 raiseArea(1, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea], circ)
  502.                 drawArea(mapImg, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea])
  503.             elif mouseMode == 2:
  504.                 pos = getTilePosition(pygame.mouse.get_pos())
  505.                 circ = 0
  506.                 if mouseCirc:
  507.                     circ = curSens
  508.                 raiseArea(-1, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea], circ)
  509.                 drawArea(mapImg, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea])
  510.             elif mouseMode == 3: #hotspot
  511.                 #addHotspot(x, y, h, intensity, dist)
  512.                 pos = getTilePosition(pygame.mouse.get_pos())
  513.                 addHotspot(pos[0], pos[1], mouseHeight, mouseIntensity, mouseArea)
  514.                 mouseMode = 0
  515.            
  516.            
  517.         mticks = pygame.time.get_ticks()