view doodle/main/prog/chess.d @ 129:10ad5417bf07

Checkpoint
author David Bryant <bagnose@gmail.com>
date Thu, 12 Jan 2012 16:42:16 +1030
parents bc4d29c7499c
children 1bc3475624d3
line wrap: on
line source

import std.stdio;
import std.ascii;
import std.traits;
import std.range;

enum Color {                // (side/player?)
    White, Black
}

Color invert(Color c) {
    return [Color.Black, Color.White][c];
}

enum Piece {
    King, Queen, Rook, Bishop, Knight, Pawn
}

/*
enum Shade {                // (color?)
    Light, Dark
}
*/

string toString(Color color, Piece piece) {
    return
        [
        [ "\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659" ],
        [ "\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F" ]
        ]
        [color][piece];
}

struct Square {
    this(Color color_, Piece piece_) {
        occupied = true;
        color = color_;
        piece = piece_;
    }

    bool  occupied = false;
    Color color;
    Piece piece;
}

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;
}

struct Update {
    Coord source;
    Coord dest;
}

struct Board {
    this(Board board, Update update) {
        squares = board.squares;
        apply(update);
    }

    Square square(Coord coord) const {
        return squares[coord.file][coord.rank];
    }

    struct SideState {
        struct PieceState {
            bool  captured;
            Coord location;
        };

        PieceState[16] pieceStates;

        @property bool canQueenSideCastle() { return !kingMoved && !queenRookMoved; }
        @property bool canKingSideCastle()  { return !kingMoved && !kingRookMoved;  }

        bool kingMoved;
        bool queenRookMoved;
        bool kingRookMoved;
    }

private:
    Square * square(Coord coord) {
        return &squares[coord.file][coord.rank];
    }

    void apply(Update update) {
        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
        }
        else {
            *sq2 = *sq1;
            sq1.occupied = false;
        }
    }

    Square[8][8] squares =
        [
        [ Square(Color.White, Piece.Rook),   Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Rook)   ],
        [ Square(Color.White, Piece.Knight), Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Knight) ],
        [ Square(Color.White, Piece.Bishop), Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Bishop) ],
        [ Square(Color.White, Piece.Queen),  Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Queen)  ],
        [ Square(Color.White, Piece.King),   Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.King)   ],
        [ Square(Color.White, Piece.Bishop), Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Bishop) ],
        [ Square(Color.White, Piece.Knight), Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Knight) ],
        [ Square(Color.White, Piece.Rook),   Square(Color.White, Piece.Pawn), Square(), Square(), Square(), Square(), Square(Color.Black, Piece.Pawn), Square(Color.Black, Piece.Rook)   ]
        ];
}

void dump(in Board board) {
    Color color = Color.White;

    foreach_reverse(r; EnumMembers!Rank) {
        write(toChar(r));
        foreach(f; EnumMembers!File) {

            if (color == Color.White) {
                write("\033[47m");
            }
            else {
                write("\033[40m");
            }

            Square square = board.square(Coord(f, r));
            if (square.occupied) {
                write(toString(square.color, square.piece));
            }
            else {
                write(" ");
            }

            color = invert(color);
        }
        writeln("\033[0m");

        color = invert(color);
    }

    write(" ");
    foreach(f; EnumMembers!File) {
        writef("%s", toChar(f));
    }
    writeln("");
}

struct Move {
}

class Player {
    abstract Move getMove(in Board board);
}

class Game {
    @property Board board() { return _board; }

    this (Player white, Player black) {
        Color turn = Color.White;

        for (;;) {
            bool valid = false;

            _players[turn].getMove(_board);
            // TODO apply 
            valid = true;

            if (valid) {
                turn = invert(turn);
            }
        }
    }

    private {
        Player[2] _players;
        Board     _board;
    }
}

class HumanPlayer : Player {
    //immutable Piece[char] _pieceByChar = [ 'A' : Piece.Queen ];
    //auto a = [ 1 : 2 ];

    override Move getMove(in Board board) {
        /*
        for (;;) {
            char[] buf;
            readln(buf);

            Piece piece = Piece.Pawn;

            if (buf.length >= 2) {
                if (isUpper(buf[0])) {
                }
            }
        }
        */

        return Move();
    }
}

void main(string[] args) {
    Board board;
    dump(board);

    Game game;

}