1
1
package strategygames .abalone .format
2
2
3
3
import strategygames .Player
4
+ import strategygames .abalone .File
4
5
import strategygames .abalone .Piece
5
6
import strategygames .abalone .PieceMap
6
7
import strategygames .abalone .Pos
7
8
import strategygames .abalone .Stone
8
- import strategygames .abalone .File
9
9
10
- // FEN is described from bottomLeft to topRight
11
10
final case class FEN (value : String ) extends AnyVal {
12
- // Belgian Daisy: pp1PP/pppPPP/1pp1PP1/8/9/8/1PP1pp1/PPPppp/PP1pp 0 0 b 0 0
13
- // Snakes: PPPPP/5P/6P/1ppppp1P/1p5P1/p1PPPPP1/p6/p5/ppppp 0 0 b 0 0
11
+ // squares are described from topLeft to bottomRight in the FEN :
12
+ // eg. Belgian Daisy: SS1ss/SSSsss/1SS1ss1/8/9/8/1ss1SS1/sssSSS/ss1SS
13
+ // Snakes: sssss/s5/s6/s1SSSSS1/1s5S1/1sssss1S/6S/5S/SSSSS
14
14
15
15
override def toString = value
16
16
17
- def pieces : PieceMap = {
18
- /*
19
- squared hex representation of the Belgian Daisy FEN :
20
- row col
21
- 9 - 72 73 74 75 'P' 'P' '1' 'p' 'p' 8: >3 (<9)
22
- 8 - 63 64 65 'P' 'P' 'P' 'p' 'p' 'p' 7: >2 (<9) next line : +4
23
- 7 - 54 55 '1' 'P' 'P' '1' 'p' 'p' '1' 6: >1 (<9) next line : +3
24
- 6 - 45 '8' 5: >0 (<9) next line : +2
25
- 5 - '9' 4: <9 next line : +1
26
- 4 - '8' 35 3: <8 next line : +1
27
- 3 - '1' 'p' 'p' '1' 'P' 'P' '1' 25 26 2: <7 next line : +2
28
- 2 - 'p' 'p' 'p' 'P' 'P' 'P' 15 16 17 1: <6 next line : +3
29
- 1 - 'p' 'p' '1' 'P' 'P' 5 6 7 8 0: <5 next line : +4
30
- | | | | | | | | |
31
- A B C D E F G H I
32
- */
33
- val position = value.split(' ' )(0 )
34
- var currentIndex = 0
35
- var currentLine = 0
36
- position.map {
37
- case 'p' => {
38
- currentIndex = currentIndex + 1
39
- Some ((Pos .apply(currentIndex - 1 ), new Piece (strategygames.abalone.P1 , Stone )))
40
- }
41
- case 'P' => {
42
- currentIndex = currentIndex + 1
43
- Some ((Pos .apply(currentIndex - 1 ), new Piece (strategygames.abalone.P2 , Stone )))
44
- }
45
- case d if d.isDigit => {
46
- currentIndex = currentIndex + d.asDigit
47
- None
48
- }
49
- case '/' => {
50
- currentLine = currentLine + 1
51
- currentIndex = if (currentLine < 5 ) {
52
- currentIndex + (File .all.size / 2 + 1 ) - (currentLine)
53
- }
54
- else {
55
- currentIndex + Math .abs((File .all.size / 2 + 1 ) - currentLine - 1 )
17
+ def pieces : PieceMap = squares.zipWithIndex.map {
18
+ case (pieces, row) => pieces.zipWithIndex.map[Option [(Option [strategygames.abalone.Pos ], strategygames.abalone.Piece )]] {
19
+ case (piece, index) => piece match {
20
+ case Stone .forsyth => Some ((Pos .at(index, (File .all.size - 1 - row)), new Piece (strategygames.abalone.P1 , Stone )))
21
+ case Stone .forsythUpper => Some ((Pos .at(index, (File .all.size - 1 - row)), new Piece (strategygames.abalone.P2 , Stone )))
22
+ case _ => None
56
23
}
57
- None
24
+ }.flatMap {
25
+ case Some ((Some (pos), piece)) => Some (pos -> piece)
26
+ case _ => None
58
27
}
59
- }.flatten.flatMap { // flatMap = map + flatten, which gets rid of None and returns the Object instead of a Some(Object) which we would get with map
60
- case (Some (pos), piece) => Some (pos -> piece)
61
- case _ => None
62
- }.toMap
63
- }
28
+ }.flatten.toMap
64
29
65
30
def player1Score : Int = intFromFen(1 ).getOrElse(0 )
66
31
67
32
def player2Score : Int = intFromFen(2 ).getOrElse(0 )
68
33
69
- def player : Option [Player ] =
70
- value.split(' ' ).lift(3 ) flatMap (_.headOption) flatMap Player .apply map( ! _ )
34
+ def player : Option [Player ] = value.split(' ' ).lift(3 ).flatMap(_.headOption).flatMap(Player .apply).map( ! _ )
71
35
72
36
def halfMovesSinceLastCapture : Option [Int ] = intFromFen(4 )
73
37
@@ -82,6 +46,15 @@ final case class FEN(value: String) extends AnyVal {
82
46
83
47
private def intFromFen (index : Int ): Option [Int ] =
84
48
value.split(' ' ).lift(index).flatMap(_.toIntOption)
49
+
50
+ // represents pieces on the Board, and '0' or '1' depending if the empty square is in the hexagon or not
51
+ private def squares : Array [Array [Char ]] = value.split(' ' )(0 ).split('/' ).zipWithIndex.map {
52
+ case (pieces, row) if (row < (File .all.size / 2 + 1 )) => { Array .fill(Math .abs(row + (File .all.size / 2 + 1 ) - File .all.size)){'0' } ++ pieces.toArray }
53
+ case (pieces, row) => { pieces.toArray ++ Array .fill(Math .abs((File .all.size / 2 ) - row)){'0' } }
54
+ }.flatten.flatMap {
55
+ case (d) if (d.isDigit && d.asDigit > 0 ) => Array .fill(d.asDigit){Array ('1' )}
56
+ case (d) => Array .fill(1 ){Array (d)}
57
+ }.flatten.grouped(File .all.size).toArray
85
58
}
86
59
87
60
object FEN {
0 commit comments