-
Notifications
You must be signed in to change notification settings - Fork 0
/
factory.go
153 lines (144 loc) · 3.94 KB
/
factory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"errors"
"math/rand"
)
const NumProducts = 8
const FactoryWidth = 5
const FactoryHeight = 5
type Factory struct {
position Position
product int
distance int
}
func (f Factory) Rectangle() Rectangle {
return Rectangle{
position: f.position,
width: FactoryWidth,
height: FactoryHeight,
}
}
func (f Factory) NextToIngressPositions() []Position {
positions := make([]Position, 0, 20)
for i := 0; i < FactoryWidth; i++ {
positions = append(positions, Position{
x: f.position.x + i,
y: f.position.y - 1,
})
positions = append(positions, Position{
x: f.position.x + i,
y: f.position.y + FactoryHeight,
})
}
for i := 0; i < FactoryHeight; i++ {
positions = append(positions, Position{
x: f.position.x - 1,
y: f.position.y + i,
})
positions = append(positions, Position{
x: f.position.x + FactoryWidth,
y: f.position.y + i,
})
}
return positions
}
func (f Factory) IngressPositions() []Position {
positions := make([]Position, 0)
for i := 0; i < FactoryWidth; i++ {
positions = append(positions, Position{
x: f.position.x + i,
y: f.position.y,
})
positions = append(positions, Position{
x: f.position.x + i,
y: f.position.y + FactoryHeight - 1,
})
}
for i := 0; i < FactoryHeight; i++ {
positions = append(positions, Position{
x: f.position.x,
y: f.position.y + i,
})
positions = append(positions, Position{
x: f.position.x + FactoryWidth - 1,
y: f.position.y + i,
})
}
return positions
}
func (s *Scenario) PositionAvailableForFactory(factories []Factory, mines []Mine, combiners []Combiner, paths []Path, position Position) bool {
factoryRectangle := Rectangle{
position: position,
width: FactoryWidth,
height: FactoryHeight,
}
if position.x+FactoryWidth > s.width || position.y+FactoryHeight > s.height {
return false
}
for _, obstacle := range s.obstacles {
if factoryRectangle.Intersects(obstacle) {
return false
}
}
for _, factory := range factories {
if factoryRectangle.Intersects(factory.Rectangle()) {
return false
}
}
for _, mine := range mines {
if mine.Intersects(factoryRectangle) {
return false
}
}
for _, deposit := range s.deposits {
depositRectangle := deposit.Rectangle()
extendedDepositRectangle := Rectangle{
Position{depositRectangle.position.x - 1, depositRectangle.position.y - 1},
depositRectangle.width + 2,
depositRectangle.height + 2,
nil,
}
if factoryRectangle.Intersects(extendedDepositRectangle) {
// top left
positionIsCorner := position.y+FactoryHeight == deposit.position.y && position.x+FactoryHeight == deposit.position.x
// top right
positionIsCorner = positionIsCorner || (position.y+FactoryHeight == deposit.position.y && position.x == deposit.position.x+deposit.width)
// bottom left
positionIsCorner = positionIsCorner || (position.y == deposit.position.y+deposit.height && position.x+FactoryHeight == deposit.position.x)
// bottom right
positionIsCorner = positionIsCorner || (position.y == deposit.position.y+deposit.height && position.x == deposit.position.x+deposit.width)
if !positionIsCorner {
return false
}
}
}
for _, combiner := range combiners {
if combiner.Intersects(factoryRectangle) {
return false
}
}
for _, path := range paths {
for _, conveyor := range path.conveyors {
if factoryRectangle.Intersects(*conveyor.Rectangle()) {
return false
}
}
}
return true
}
func (s *Scenario) RandomFactory(chromosome Chromosome) (Factory, error) {
rng := NewUniqueRNG(s.width * s.height)
var n int
done := false
for !done {
n, done = rng.Next()
x := n % s.width
y := n / s.width
pos := Position{x, y}
if s.PositionAvailableForFactory(chromosome.factories, chromosome.mines, chromosome.combiners, chromosome.paths, pos) {
subtype := s.products[rand.Intn(len(s.products))].subtype
return Factory{position: pos, product: subtype}, nil
}
}
return Factory{}, errors.New("no position available for factory")
}