TheChess
|
00001 /* 00002 * thechess, chess game web application written in C++ and based on Wt 00003 * Copyright (C) 2010 Boris Nagaev 00004 * 00005 * thechess is licensed under the GNU GPL Version 2. 00006 * Other versions of the GPL do not apply. 00007 * See the LICENSE file for terms of use. 00008 */ 00009 00010 // 00011 00012 #ifndef THECHESS_MOVES_H_ 00013 #define THECHESS_MOVES_H_ 00014 00015 namespace thechess { 00016 namespace chess { 00017 struct MovesCheck; 00018 class Moves; 00019 class MovesIterator; 00020 } 00021 } 00022 00023 #include <vector> 00024 00025 #include "move.hpp" 00026 #include "xy.hpp" 00027 #include "board.hpp" 00028 #include "tests.hpp" 00029 00030 typedef unsigned char byte; 00031 00032 namespace thechess { 00033 namespace chess { 00034 00035 struct MovesCheck { 00036 bool correct; 00037 int move_with_error; 00038 Board board; 00039 }; 00040 00041 enum Xy_type { 00042 xy_from = 0, 00043 xy_to = 1 00044 }; 00045 00046 typedef std::vector<byte> svuc; 00047 00048 class Moves : public svuc { 00049 public: 00050 Moves(int moves_count=0); 00051 Moves(Move moves[], int moves_count); 00052 const svuc& as_svuc() const { 00053 return *this; 00054 } 00055 svuc& as_svuc() { 00056 return *this; 00057 } 00058 int size() const { 00059 return (this->svuc::size() * 8) / 12; 00060 } 00061 00062 void push_move(Move move); 00063 void pop_move(); 00064 void pop_moves(int number); 00065 00066 Move move_at(int n, const Board& board) const { 00067 return Move(xy_(n, xy_from), xy_(n, xy_to), board); 00068 } 00069 Move move_at(int n) const { 00070 return Move(xy_(n, xy_from), xy_(n, xy_to)); 00071 } 00072 Board board_at(int n) const; // returns board position BEFORE move number n 00073 00074 int check() const; // -1 = no errors, other value -- n of wrong move 00075 00076 static int n_to_human(int move_n) { 00077 return (move_n + 2) / 2; 00078 } 00079 static int size_to_human(int size) { 00080 return n_to_human(size - 1); 00081 } 00082 static int n_from_human(int human_i, Color color) { 00083 return (human_i - 1) * 2 + ((color == white) ? 0 : 1); 00084 } 00085 int human_size() const { 00086 return size_to_human(size()); 00087 } 00088 00089 static int order_int(int move_n) { 00090 return move_n % 2; 00091 } 00092 static Color order(int move_n) { 00093 return order_int(move_n) == 0 ? white : black; 00094 } 00095 00096 void pgn(std::ostream& out, const std::string& result, 00097 bool reduced=false) const; 00098 00099 private: 00100 byte q(int i) const { 00101 return (byte)((*this)[i]); 00102 } 00103 00104 Xy xy_(int i) const; 00105 Xy xy_(int n, Xy_type xy_type) const { 00106 return xy_(n * 2 + (int)xy_type); 00107 } 00108 void xy_(int i, Xy xy); 00109 void xy_(int n, Xy_type xy_type, Xy xy) { 00110 xy_(n * 2 + (int)xy_type, xy); 00111 } 00112 00113 void set_move(int n, Move move); 00114 void fill(int moves_count); 00115 friend void run_tests(); 00116 }; 00117 00118 class MovesIterator { 00119 public: 00120 MovesIterator(const Moves* moves, Board& board, int from=0); 00121 //~ MovesIterator(const Moves* moves, int from=0); 00122 Move move() const { 00123 return moves_->move_at(n, board_); 00124 } 00125 Move operator*() const { 00126 return move(); 00127 } 00128 MovesIterator& operator ++() { 00129 board_.make_move(move()); 00130 n++; 00131 return *this; 00132 } 00133 const Moves* moves_; 00134 Board& board_; 00135 int n; 00136 }; 00137 00138 00139 #define THECHESS_MOVES_FROM_TO(move_it, moves, board, from, to) \ 00140 for (thechess::chess::MovesIterator move_it = \ 00141 thechess::chess::MovesIterator(moves, board, from); \ 00142 move_it.n < to; ++move_it) 00143 00144 #define THECHESS_MOVES_TO(move_it, moves, board, to) \ 00145 THECHESS_MOVES_FROM_TO(move_it, moves, board, 0, to) 00146 00147 #define THECHESS_MOVES_FROM(move_it, moves, board, from) \ 00148 THECHESS_MOVES_FROM_TO(move_it, moves, board, from, (moves)->size()) 00149 00150 #define THECHESS_MOVES_FOREACH(move_it, moves, board) \ 00151 THECHESS_MOVES_FROM(move_it, moves, board, 0) 00152 00153 } 00154 } 00155 00156 00157 /* moves_: 00158 * each move takes 12 bites, each Xy -- 6 bits, each coordinate -- 3 bits 00159 * pair of moves -- 3 bytes 00160 */ 00161 00162 #endif // THECHESS_MOVES_H_ 00163