211 lines
7.7 KiB
CoffeeScript
211 lines
7.7 KiB
CoffeeScript
|
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 "?"
|