diff doodle/main/chess.d @ 139:e33f37b14893 default tip

Port to 'no-more-make' https://github.com/GrahamStJack/no-more-make
author David Bryant <bagnose@gmail.com>
date Sun, 30 Sep 2012 15:41:25 +0930
parents doodle/main/util/chess.d@89e8b0d92f36
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doodle/main/chess.d	Sun Sep 30 15:41:25 2012 +0930
@@ -0,0 +1,266 @@
+//
+// Notes:
+//  ply = half move (ie black or white's half of the move)
+
+import std.stdio;
+import std.ascii;
+import std.traits;
+import std.range;
+
+enum Side {
+    White, Black
+}
+
+enum Name {
+    King, Queen, Rook, Bishop, Knight, Pawn
+}
+
+struct Piece {
+    Side side;
+    Name name;
+}
+
+string toString(Piece piece) {
+    return
+        [
+        [ "\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659" ],
+        [ "\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F" ]
+        ]
+        [piece.side][piece.name];
+}
+
+//
+//
+//
+
+enum File {
+    _A, _B, _C, _D, _E, _F, _G, _H
+}
+
+char toChar(File f) {
+    return "abcdefgh"[f];
+}
+
+enum Rank {
+    _1, _2, _3, _4, _5, _6, _7, _8
+}
+
+char toChar(Rank r) {
+    return "12345678"[r];
+}
+
+struct Coord {
+    File file;
+    Rank rank;
+}
+
+string toString(in Coord coord) {
+    return toChar(coord.file) ~ "+" ~ toChar(coord.rank);
+}
+
+//
+//
+//
+
+struct Board {
+    struct Square {
+        this(in Side side, in Name name) {
+            occupied = true;
+            piece = Piece(side, name);
+        }
+
+        bool  occupied = false;
+        Piece piece;        // valid if occupied
+    }
+
+    this(in Square[8][8] squares_) {
+        squares = squares_;
+    }
+
+    Square square(Coord coord) const {
+        return squares[coord.file][coord.rank];
+    }
+
+private:
+    Square * at(Coord coord) {
+        return &squares[coord.file][coord.rank];
+    }
+
+    void add(Piece piece, Coord coord) {
+        auto square = at(coord);
+        if (square.occupied) {
+            // error
+        }
+        else {
+            square.occupied = true;
+            square.piece    = piece;
+        }
+    }
+
+    void remove(Coord coord) {
+        auto square = at(coord);
+        if (square.occupied) {
+            square.occupied = false;
+        }
+        else {
+            // error
+        }
+    }
+
+    void move(Coord source, Coord dest) {
+        auto source_sq = at(source);
+        auto dest_sq = at(dest);
+
+        if (source_sq.occupied && !dest_sq.occupied) {
+            source_sq.occupied = false;
+            dest_sq.occupied = true;
+            dest_sq.piece = source_sq.piece;
+        }
+        else {
+            // error
+        }
+    }
+
+    Square[8][8] squares =
+        [
+        [ Square(Side.White, Name.Rook),   Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook)   ],
+        [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ],
+        [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ],
+        [ Square(Side.White, Name.Queen),  Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Queen)  ],
+        [ Square(Side.White, Name.King),   Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.King)   ],
+        [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ],
+        [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ],
+        [ Square(Side.White, Name.Rook),   Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook)   ]
+        ];
+}
+
+void dump(in Board board) {
+    bool light_square = true;
+
+    foreach_reverse(r; EnumMembers!Rank) {
+        write(toChar(r));
+        foreach(f; EnumMembers!File) {
+
+            if (light_square) {
+                write("\033[47m");
+            }
+            else {
+                write("\033[40m");
+            }
+
+            Board.Square square = board.square(Coord(f, r));
+            if (square.occupied) {
+                write(toString(square.piece));
+            }
+            else {
+                write(" ");
+            }
+
+            light_square = !light_square;
+        }
+        writeln("\033[0m");
+
+        light_square = !light_square;
+    }
+
+    write(" ");
+    foreach(f; EnumMembers!File) {
+        writef("%s", toChar(f));
+    }
+    writeln("");
+}
+
+//
+//
+//
+
+enum KingState {
+    Safe,
+    Check,
+    CheckMate
+}
+
+class Game {
+    struct SideState {
+        KingState kingState;
+        bool      kingMoved;
+        bool      queenRookMoved;
+        bool      kingRookMoved;
+    }
+
+    struct Ply {
+        this(Coord source_, Coord dest_) {
+            source = source_;
+            dest = dest_;
+        }
+
+        Coord source;
+        Coord dest;
+    }
+
+    @property Board board() { return _board; }
+
+    struct Flags {
+        bool check;
+        bool mate;
+    }
+
+    // Default initial pieces, white to play
+    this () {
+    }
+
+    // Restore a previous game
+    this (Board board, Flags whiteFlags, Flags blackFlags, Side nextPly) {
+        _board   = board;
+        _nextPly = nextPly;
+    }
+
+    enum Acceptance {
+        Normal,
+        Check,
+        Mate,
+        Illegal
+    }
+
+    Acceptance apply(in Ply ply) {
+        auto source = _board.square(ply.source);
+        auto dest   = _board.square(ply.dest);
+
+        /+
+        auto sq1 = square(update.source);
+        auto sq2 = square(update.dest);
+
+        if (sq1.piece == Piece.Pawn && update.dest.file != update.source.file) {
+            // en-passant
+        }
+        else if (sq1.piece == Piece.King && update.dest.file - update.source.file > 1) {
+            // castle
+        }
+        +/
+
+        return Acceptance.Normal;
+    }
+
+    private {
+        struct PieceState {
+            bool  uncaptured;
+            Coord coord;        // valid if uncaptured
+        }
+
+        Board         _board;
+        Side          _nextPly;
+        SideState     _whiteSideState;
+        PieceState[8] _whitePieceState;
+        SideState     _blackSideState;
+        PieceState[8] _blackPieceState;
+    }
+}
+
+void main(string[] args) {
+    Board board;
+    dump(board);
+
+    /+
+    Game game;
+    +/
+}