class Maze # карта игры, см. map.ods # forest - лес # shore - берег # lake - озеро # stream - ручей # stones - камни # rock - скалы # mouth - устье # bank - берег ручья # cave - вход в пещеру # ucavei - вход в подводную пещеру # ucavee - выход из подводной пещеры map: [ ['forest', 'shore', 'lake', 'shore', 'forest', 'forest', 'shore', 'lake', 'stones','stones'] ['shore', 'lake', 'lake', 'shore', 'forest', 'forest', 'shore', 'lake', 'stones','stones'] ['lake', 'lake', 'lake', 'shore', 'shore', 'shore', 'shore', 'lake', 'stones','stones'] ['lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'stones','stones'] ['lake', 'ucavei','lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'shore', 'stones'] ['lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'lake', 'shore', 'forest'] ['shore', 'shore', 'shore', 'shore', 'shore', 'mouth', 'shore', 'shore', 'shore', 'forest'] ['forest', 'forest','forest','forest','bank', 'stream', 'bank', 'forest','forest','forest'] ['forest', 'cave', 'forest','forest','bank', 'stream', 'bank', 'forest','rock', 'rock' ] ['forest', 'forest','forest','forest','bank', 'stream', 'bank', 'forest','rock', 'rock' ] ['forest', 'forest','forest','forest','bank', 'stream', 'bank', 'forest','forest','forest'] ['forest', 'rock', 'rock', 'forest','bank', 'stream', 'stream','bank', 'cave', 'forest'] ['rock', 'rock', 'rock', 'forest','forest', 'bank', 'stream','bank', 'forest','forest'] ['rock', 'ucavee','rock', 'forest','forest', 'bank', 'stream','stream','bank', 'forest'] ['forest', 'forest','rock', 'forest','forest', 'forest', 'bank', 'stream','stream','bank' ] ['forest', 'forest','rock', 'forest','forest', 'forest', 'forest','bank', 'stream','bank' ] ] gridData: (x, y) -> maptype = @map[y][x] # тип ячейки: # lowstones - камни лёгкого наклона # medstones - камни среднего наклона # histones - камни крутого наклона # rareforest - редкий лес # thickforest - густой лес # deepforest - дремучий лес # thickshrub - густой кустарник # openfield - открытое поле # swamp - болото # jungle - густые джунгли кустарника # calmstream - тихая заводь ручья # lake - озеро # stream - ручей # rock - скалы # cave - пещера # ucavei - вход в подводную пещеру # ucavee - выход из подводной пещеры switch maptype when "forest" rnd = salet.rnd.rand(20) switch when rnd < 4 then type = "thickforest" when rnd < 8 then type = "rareforest" when rnd < 12 then type = "openfield" when rnd < 16 then type = "deepforest" else type = "swamp" when "stones" rnd = salet.rnd.rand(12) switch when rnd < 4 then type = "lowstones" when rnd < 8 then type = "medstones" else type = "histones" when "bank" rnd = salet.rnd.rand(20) switch when rnd < 5 then type = "rareforest" when rnd < 10 then type = "jungle" when rnd < 15 then type = "thickforest" else type = "calmstream" else type = maptype return type constructor: (@width, @height) -> @data = [] for y in [0..(@height-1)] for x in [0..(@width-1)] @data[x] ?= [] @data[x][y] = new Maze.Cell @data[x][y].setTag('type', @gridData(x, y)) # special encounters specialEncounters = Object.keys(salet.specials).shuffle() plotEncounters = ["meet1"] # зд. возможно что две особых встречи упадут на одну клетку. for event in specialEncounters rnd = salet.rnd.rand(20) # вероятность 5% if plotEncounters.indexOf(event) != false rnd = 1 # вероятность 100% if rnd != 1 continue x = salet.rnd.rand(@width-1) y = salet.rnd.rand(@height-1) @data[x][y].setTag('special', event) console.log "Special encounter set to (#{x}, #{y})" return true at: (x, y) -> return @data[x][y] describe: (x, y, improv) -> model = @data[x][y] model = setAdjacent(model) return improv.gen('description', model) isEast: (x, y) -> return (x+1) <= (@width - 1) isWest: (x, y) -> return (x-1) >= 0 isNorth: (x, y) -> return (y-1) >= 0 isSouth: (x, y) -> return (y+1) <= (@height - 1) getEast: (x, y) -> if @isEast(x, y) return @at(x+1, y) return false getWest: (x, y) -> if @isWest(x, y) return @at(x-1, y) return false getNorth: (x, y) -> if @isNorth(x, y) return @at(x, y-1) return false getSouth: (x, y) -> if @isSouth(x, y) return @at(x+1, y+1) return false log: () -> map = "" for y in [0..(@height-1)] for x in [0..(@width-1)] map += @data[x][y].log() map += "\n" console.log map bezier: (type) -> halfheight = Math.floor(@height/2) halfwidth = Math.floor(@width/2) rnd = salet.rnd.rand(2) if rnd == 1 # P0 is in the lower left quadrant x0 = salet.rnd.rand(halfwidth) y0 = halfheight + salet.rnd.rand(halfheight) else # P0 is in the lower right quadrant x0 = halfwidth + salet.rnd.rand(halfwidth) y0 = halfheight + salet.rnd.rand(halfheight) rnd = salet.rnd.rand(2) if rnd == 1 # P1 - higher left x1 = salet.rnd.rand(halfwidth) y1 = salet.rnd.rand(halfheight) else # P1 - lower left x1 = salet.rnd.rand(halfwidth) y1 = halfheight + salet.rnd.rand(halfheight) # P2 - always higher right x2 = halfwidth+salet.rnd.rand(halfwidth) y2 = salet.rnd.rand(halfheight) # quadratic bezier curve for t in [0..@width] by 0.1 xp = Math.floor(Math.pow((1-t), 2)*x0+2*t*x1-2*Math.pow(t, 2)*x1+Math.pow(t, 2)*x2) yp = Math.floor(Math.pow((1-t), 2)*y0+2*t*y1-2*Math.pow(t, 2)*y1+Math.pow(t, 2)*y2) if @data[xp] == undefined or @data[xp][yp] == undefined break @data[xp][yp].setTag('type', type) class Maze.Cell constructor: () -> @tags = [] getTag: (tagName) -> for tag in @tags if tag[0] == tagName return tag[1] return undefined hasTag: (tagName) -> for tag in @tags if tag[0] == tagName return true return false setTag: (tagName, value) -> for tag, index in @tags if tag[0] == tagName @tags[index][1] = value return true @tags.push([tagName, value]) return true setTagIfNotPresent: (tagName, value) -> if @getTag(tagName) == undefined @tags.push([tagName, value]) log: () -> type = @getTag('type') switch type when "lowstones" then return "s" when "medstones" then return "s" when "histones" then return "s" when "rareforest" then return "f" when "thickforest" then return "f" when "deepforest" then return "f" when "thickshrub" then return "t" when "openfield" then return "o" when "swamp" then return "w" when "jungle" then return "j" when "calmstream" then return "c" when "lake" then return "l" when "stream" then return "s" when "rock" then return "r" when "cave" then return "a" when "ucavee" then return "a" when "ucavei" then return "a" when "special" then return "!" when "shore" then return "h" else return "?"