Skip to content

Commit 6702092

Browse files
committed
refactoring: create a generic CrossingGenerator for RHW/NMW/etc.
1 parent ddfcbaf commit 6702092

2 files changed

Lines changed: 88 additions & 71 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.sc4nam.module
2+
3+
import io.github.memo33.metarules.meta._
4+
import syntax._, Network._, Flags._, RotFlip._, Implicits._
5+
import NetworkProperties._
6+
7+
object CrossingGenerator {
8+
9+
def crossingNetworksOf(main: Network): Iterator[Network] = {
10+
for {
11+
minor <- Network.values.iterator
12+
if minor != Subway && !isHrw(minor) && (main.isRhw || minor.isRhw ||
13+
(main.isNwm && (minor.isRhw || minor.isNwm || minor.base.isEmpty)) ||
14+
(main.isNwm && isSingleTile(main) && main.height == 0 && (minor == L1Dtr || minor == L2Dtr))
15+
) && intersectionAllowed(main, minor)
16+
} yield minor
17+
}
18+
}
19+
20+
trait CrossingGenerator extends Adjacencies { this: RuleGenerator =>
21+
22+
/** Creates generic rules for +-intersections and overpasses (O×O, O×D, D×O, D×D). */
23+
def createCrossingRules(main: Network, minor: Network): Unit = {
24+
for (base <- main.base) {
25+
// entry (override from straight tile to first crossing tile)
26+
if (intersectionAllowed(base, minor)) { // skips e.g. preexisting L0Rhw2 x L0Rhw6c in second tile
27+
def entryCode(orient: Segment => Segment) = withSharedDiagonals {
28+
Rules += main~WE | (base ~> main)~WE & orient(minor~NS) // OxO
29+
Rules += main~WE~EW | (base ~> main)~WE~EW & orient(minor~ES) // OxD
30+
Rules += main~SE~ES | (base ~> main)~WN~NW & orient(minor~NS) // DxO
31+
Rules += main~SE~ES | (base ~> main)~WN~NW & orient(minor~NE) // DxD
32+
// Shared diagonals on minor are not relevant here since the shared diagonal is an inner tile (i.e. without an edge).
33+
}
34+
if (hasRightShoulder(minor)) entryCode(identity)
35+
if (hasLeftShoulder(minor)) entryCode(_.reverse)
36+
createRules() // duplicate rules will be removed
37+
}
38+
// exit (override from last crossing tile to straight tile)
39+
{
40+
def exitCode(orient: Segment => Segment) = withSharedDiagonals {
41+
Rules += main~WE & orient(minor~SN) | (base ~> main)~WE // OxO
42+
Rules += main~WE~EW & orient(minor~WN) | (base ~> main)~WE~EW // OxD
43+
Rules += main~SE~ES & orient(minor~SN) | (base ~> main)~WN~NW // DxO
44+
Rules += main~SE~ES & orient(minor~SW) | (base ~> main)~WN~NW // DxD
45+
// Shared diagonals on minor are not relevant here since the shared diagonal is an inner tile (i.e. without an edge).
46+
}
47+
if (hasRightShoulder(minor)) exitCode(identity)
48+
if (hasLeftShoulder(minor)) exitCode(_.reverse)
49+
createRules()
50+
}
51+
// Inside diagonal crossings (Diagonal crossings consist of two or more tiles, so the following rules ensure
52+
// that the override carries over between those inner-intersection tiles)
53+
withSharedDiagonals {
54+
if (intersectionAllowed(base, minor)) {
55+
Rules += main~WE~EW & minor~NE | (base ~> main)~WE~EW & minor~WS // OxD
56+
Rules += main~WE~EW & minor~EN | (base ~> main)~WE~EW & minor~SW
57+
Rules += main~SE~ES & minor~WE | (base ~> main)~WN~NW & minor~WE // DxO
58+
Rules += main~SE~ES & minor~EW | (base ~> main)~WN~NW & minor~EW
59+
Rules += main~SE~ES & minor~NE | (base ~> main)~WN~NW & minor~WS // DxD
60+
Rules += main~SE~ES & minor~EN | (base ~> main)~WN~NW & minor~SW
61+
}
62+
// stability
63+
if (minor >= main) for (minBase <- minor.base) { // If minor < main, then the following rules have already been added as part of the overrides of minor.
64+
Rules += main~WE~EW & minor~NE | (base ~> main)~WE~EW & (minBase ~> minor)~WS // OxD
65+
Rules += main~WE~EW & minor~EN | (base ~> main)~WE~EW & (minBase ~> minor)~SW
66+
Rules += main~SE~ES & minor~WE | (base ~> main)~WN~NW & (minBase ~> minor)~WE // DxO
67+
Rules += main~SE~ES & minor~EW | (base ~> main)~WN~NW & (minBase ~> minor)~EW
68+
Rules += main~SE~ES & minor~NE | (base ~> main)~WN~NW & (minBase ~> minor)~WS // DxD
69+
Rules += main~SE~ES & minor~EN | (base ~> main)~WN~NW & (minBase ~> minor)~SW
70+
if (intersectionAllowed(base, minor) && intersectionAllowed(main, minBase)) {
71+
Rules += main~WE~EW & (minBase ~> minor)~NE | (base ~> main)~WE~EW & minor~WS // OxD
72+
Rules += main~WE~EW & (minBase ~> minor)~EN | (base ~> main)~WE~EW & minor~SW
73+
Rules += main~SE~ES & (minBase ~> minor)~WE | (base ~> main)~WN~NW & minor~WE // DxO
74+
Rules += main~SE~ES & (minBase ~> minor)~EW | (base ~> main)~WN~NW & minor~EW
75+
Rules += main~SE~ES & (minBase ~> minor)~NE | (base ~> main)~WN~NW & minor~WS // DxD
76+
Rules += main~SE~ES & (minBase ~> minor)~EN | (base ~> main)~WN~NW & minor~SW
77+
}
78+
}
79+
}
80+
// inside multi-tile intersection
81+
createAdjacentIntersections(main, base, minor)
82+
createRules()
83+
}
84+
}
85+
}

src/main/scala/module/RhwRuleGenerator.scala

Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,9 @@ object RhwRuleGenerator {
2424
m
2525
}
2626
}
27-
28-
def crossingNetworksOf(main: Network): Iterator[Network] = {
29-
for {
30-
minor <- Network.values.iterator
31-
if minor != Subway && !isHrw(minor) && (main.isRhw || minor.isRhw ||
32-
(main.isNwm && (minor.isRhw || minor.isNwm || minor.base.isEmpty)) ||
33-
(main.isNwm && isSingleTile(main) && main.height == 0 && (minor == L1Dtr || minor == L2Dtr))
34-
) && intersectionAllowed(main, minor)
35-
} yield minor
36-
}
3727
}
3828

39-
class RhwRuleGenerator(var context: RuleTransducer.Context) extends RuleGenerator with Curve45Generator with Adjacencies {
29+
class RhwRuleGenerator(var context: RuleTransducer.Context) extends RuleGenerator with Curve45Generator with CrossingGenerator {
4030
import RhwRuleGenerator._
4131

4232
def createMultiTileStarters(): Unit = {
@@ -78,66 +68,8 @@ class RhwRuleGenerator(var context: RuleTransducer.Context) extends RuleGenerato
7868
createCurve90Rules(main)
7969

8070
// TODO filtering
81-
for (minor <- crossingNetworksOf(main)) {
82-
// entry (override from straight tile to first crossing tile)
83-
if (intersectionAllowed(base, minor)) { // skips e.g. preexisting L0Rhw2 x L0Rhw6c in second tile
84-
def entryCode(orient: Segment => Segment) = withSharedDiagonals {
85-
Rules += main~WE | (base ~> main)~WE & orient(minor~NS) // OxO
86-
Rules += main~WE~EW | (base ~> main)~WE~EW & orient(minor~ES) // OxD
87-
Rules += main~SE~ES | (base ~> main)~WN~NW & orient(minor~NS) // DxO
88-
Rules += main~SE~ES | (base ~> main)~WN~NW & orient(minor~NE) // DxD
89-
// Shared diagonals on minor are not relevant here since the shared diagonal is an inner tile (i.e. without an edge).
90-
}
91-
if (hasRightShoulder(minor)) entryCode(identity)
92-
if (hasLeftShoulder(minor)) entryCode(_.reverse)
93-
createRules() // duplicate rules will be removed
94-
}
95-
// exit (override from last crossing tile to straight tile)
96-
{
97-
def exitCode(orient: Segment => Segment) = withSharedDiagonals {
98-
Rules += main~WE & orient(minor~SN) | (base ~> main)~WE // OxO
99-
Rules += main~WE~EW & orient(minor~WN) | (base ~> main)~WE~EW // OxD
100-
Rules += main~SE~ES & orient(minor~SN) | (base ~> main)~WN~NW // DxO
101-
Rules += main~SE~ES & orient(minor~SW) | (base ~> main)~WN~NW // DxD
102-
// Shared diagonals on minor are not relevant here since the shared diagonal is an inner tile (i.e. without an edge).
103-
}
104-
if (hasRightShoulder(minor)) exitCode(identity)
105-
if (hasLeftShoulder(minor)) exitCode(_.reverse)
106-
createRules()
107-
}
108-
// Inside diagonal crossings (Diagonal crossings consist of two or more tiles, so the following rules ensure
109-
// that the override carries over between those inner-intersection tiles)
110-
withSharedDiagonals {
111-
if (intersectionAllowed(base, minor)) {
112-
Rules += main~WE~EW & minor~NE | (base ~> main)~WE~EW & minor~WS // OxD
113-
Rules += main~WE~EW & minor~EN | (base ~> main)~WE~EW & minor~SW
114-
Rules += main~SE~ES & minor~WE | (base ~> main)~WN~NW & minor~WE // DxO
115-
Rules += main~SE~ES & minor~EW | (base ~> main)~WN~NW & minor~EW
116-
Rules += main~SE~ES & minor~NE | (base ~> main)~WN~NW & minor~WS // DxD
117-
Rules += main~SE~ES & minor~EN | (base ~> main)~WN~NW & minor~SW
118-
createRules()
119-
}
120-
// stability
121-
if (minor >= main) for (minBase <- minor.base) { // If minor < main, then the following rules have already been added as part of the overrides of minor.
122-
Rules += main~WE~EW & minor~NE | (base ~> main)~WE~EW & (minBase ~> minor)~WS // OxD
123-
Rules += main~WE~EW & minor~EN | (base ~> main)~WE~EW & (minBase ~> minor)~SW
124-
Rules += main~SE~ES & minor~WE | (base ~> main)~WN~NW & (minBase ~> minor)~WE // DxO
125-
Rules += main~SE~ES & minor~EW | (base ~> main)~WN~NW & (minBase ~> minor)~EW
126-
Rules += main~SE~ES & minor~NE | (base ~> main)~WN~NW & (minBase ~> minor)~WS // DxD
127-
Rules += main~SE~ES & minor~EN | (base ~> main)~WN~NW & (minBase ~> minor)~SW
128-
if (intersectionAllowed(base, minor) && intersectionAllowed(main, minBase)) {
129-
Rules += main~WE~EW & (minBase ~> minor)~NE | (base ~> main)~WE~EW & minor~WS // OxD
130-
Rules += main~WE~EW & (minBase ~> minor)~EN | (base ~> main)~WE~EW & minor~SW
131-
Rules += main~SE~ES & (minBase ~> minor)~WE | (base ~> main)~WN~NW & minor~WE // DxO
132-
Rules += main~SE~ES & (minBase ~> minor)~EW | (base ~> main)~WN~NW & minor~EW
133-
Rules += main~SE~ES & (minBase ~> minor)~NE | (base ~> main)~WN~NW & minor~WS // DxD
134-
Rules += main~SE~ES & (minBase ~> minor)~EN | (base ~> main)~WN~NW & minor~SW
135-
}
136-
}
137-
}
138-
// inside multi-tile intersection
139-
createAdjacentIntersections(main, base, minor)
140-
createRules()
71+
for (minor <- CrossingGenerator.crossingNetworksOf(main)) {
72+
createCrossingRules(main, minor)
14173
}
14274
}
14375
}

0 commit comments

Comments
 (0)