2021-03-01 05:03:03 -05:00
|
|
|
package d2ds1
|
|
|
|
|
|
|
|
const (
|
|
|
|
maxWallLayers = 4
|
|
|
|
maxFloorLayers = 2
|
|
|
|
maxShadowLayers = 1
|
|
|
|
maxSubstitutionLayers = 1
|
|
|
|
)
|
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
// LayerGroupType represents a type of layer (floor, wall, shadow, etc)
|
|
|
|
type LayerGroupType int
|
2021-03-01 05:03:03 -05:00
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
// Layer group types
|
2021-03-01 05:03:03 -05:00
|
|
|
const (
|
2021-03-31 15:14:00 -04:00
|
|
|
FloorLayerGroup LayerGroupType = iota
|
|
|
|
WallLayerGroup
|
|
|
|
ShadowLayerGroup
|
2021-04-07 04:48:04 -04:00
|
|
|
SubstitutionLayerGroup
|
2021-03-01 05:03:03 -05:00
|
|
|
)
|
|
|
|
|
2021-04-07 05:06:50 -04:00
|
|
|
func (l LayerGroupType) String() string {
|
|
|
|
switch l {
|
|
|
|
case FloorLayerGroup:
|
|
|
|
return "floor"
|
|
|
|
case WallLayerGroup:
|
|
|
|
return "wall"
|
|
|
|
case ShadowLayerGroup:
|
|
|
|
return "shadow"
|
|
|
|
case SubstitutionLayerGroup:
|
|
|
|
return "substitution"
|
|
|
|
}
|
|
|
|
|
|
|
|
// should not be reached
|
|
|
|
return "unknown"
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
type layerGroup []*Layer
|
2021-03-01 05:03:03 -05:00
|
|
|
|
|
|
|
type ds1Layers struct {
|
|
|
|
width, height int
|
|
|
|
Floors layerGroup
|
|
|
|
Walls layerGroup
|
|
|
|
Shadows layerGroup
|
|
|
|
Substitutions layerGroup
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) ensureInit() {
|
|
|
|
if l.Floors == nil {
|
|
|
|
l.Floors = make(layerGroup, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if l.Walls == nil {
|
|
|
|
l.Walls = make(layerGroup, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if l.Shadows == nil {
|
|
|
|
l.Shadows = make(layerGroup, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if l.Substitutions == nil {
|
|
|
|
l.Substitutions = make(layerGroup, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// removes nil layers from all layer groups
|
|
|
|
func (l *ds1Layers) cull() {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.cullNilLayers(FloorLayerGroup)
|
|
|
|
l.cullNilLayers(WallLayerGroup)
|
|
|
|
l.cullNilLayers(ShadowLayerGroup)
|
2021-04-07 04:48:04 -04:00
|
|
|
l.cullNilLayers(SubstitutionLayerGroup)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// removes nil layers of given layer group type
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) cullNilLayers(t LayerGroupType) {
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-27 16:09:53 -04:00
|
|
|
if group == nil {
|
2021-03-01 05:03:03 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// from last to first layer, remove first encountered nil layer and restart the culling procedure.
|
|
|
|
// exit culling procedure when no nil layers are found in entire group.
|
|
|
|
culling:
|
|
|
|
for {
|
2021-04-07 11:24:00 -04:00
|
|
|
for idx := len(*group) - 1; idx >= 0; idx-- {
|
2021-03-01 05:03:03 -05:00
|
|
|
if (*group)[idx] == nil {
|
2021-04-07 11:24:00 -04:00
|
|
|
*group = append((*group)[:idx], (*group)[idx+1:]...)
|
2021-03-01 05:03:03 -05:00
|
|
|
continue culling
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break culling // encountered no new nil layers
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) Size() (w, h int) {
|
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
|
|
|
|
|
|
|
return l.width, l.height
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) SetSize(w, h int) {
|
|
|
|
l.width, l.height = w, h
|
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
l.enforceSize(FloorLayerGroup)
|
|
|
|
l.enforceSize(WallLayerGroup)
|
|
|
|
l.enforceSize(ShadowLayerGroup)
|
2021-04-07 04:48:04 -04:00
|
|
|
l.enforceSize(SubstitutionLayerGroup)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) enforceSize(t LayerGroupType) {
|
2021-03-01 05:03:03 -05:00
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-27 16:09:53 -04:00
|
|
|
if group == nil {
|
2021-03-01 05:03:03 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for idx := range *group {
|
|
|
|
(*group)[idx].SetSize(l.width, l.height)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) Width() int {
|
|
|
|
w, _ := l.Size()
|
|
|
|
return w
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) SetWidth(w int) {
|
|
|
|
l.SetSize(w, l.height)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) Height() int {
|
|
|
|
_, h := l.Size()
|
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) SetHeight(h int) {
|
|
|
|
l.SetSize(l.width, h)
|
|
|
|
}
|
|
|
|
|
|
|
|
// generic push func for all layer types
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) push(t LayerGroupType, layer *Layer) {
|
2021-03-01 05:03:03 -05:00
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
2021-03-31 07:52:31 -04:00
|
|
|
layer.SetSize(l.Size())
|
2021-03-01 05:03:03 -05:00
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-01 05:03:03 -05:00
|
|
|
|
2021-04-07 04:55:15 -04:00
|
|
|
max := GetMaxGroupLen(t)
|
2021-03-01 05:03:03 -05:00
|
|
|
|
|
|
|
if len(*group) < max {
|
|
|
|
*group = append(*group, layer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// generic pop func for all layer types
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) pop(t LayerGroupType) *Layer {
|
2021-03-01 05:03:03 -05:00
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-27 16:09:53 -04:00
|
|
|
if group == nil {
|
2021-03-01 05:03:03 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
var theLayer *Layer
|
2021-03-27 16:09:53 -04:00
|
|
|
|
2021-03-01 05:03:03 -05:00
|
|
|
// remove last layer of slice and return it
|
|
|
|
if len(*group) > 0 {
|
|
|
|
lastIdx := len(*group) - 1
|
|
|
|
theLayer = (*group)[lastIdx]
|
|
|
|
*group = (*group)[:lastIdx]
|
|
|
|
|
|
|
|
return theLayer
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) get(t LayerGroupType, idx int) *Layer {
|
2021-03-01 05:03:03 -05:00
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-27 16:09:53 -04:00
|
|
|
if group == nil {
|
2021-03-01 05:03:03 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if idx >= len(*group) || idx < 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return (*group)[idx]
|
|
|
|
}
|
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) insert(t LayerGroupType, idx int, newLayer *Layer) {
|
2021-03-01 05:03:03 -05:00
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
|
|
|
|
|
|
|
if newLayer == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:52:31 -04:00
|
|
|
newLayer.SetSize(l.Size())
|
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-27 16:09:53 -04:00
|
|
|
if group == nil {
|
|
|
|
return
|
|
|
|
}
|
2021-03-01 05:03:03 -05:00
|
|
|
|
2021-04-07 04:55:15 -04:00
|
|
|
if len(*group)+1 > GetMaxGroupLen(t) {
|
2021-03-01 05:03:03 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-27 16:09:53 -04:00
|
|
|
if len(*group) == 0 {
|
|
|
|
*group = append(*group, newLayer) // nolint:staticcheck // we possibly use group later
|
2021-03-01 05:03:03 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-27 16:09:53 -04:00
|
|
|
if l := len(*group) - 1; idx > l {
|
|
|
|
idx = l
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// example:
|
|
|
|
// suppose
|
|
|
|
// idx=1
|
|
|
|
// newLayer=c
|
|
|
|
// existing layerGroup is [a, b]
|
2021-05-12 02:30:28 -04:00
|
|
|
*group = append((*group)[:idx], append([]*Layer{newLayer}, (*group)[idx:]...)...)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 15:14:00 -04:00
|
|
|
func (l *ds1Layers) delete(t LayerGroupType, idx int) {
|
2021-03-01 05:03:03 -05:00
|
|
|
l.ensureInit()
|
|
|
|
l.cull()
|
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
group := l.GetLayersGroup(t)
|
2021-03-27 16:09:53 -04:00
|
|
|
if group == nil {
|
2021-03-01 05:03:03 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-27 16:09:53 -04:00
|
|
|
if idx >= len(*group) || idx < 0 {
|
2021-03-01 05:03:03 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-03-27 16:09:53 -04:00
|
|
|
(*group)[idx] = nil
|
2021-03-01 05:03:03 -05:00
|
|
|
|
|
|
|
l.cull()
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) GetFloor(idx int) *Layer {
|
2021-03-31 15:14:00 -04:00
|
|
|
return l.get(FloorLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PushFloor(floor *Layer) *ds1Layers {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.push(FloorLayerGroup, floor)
|
2021-03-01 05:03:03 -05:00
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PopFloor() *Layer {
|
2021-03-31 15:14:00 -04:00
|
|
|
return l.pop(FloorLayerGroup)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) InsertFloor(idx int, newFloor *Layer) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.insert(FloorLayerGroup, idx, newFloor)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) DeleteFloor(idx int) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.delete(FloorLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) GetWall(idx int) *Layer {
|
2021-03-31 15:14:00 -04:00
|
|
|
return l.get(WallLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PushWall(wall *Layer) *ds1Layers {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.push(WallLayerGroup, wall)
|
2021-03-01 05:03:03 -05:00
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PopWall() *Layer {
|
2021-03-31 15:14:00 -04:00
|
|
|
return l.pop(WallLayerGroup)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) InsertWall(idx int, newWall *Layer) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.insert(WallLayerGroup, idx, newWall)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) DeleteWall(idx int) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.delete(WallLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) GetShadow(idx int) *Layer {
|
2021-03-31 15:14:00 -04:00
|
|
|
return l.get(ShadowLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PushShadow(shadow *Layer) *ds1Layers {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.push(ShadowLayerGroup, shadow)
|
2021-03-01 05:03:03 -05:00
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PopShadow() *Layer {
|
2021-03-31 15:14:00 -04:00
|
|
|
return l.pop(ShadowLayerGroup)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) InsertShadow(idx int, newShadow *Layer) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.insert(ShadowLayerGroup, idx, newShadow)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) DeleteShadow(idx int) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.delete(ShadowLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) GetSubstitution(idx int) *Layer {
|
2021-04-07 04:48:04 -04:00
|
|
|
return l.get(SubstitutionLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PushSubstitution(sub *Layer) *ds1Layers {
|
2021-04-07 04:48:04 -04:00
|
|
|
l.push(SubstitutionLayerGroup, sub)
|
2021-03-01 05:03:03 -05:00
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) PopSubstitution() *Layer {
|
2021-04-07 04:48:04 -04:00
|
|
|
return l.pop(SubstitutionLayerGroup)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 07:50:40 -04:00
|
|
|
func (l *ds1Layers) InsertSubstitution(idx int, newSubstitution *Layer) {
|
2021-04-07 04:48:04 -04:00
|
|
|
l.insert(SubstitutionLayerGroup, idx, newSubstitution)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ds1Layers) DeleteSubstitution(idx int) {
|
2021-03-31 15:14:00 -04:00
|
|
|
l.delete(ShadowLayerGroup, idx)
|
2021-03-01 05:03:03 -05:00
|
|
|
}
|
2021-03-27 16:09:53 -04:00
|
|
|
|
2021-04-07 04:57:20 -04:00
|
|
|
// GetLayersGroup returns layer group depending on type given
|
|
|
|
func (l *ds1Layers) GetLayersGroup(t LayerGroupType) (group *layerGroup) {
|
2021-03-27 16:09:53 -04:00
|
|
|
switch t {
|
2021-03-31 15:14:00 -04:00
|
|
|
case FloorLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
group = &l.Floors
|
2021-03-31 15:14:00 -04:00
|
|
|
case WallLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
group = &l.Walls
|
2021-03-31 15:14:00 -04:00
|
|
|
case ShadowLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
group = &l.Shadows
|
2021-04-07 04:48:04 -04:00
|
|
|
case SubstitutionLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
group = &l.Substitutions
|
|
|
|
default:
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return group
|
|
|
|
}
|
|
|
|
|
2021-04-07 04:55:15 -04:00
|
|
|
// GetMaxGroupLen returns maximum length of layer group of type given
|
|
|
|
func GetMaxGroupLen(t LayerGroupType) (max int) {
|
2021-03-27 16:09:53 -04:00
|
|
|
switch t {
|
2021-03-31 15:14:00 -04:00
|
|
|
case FloorLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
max = maxFloorLayers
|
2021-03-31 15:14:00 -04:00
|
|
|
case WallLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
max = maxWallLayers
|
2021-03-31 15:14:00 -04:00
|
|
|
case ShadowLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
max = maxShadowLayers
|
2021-04-07 04:48:04 -04:00
|
|
|
case SubstitutionLayerGroup:
|
2021-03-27 16:09:53 -04:00
|
|
|
max = maxSubstitutionLayers
|
|
|
|
default:
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
return max
|
|
|
|
}
|