mapgen/game/1_maze.coffee
Alexander Yakovlev 1e69ec3fe3
All checks were successful
default/mapgen/master This commit looks good
bathname
2018-09-29 22:07:00 +07:00

205 lines
6.7 KiB
CoffeeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class Maze
# карта игры
# для простоты мы используем только 2 типа клеток: exterior и interior
# в реале это могут быть forest (лес), rock (скалы), shore(берег)…
map: [
['interior', 'interior', 'interior', 'interior']
['interior', 'exterior', 'exterior', 'interior']
['interior', 'exterior', 'exterior', 'interior']
['interior', 'interior', 'interior', 'interior']
]
gridData: (x, y) ->
maptype = @map[y][x]
# тип ячейки:
# square - площадь
# fountain - фонтан
# street - улица
# bath - баня
# tavern - таверна
# guild - гильдия
# hospital - лечебница
# chapel - часовня
# workshop - мастерская
switch maptype
when "exterior"
# d20
rnd = salet.rnd.rand(20)
switch
when rnd < 4 then type = "fountain"
when rnd < 16 then type = "street"
else type = "square"
when "interior"
rnd = salet.rnd.rand(18)
switch
when rnd < 2 then type = "tavern"
when rnd < 3 then type = "hospital"
when rnd < 6 then type = "bath"
when rnd < 10 then type = "chapel"
when rnd < 14 then type = "guild"
else type = "workshop"
else
type = maptype
return type
constructor: (@width, @height, improv) ->
@data = []
# TODO получить координаты особых локаций
for y in [0..(@height-1)]
for x in [0..(@width-1)]
@data[x] ?= []
@data[x][y] = new Maze.Cell
@data[x][y].setTag('position', @map[y][x])
@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})"
###
# мы выставили типы всем ячейкам, теперь превратим это в названия
for y in [0..(@height-1)]
for x in [0..(@width-1)]
@data[x][y].loctitle = improv.gen('loctitle', @data[x][y])
if @data[x][y].getTag('type') == 'bath'
salet.character.bathname = @data[x][y].loctitle
salet.character.bathx = x
salet.character.bathy = y
return true
at: (x, y) -> return @data[x][y]
describe: (x, y, improv) ->
model = @data[x][y]
model = setAdjacent(model)
return '<h4>'+model.loctitle+"</h4>\n"+improv.gen('description', model)+"\n\n"#+improv.gen('directions', model)
# Я хотел сделать дополнительные ссылки в тексте, но это жутко муторно
# писать кучу кода для Improv на разбор, какие направления доступны.
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
getDirection: (direction, x, y) ->
switch direction
when "north" then return @getNorth(x,y)
when "south" then return @getSouth(x,y)
when "east" then return @getEast(x,y)
when "west" then return @getWest(x,y)
else 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
# выбрать особый квадрант и выставить в нём клетку нужного типа
# вернуть её координаты
# TODO
setspecialregion: (quadrant, type) ->
halfheight = Math.floor(@height/2)
halfwidth = Math.floor(@width/2)
x = 0
y = 0
return {
x: x
y: y
}
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 "exterior" then return "e"
when "interior" then return "i"
when "fountain" then return "f"
when "street" then return "s"
when "bath" then return "b"
when "tavern" then return "t"
when "guild" then return "g"
when "hospital" then return "h"
when "chapel" then return "c"
when "workshop" then return "w"
when "special" then return "!"
else return "?"