Ver Fonte

yeea baby, sum changees

Nicolas Winkler há 8 anos atrás
pai
commit
b2266e0cca
11 ficheiros alterados com 233 adições e 183 exclusões
  1. 21 43
      src/BitBoard.h
  2. 56 2
      src/BitOperations.h
  3. 52 85
      src/Board.cpp
  4. 18 18
      src/Board.h
  5. 21 15
      src/ChessGame.cpp
  6. 2 0
      src/ChessGame.h
  7. 19 4
      src/MoveGeneration.cpp
  8. 27 11
      src/MoveGeneration.h
  9. 2 2
      src/UciParser.cpp
  10. 14 2
      src/main.cpp
  11. 1 1
      src/makefile

+ 21 - 43
src/BitBoard.h

@@ -1,40 +1,43 @@
 #ifndef CHESSY_BITBOARD_H
 #define CHESSY_BITBOARD_H
 
+#include "BitOperations.h"
+
 #include <cinttypes>
 #include <type_traits>
-#include <array>
+#include <string>
 
 
 namespace chessy
 {
-    using U64 = uint64_t;
     union Index;
 
     struct Bitboard;
 }
 
+/*!
+ * data structure to index one field on a chess board
+ */
 union chessy::Index
 {
     int8_t index;
 
-    // Anonymous structs are actually not allowed in C++.
-    // Fortunately any sane compiler still supports them.
-    struct {
-        uint8_t column : 3;
-        uint8_t row    : 3;
-    };
-
     Index(void) = default;
-    inline Index(int8_t ind) : index {ind} {}
-    inline Index(const std::string& name) : Index{name[0] - 'a', name[1] - '0'} {}
+    inline Index(int8_t ind) : index{ ind } {}
+    inline Index(const std::string& name) :
+        Index{name[0] - '1', name[1] - 'a'} {}
     inline Index(int row, int column) :
         index{int8_t(((row & 0x7) << 3) + (column & 0x7))} {}
-    inline operator int8_t (void) const { return index; }
 
-    inline std::array<char, 2> getName(void) const
+
+    inline operator int8_t   (void) const   { return index; }
+
+    inline int getColumn    (void) const    { return index & 0x7; }
+    inline int getRow       (void) const    { return (index >> 3) & 0x7; }
+
+    inline std::string getName(void) const
     {
-        return {char('a' + ((index & 0x7) >> 3)), char('0' + (index & 0x7))};
+        return { char('a' + getColumn()), char('1' + getRow()) };
     }
 };
 
@@ -47,11 +50,11 @@ struct chessy::Bitboard
     Bitboard        (const Bitboard&)       = default;
     ~Bitboard       (void)                  = default;
 
-    inline Bitboard (U64 bits) : bits {bits} {}
+    inline Bitboard(U64 bits) : bits{ bits } {}
     inline static Bitboard fromIndex(Index i) { return U64(1) << i; }
 
-    inline void     setBit      (Index i)     { bits |= 1 << i.index; }
-    inline void     unsetBit    (Index i)     { bits |= ~(1 << i.index); }
+    inline void     setBit      (Index i)     { bits |= 1ULL << i.index; }
+    inline void     unsetBit    (Index i)     { bits |= ~(1ULL << i.index); }
 
     inline void     setBit      (int row, int column)
         { setBit(row * 8 + column); }
@@ -85,32 +88,7 @@ struct chessy::Bitboard
     inline          operator U64(void) const                { return bits; }
     inline explicit operator bool(void) const               { return bits != 0; }
 
-
-    inline Bitboard mirror      (void) const
-    {
-#if __GNUC__ > 4 && __GNUC_MINOR__ >= 3
-        return __builtin_bswap64(bits);
-#else
-        return (bits << 56) |
-            ((bits & 0xFF00) << 40) |
-            ((bits & 0xFF0000) << 24) |
-            ((bits & 0xFF000000) << 8) |
-            ((bits & 0xFF00000000) >> 8) |
-            ((bits & 0xFF0000000000) >> 24) |
-            ((bits & 0xFF000000000000) >> 40) |
-            (bits >> 56);
-#endif
-    }
-
-    static int trailingZeroes   (U64 x) {
-#if __GNUC__ > 4 && __GNUC_MINOR__ >= 5
-        return __builtin_ctzll(x);
-#else
-        for (unsigned char i = 0; i < 64; i++)
-            if (x & (1 << i))
-                return i;
-#endif
-    }
+    inline Bitboard mirror(void) const                      { return byteswap(bits); }
 };
 
 

+ 56 - 2
src/BitOperations.h

@@ -1,16 +1,70 @@
 #ifndef CHESSY_BITOPERATIONS_H
 #define CHESSY_BITOPERATIONS_H 
 
+#include <cinttypes>
 
-namespace chessy
-{
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
 
 
+namespace chessy
+{
+    using U64 = uint64_t;
+    using U32 = uint32_t;
+    using U16 = uint16_t;
+    using U8  = uint8_t;
 
 
+    /*!
+     * reverses the byte order of a 64-bit integer
+     */
+    inline U64 byteswap(U64 x)
+    {
+#if __GNUC__ > 4 && __GNUC_MINOR__ >= 3
+        return __builtin_bswap64(x);
+#else
+        return (x << 56) |
+            ((x & 0xFF00) << 40) |
+            ((x & 0xFF0000) << 24) |
+            ((x & 0xFF000000) << 8) |
+            ((x & 0xFF00000000) >> 8) |
+            ((x & 0xFF0000000000) >> 24) |
+            ((x & 0xFF000000000000) >> 40) |
+            (x >> 56);
+#endif
+    }
 
+    /*!
+    * counts the trailing zeroes on a 64 bit integer
+    */
+    inline int trailingZeroes(U64 x) {
+#if __GNUC__ > 4 && 0
+        return __builtin_ctzll(x);
+#else
+        for (int i = 0; i < 64; i++)
+            if (x & (1ULL << i))
+                return i;
+        return 0;
+#endif
+    }
 
 
+    /*!
+    * counts the leading zeroes on a 64 bit integer
+    */
+    inline int leadingZeroes(U64 x) {
+#if __GNUC__ > 4
+        return __builtin_clzll(x);
+#elif defined(_MSC_VER) && defined(_M_X64)
+        return __lzcnt64(x);
+#else
+        for (int i = 0; i < 64; i++)
+            if (x & (1ULL << (63 - i)))
+                return i;
+        return 0;
+#endif
+    }
 }
 
 

+ 52 - 85
src/Board.cpp

@@ -9,51 +9,39 @@ using namespace chessy;
 using namespace std;
 
 
-Bitboard& Board::operator[] (int index)
-{
-    return (&whitePawns)[index];
-}
-
-
-const Bitboard& Board::operator[] (int index) const
-{
-    return (&whitePawns)[index];
-}
-
-
 void Board::resetBoard(void)
 {
-    whitePawns =    0x000000000000FF00;
-    whiteRooks =    0x0000000000000081;
-    whiteKnights =  0x0000000000000042;
-    whiteBishops =  0x0000000000000024;
-    whiteQueens =   0x0000000000000010;
-    whiteKing =     0x0000000000000008;
-
-    blackPawns =    0x00FF000000000000;
-    blackRooks =    0x8100000000000000;
-    blackKnights =  0x4200000000000000;
-    blackBishops =  0x2400000000000000;
-    blackQueens =   0x1000000000000000;
-    blackKing =     0x0800000000000000;
+    whites[PieceType::PAWN]   = 0x0000000000000081;
+    whites[PieceType::KNIGHT] = 0x0000000000000042;
+    whites[PieceType::BISHOP] = 0x0000000000000024;
+    whites[PieceType::ROOK]   = 0x0000000000000010;
+    whites[PieceType::QUEEN]  = 0x0000000000000008;
+    whites[PieceType::KING]   = 0x000000000000FF00;
+
+    blacks[PieceType::PAWN]   = 0x00FF000000000000;
+    blacks[PieceType::KNIGHT] = 0x8100000000000000;
+    blacks[PieceType::BISHOP] = 0x4200000000000000;
+    blacks[PieceType::ROOK]   = 0x2400000000000000;
+    blacks[PieceType::QUEEN]  = 0x1000000000000000;
+    blacks[PieceType::KING]   = 0x0800000000000000;
 }
 
 
 void Board::setEmpty(void)
 {
-    whitePawns =    0;
-    whiteRooks =    0;
-    whiteKnights =  0;
-    whiteBishops =  0;
-    whiteQueens =   0;
-    whiteKing =     0;
-
-    blackPawns =    0;
-    blackRooks =    0;
-    blackKnights =  0;
-    blackBishops =  0;
-    blackQueens =   0;
-    blackKing =     0;
+    whites[PieceType::PAWN] = 0;
+    whites[PieceType::KNIGHT] = 0;
+    whites[PieceType::BISHOP] = 0;
+    whites[PieceType::ROOK] = 0;
+    whites[PieceType::QUEEN] = 0;
+    whites[PieceType::KING] = 0;
+
+    blacks[PieceType::PAWN] = 0;
+    blacks[PieceType::KNIGHT] = 0;
+    blacks[PieceType::BISHOP] = 0;
+    blacks[PieceType::ROOK] = 0;
+    blacks[PieceType::QUEEN] = 0;
+    blacks[PieceType::KING] = 0;
 }
 
 
@@ -61,6 +49,7 @@ bool Board::tryToMove(Bitboard start, Bitboard end, Bitboard& b)
 {
     if (start & b)
         b = b ^ start ^ end;
+    return false;
 }
 
 
@@ -68,18 +57,18 @@ void Board::setBoard(const std::string& fenPosition)
 {
     int row = 0, column = 0;
     unordered_map<char, Bitboard*> boards {
-        {'p', &whitePawns},
-        {'n', &whiteKnights},
-        {'b', &whiteBishops},
-        {'r', &whiteRooks},
-        {'q', &whiteQueens},
-        {'k', &whiteKing},
-        {'P', &blackPawns},
-        {'N', &blackKnights},
-        {'B', &blackBishops},
-        {'R', &blackRooks},
-        {'Q', &blackQueens},
-        {'K', &blackKing}
+        { 'p', &whites[PieceType::PAWN] },
+        { 'n', &whites[PieceType::KNIGHT] },
+        { 'b', &whites[PieceType::BISHOP] },
+        { 'r', &whites[PieceType::ROOK] },
+        { 'q', &whites[PieceType::QUEEN] },
+        { 'k', &whites[PieceType::KING] },
+        { 'P', &blacks[PieceType::PAWN] },
+        { 'N', &blacks[PieceType::KNIGHT] },
+        { 'B', &blacks[PieceType::BISHOP] },
+        { 'R', &blacks[PieceType::ROOK] },
+        { 'Q', &blacks[PieceType::QUEEN] },
+        { 'K', &blacks[PieceType::KING] }
     };
     setEmpty();
     for (auto character : fenPosition) {
@@ -111,8 +100,8 @@ std::string Board::getFenBoard(void) const
     for (int row = 0; row < 8; row++) {
         int counter = 0;
         for (int column = 0; column < 8; column++) {
-            PieceType black = getBlackAtPosition({row, column});
-            PieceType white = getWhiteAtPosition({row, column});
+            PieceType black = getBlackAtPosition({ row, column });
+            PieceType white = getWhiteAtPosition({ row, column });
             //str << " " << Bitboard::fromIndex({row, column}) << " " << " ";;
             //str << "row,column,index: " << row << "," << column << "," <<
             //    int(Index(row, column).index) << " ";
@@ -138,6 +127,7 @@ std::string Board::getFenBoard(void) const
                     case PieceType::ROOK:   str << 'r'; break;
                     case PieceType::QUEEN:  str << 'q'; break;
                     case PieceType::KING:   str << 'k'; break;
+                    default:;
                 }
             }
         }
@@ -153,26 +143,20 @@ std::string Board::getFenBoard(void) const
 PieceType Board::getWhiteAtPosition(Index i) const
 {
     Bitboard mask = Bitboard::fromIndex(i);
-    if (whitePawns & mask)      return PieceType::PAWN;
-    if (whiteKnights & mask)    return PieceType::KNIGHT;
-    if (whiteBishops & mask)    return PieceType::BISHOP;
-    if (whiteRooks & mask)      return PieceType::ROOK;
-    if (whiteQueens & mask)     return PieceType::QUEEN;
-    if (whiteKing & mask)       return PieceType::KING;
-                                return PieceType::EMPTY;
+    for (int i = 0; i < 6; i++)
+        if (whites[i] & mask)
+            return (PieceType) i;
+    return PieceType::EMPTY;
 }
 
 
 PieceType Board::getBlackAtPosition(Index i) const
 {
     Bitboard mask = Bitboard::fromIndex(i);
-    if (blackPawns & mask)      return PieceType::PAWN;
-    if (blackKnights & mask)    return PieceType::KNIGHT;
-    if (blackBishops & mask)    return PieceType::BISHOP;
-    if (blackRooks & mask)      return PieceType::ROOK;
-    if (blackQueens & mask)     return PieceType::QUEEN;
-    if (blackKing & mask)       return PieceType::KING;
-                                return PieceType::EMPTY;
+    for (int i = 0; i < 6; i++)
+        if (blacks[i] & mask)
+            return (PieceType) i;
+    return PieceType::EMPTY;
 }
 
 
@@ -180,35 +164,18 @@ void Board::applyMove(const Move& move)
 {
     Bitboard start = Bitboard::fromIndex(move.origin);
     Bitboard end = Bitboard::fromIndex(move.destination);
-
-    tryToMove(start, end, whitePawns);
-    tryToMove(start, end, whiteRooks);
-    tryToMove(start, end, whiteKnights);
-    tryToMove(start, end, whiteBishops);
 }
 
 
 Bitboard Board::getWhites(void) const
 {
-    return
-        whitePawns |
-        whiteRooks |
-        whiteKnights |
-        whiteBishops |
-        whiteQueens |
-        whiteKing;
+    return whites[0] | whites[1] | whites[2] | whites[3] | whites[4] | whites[5];
 }
 
 
 Bitboard Board::getBlacks(void) const
 {
-    return
-        blackPawns |
-        blackRooks |
-        blackKnights |
-        blackBishops |
-        blackQueens |
-        blackKing;
+    return blacks[0] | blacks[1] | blacks[2] | blacks[3] | blacks[4] | blacks[5];
 }
 
 

+ 18 - 18
src/Board.h

@@ -8,13 +8,13 @@
 
 namespace chessy
 {
-    enum class PieceType : int;
+    enum PieceType : int;
 
     class Board;
 }
 
 
-enum class chessy::PieceType : int
+enum chessy::PieceType : int
 {
     EMPTY = -1,
     PAWN = 0,
@@ -28,28 +28,14 @@ enum class chessy::PieceType : int
 
 class chessy::Board
 {
-    Bitboard whitePawns;
-    Bitboard whiteKnights;
-    Bitboard whiteBishops;
-    Bitboard whiteRooks;
-    Bitboard whiteQueens;
-    Bitboard whiteKing;
-
-    Bitboard blackPawns;
-    Bitboard blackKnights;
-    Bitboard blackBishops;
-    Bitboard blackRooks;
-    Bitboard blackQueens;
-    Bitboard blackKing;
+    Bitboard whites[6];
+    Bitboard blacks[6];
 
 public:
     Board(void) = default;
     Board(const Board&) = default;
     ~Board(void) = default;
 
-    Bitboard& operator [] (int index);
-    const Bitboard& operator [] (int index) const;
-
     /*!
      * resets the board to the chess starting position.
      */
@@ -61,6 +47,20 @@ private:
     bool tryToMove(Bitboard start, Bitboard end, Bitboard& b);
 public:
 
+    Bitboard getWhitePawns(void) const { return whites[PAWN]; }
+    Bitboard getWhiteKnights(void) const { return whites[KNIGHT]; }
+    Bitboard getWhiteBishops(void) const { return whites[BISHOP]; }
+    Bitboard getWhiteRooks(void) const { return whites[ROOK]; }
+    Bitboard getWhiteQueens(void) const { return whites[QUEEN]; }
+    Bitboard getWhiteKings(void) const { return whites[KING]; }
+
+    Bitboard getBlackPawns(void) const { return blacks[PAWN]; }
+    Bitboard getBlackKnights(void) const { return blacks[KNIGHT]; }
+    Bitboard getBlackBishops(void) const { return blacks[BISHOP]; }
+    Bitboard getBlackRooks(void) const { return blacks[ROOK]; }
+    Bitboard getBlackQueens(void) const { return blacks[QUEEN]; }
+    Bitboard getBlackKings(void) const { return blacks[KING]; }
+
     /*!
      * parses the first part of a FEN string and sets the board
      * to the accourding position

+ 21 - 15
src/ChessGame.cpp

@@ -20,7 +20,6 @@ bool ChessGame::isValidMove(const Move& move) const
 std::vector<Move> ChessGame::getValidMoves(void) const
 {
     std::vector<Move> ret;
-
     return ret;
 }
 
@@ -48,8 +47,8 @@ void ChessGame::loadFromFen(const std::string& fenString)
     this->board.setBoard(board);
     this->enPassant = Index {enPassant};
 
-    if (turn == "w") this->turn = Turn::WHITE;
-    else if (turn == "b") this->turn = Turn::BLACK;
+    if (turn == "w"s) this->turn = Turn::WHITE;
+    else if (turn == "b"s) this->turn = Turn::BLACK;
     else throw runtime_error("invalid turn "s + turn);
 
     canCastleQueenSideWhite = false;
@@ -76,7 +75,14 @@ void ChessGame::loadFromFen(const std::string& fenString)
         }
     }
 
-    if (enPassant == "-") enPassant = -1;
+    if (enPassant == "-"s) {
+        this->enPassant = -1;
+    }
+    else {
+        if (enPassant.size() != 2 || (enPassant[1] != '3' && enPassant[1] != '6'))
+            throw runtime_error("invalid en passant string: "s + enPassant);
+        this->enPassant = Index{ enPassant };
+    }
 
     try {
         reversibleHalfMoves = stoi(halfmoves);
@@ -100,20 +106,20 @@ std::string ChessGame::generateFen(void) const
 
     string board = this->board.getFenBoard();
 
-    string turn = this->turn == Turn::WHITE ? "w" : "b";
- 
-    string castlingRights = ""s +
-        (canCastleKingSideBlack ? "K" : "") +
-        (canCastleQueenSideBlack ? "Q" : "") +
-        (canCastleKingSideWhite ? "k" : "") +
-        (canCastleQueenSideWhite ? "q" : "");
+    string turn = this->turn == Turn::WHITE ? "w"s : "b"s;
+
+    string castlingRights =
+        (canCastleKingSideBlack ? "K"s : ""s) +
+        (canCastleQueenSideBlack ? "Q"s : ""s) +
+        (canCastleKingSideWhite ? "k"s : ""s) +
+        (canCastleQueenSideWhite ? "q"s : ""s);
 
     string enPassant;
-    if (this->enPassant == -1)
-        enPassant = "-";
+    if (this->enPassant == -1) {
+        enPassant = "-"s;
+    }
     else {
-        auto a = this->enPassant.getName();
-        enPassant = {a[0], a[1]};
+        enPassant = this->enPassant.getName();
     }
 
     string halfmoves = to_string(reversibleHalfMoves);

+ 2 - 0
src/ChessGame.h

@@ -47,6 +47,8 @@ public:
     bool isValidMove(const Move& move) const;
     std::vector<Move> getValidMoves(void) const;
 
+    inline const Board& getBoard(void) const { return board; }
+
     void loadFromFen(const std::string& fenString);
     std::string generateFen(void) const;
 };

+ 19 - 4
src/MoveGeneration.cpp

@@ -3,12 +3,27 @@
 
 using namespace chessy;
 
-MoveGenerator::MoveIterator MoveGenerator::begin(void) const
+template class MoveGenerator<0>;
+template class MoveGenerator<1>;
+
+
+std::string chessy::Move::asString(void) const
 {
-    return MoveIterator{ chessGame.getBoard(). };
+    return origin.getName() + "-" + destination.getName();
 }
 
-MoveGenerator::MoveIterator chessy::MoveGenerator::end(void) const
+
+template<int side>
+typename MoveGenerator<side>::MoveIterator MoveGenerator<side>::begin(void) const
 {
-    return MoveIterator();
+    return MoveIterator{ chessGame.getBoard().getWhitePawns() };
 }
+
+
+template<int side>
+typename MoveGenerator<side>::MoveIterator chessy::MoveGenerator<side>::end(void) const
+{
+    return MoveIterator{ PositionSet::end() };
+}
+
+

+ 27 - 11
src/MoveGeneration.h

@@ -2,13 +2,18 @@
 #define CHESSY_MOVEGENERATION_H
 
 #include "BitBoard.h"
+#include <string>
 
 namespace chessy
 {
     struct Move;
 
+    // forward declaration
+    class ChessGame;
+
     class PositionSet;
 
+    template<int side>
     class MoveGenerator;
 }
 
@@ -24,6 +29,8 @@ struct chessy::Move
 
     inline Move(Index origin, Index destination) :
         origin{origin}, destination{destination} {}
+
+    std::string asString(void) const;
 };
 
 
@@ -32,20 +39,21 @@ class chessy::PositionSet
     Bitboard bitboard;
 
 public:
+
+    inline PositionSet(Bitboard b) : bitboard{ b } {}
+
     struct PositionSetIterator
     {
         Bitboard bitboard;
 
         inline Index operator *(void) const
         {
-            //if (bitboard == Bitboard(0)) return -1;
-            return Bitboard::trailingZeroes(bitboard.bits);
+            return Index{ int8_t(trailingZeroes(bitboard.bits)) };
         }
 
         inline void operator ++(void)
-        {
-            // remove least significant one-bit
-            bitboard.bits &= bitboard.bits - 1;
+        {            
+            bitboard.bits &= bitboard.bits - 1ULL; // remove least significant one bit
         }
 
         inline bool operator !=(const PositionSetIterator& psi) const
@@ -56,24 +64,28 @@ public:
 
     inline PositionSetIterator begin(void) const
     {
-        return PositionSetIterator {bitboard};
+        return PositionSetIterator{ bitboard };
     }
-    inline PositionSetIterator end(void) const
+
+    inline static PositionSetIterator end(void)
     {
-        return PositionSetIterator {0};
+        return PositionSetIterator{ 0 };
     }
 };
 
 
+template<int side>
 class chessy::MoveGenerator
 {
+    const ChessGame& chessGame;
+
     struct MoveIterator
     {
         PositionSet::PositionSetIterator pawnPushes;
         inline Move operator *(void) const
         {
             Index pp = *pawnPushes;
-            return Move(pp - 8, pp);
+            return Move{ int8_t(pp + side == 0 ? 8 : -8), pp };
         }
 
         inline void operator ++(void)
@@ -83,11 +95,15 @@ class chessy::MoveGenerator
 
         inline bool operator !=(const MoveIterator& psi) const
         {
-            pawnPushes != PositionSet::PositionSetIterator {0};
+            pawnPushes != psi.pawnPushes;
         }
     };
 public:
-    MoveGenerator(void);
+    inline MoveGenerator(const ChessGame& cg) : chessGame{ cg } {}
+
+    MoveIterator begin(void) const;
+    MoveIterator end(void) const;
+
     //PawnPushProducer generatePawnPushes(void) const;
 };
 

+ 2 - 2
src/UciParser.cpp

@@ -26,12 +26,12 @@ int UciParser::executeLine(const string& line)
     while (s >> token) {
         args.push_back(token);
     }
-    executeCommand(command, args);
+    return executeCommand(command, args);
 }
 
 
 int UciParser::executeCommand(const string& command,
     const vector<string>& args)
 {
-
+    return 0;
 }

+ 14 - 2
src/main.cpp

@@ -1,6 +1,7 @@
 #include <iostream>
 #include "UciParser.h"
 #include "ChessGame.h"
+#include "MoveGeneration.h"
 
 using namespace std;
 
@@ -9,8 +10,19 @@ auto main() -> int
     chessy::ChessGame cg;
     string line;
     getline(cin, line);
-    cg.loadFromFen(line);
-    cout << cg.generateFen();
+    try {
+        cg.loadFromFen(line);
+        cout << cg.generateFen() << endl;
+        chessy::MoveGenerator<0> mg{ cg };
+        for (auto pos : mg) {
+            cout << pos.asString() << endl;
+        }
+    }
+    catch (runtime_error& re) {
+        cerr << re.what() << endl;
+        return 1;
+    }
+    cin.get();
     return 0;
     UciParser uciParser;
     uciParser.parse(cin, cout);

+ 1 - 1
src/makefile

@@ -3,7 +3,7 @@ CXX=        g++
 CXXFLAGS=   -std=c++14
 LNFLAGS=    
 DEPS=       Bitfield.h
-OBJ=        main.o Board.o ChessGame.o UciParser.o
+OBJ=        main.o Board.o ChessGame.o UciParser.o MoveGeneration.o
 
 
 %.o: %.c $(DEPS)