-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathPos.scala
166 lines (133 loc) · 5.06 KB
/
Pos.scala
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
154
155
156
157
158
159
160
161
162
163
164
165
166
package strategygames.togyzkumalak
import strategygames.Player
import scala.math.{ abs, max, min }
//match src/main/scala/fairysf/Pos.scala for use in analysis and stratops
object Piotr {
val lookup: Map[Int, Char] = Map(
Pos.A1.index -> 'a',
Pos.B1.index -> 'b',
Pos.C1.index -> 'c',
Pos.D1.index -> 'd',
Pos.E1.index -> 'e',
Pos.F1.index -> 'f',
Pos.G1.index -> 'g',
Pos.H1.index -> 'h',
Pos.A2.index -> 'i',
Pos.B2.index -> 'j',
Pos.C2.index -> 'k',
Pos.D2.index -> 'l',
Pos.E2.index -> 'm',
Pos.F2.index -> 'n',
Pos.G2.index -> 'o',
Pos.H2.index -> 'p',
Pos.I1.index -> '[',
Pos.I2.index -> ']'
)
}
case class Pos private (index: Int) extends AnyVal {
def down: Option[Pos] = Pos.at(file.index, rank.index - 1)
def left: Option[Pos] = Pos.at(file.index - 1, rank.index)
def downLeft: Option[Pos] = Pos.at(file.index - 1, rank.index - 1)
def downRight: Option[Pos] = Pos.at(file.index + 1, rank.index - 1)
def up: Option[Pos] = Pos.at(file.index, rank.index + 1)
def right: Option[Pos] = Pos.at(file.index + 1, rank.index)
def upLeft: Option[Pos] = Pos.at(file.index - 1, rank.index + 1)
def upRight: Option[Pos] = Pos.at(file.index + 1, rank.index + 1)
def >|(stop: Pos => Boolean): List[Pos] = |<>|(stop, _.right)
def |<(stop: Pos => Boolean): List[Pos] = |<>|(stop, _.left)
def |<>|(stop: Pos => Boolean, dir: Direction): List[Pos] =
dir(this) map { p =>
p :: (if (stop(p)) Nil else p.|<>|(stop, dir))
} getOrElse Nil
def ?<(other: Pos): Boolean = file < other.file
def ?>(other: Pos): Boolean = file > other.file
def ?+(other: Pos): Boolean = rank < other.rank
def ?^(other: Pos): Boolean = rank > other.rank
def ?|(other: Pos): Boolean = file == other.file
def ?-(other: Pos): Boolean = rank == other.rank
def <->(other: Pos): Iterable[Pos] =
min(file.index, other.file.index) to max(file.index, other.file.index) flatMap { Pos.at(_, rank.index) }
def touches(other: Pos): Boolean = xDist(other) <= 1 && yDist(other) <= 1
def onSameDiagonal(other: Pos): Boolean =
file.index - rank.index == other.file.index - other.rank.index || file.index + rank.index == other.file.index + other.rank.index
def onSameLine(other: Pos): Boolean = ?-(other) || ?|(other)
def xDist(other: Pos) = abs(file - other.file)
def yDist(other: Pos) = abs(rank - other.rank)
def isLight: Boolean = (file.index + rank.index) % 2 == 1
@inline def file = File of this
@inline def rank = Rank of this
// We're going to use the chess piotr's which are not based on the
// indices that we use.
def piotr: Char = Piotr.lookup.get(index).getOrElse('?')
def piotrStr = piotr.toString
def player: Player = if (index < File.all.size) Player.P1 else Player.P2
def last(width: Int): Boolean =
if (rank.index == 0) (index + 1) % width == 0
else index == Pos.all.size - 1
def indexByWidth(width: Int): Int =
if (rank.index == 0) index
else index - (File.all.size - width) * 2
def key = file.toString + rank.toString
override def toString = key
}
object Pos {
def apply(index: Int): Option[Pos] =
if (0 <= index && index < File.all.size * Rank.all.size) Some(new Pos(index))
else None
def apply(file: File, rank: Rank): Pos =
if (rank.index == 0) new Pos(file.index)
else new Pos(File.all.size * (rank.index + 1) - 1 - file.index)
def at(x: Int, y: Int): Option[Pos] =
if (0 <= x && x < File.all.size && 0 <= y && y < Rank.all.size)
Some(new Pos(x + (File.all.size - x) * y))
else None
def opposite(index: Int): Option[Pos] =
apply(if (index < File.all.size) index + File.all.size else index - File.all.size)
def fromKey(key: String): Option[Pos] = allKeys get key
def piotr(c: Char): Option[Pos] = allPiotrs get c
def keyToPiotr(key: String) = fromKey(key) map (_.piotr)
def doubleKeyToPiotr(key: String) =
for {
a <- keyToPiotr(key take 2)
b <- keyToPiotr(key drop 2)
} yield s"$a$b"
def doublePiotrToKey(piotrs: String) =
for {
a <- piotr(piotrs.head)
b <- piotr(piotrs(1))
} yield s"${a.key}${b.key}"
val A1 = new Pos(0)
val B1 = new Pos(1)
val C1 = new Pos(2)
val D1 = new Pos(3)
val E1 = new Pos(4)
val F1 = new Pos(5)
val G1 = new Pos(6)
val H1 = new Pos(7)
val I1 = new Pos(8)
// backwards for 2nd rank
val I2 = new Pos(9)
val H2 = new Pos(10)
val G2 = new Pos(11)
val F2 = new Pos(12)
val E2 = new Pos(13)
val D2 = new Pos(14)
val C2 = new Pos(15)
val B2 = new Pos(16)
val A2 = new Pos(17)
// if adding new Pos check for use of Pos.all
val all: List[Pos] = (0 to (File.all.size * Rank.all.size) - 1).map(new Pos(_)).toList
def allByWidth(width: Int): List[Pos] = all.filter(_.file.index < width)
val allKeys: Map[String, Pos] = all
.map { pos =>
pos.key -> pos
}
.to(Map)
val allPiotrs: Map[Char, Pos] = all
.map { pos =>
pos.piotr -> pos
}
.to(Map)
// val posR = "([a-i][1-9]|[a-i]10)"
val posR = "([a-i][1-2])"
}