TheChess

model/Game.hpp

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 #ifndef THECHESS_MODEL_GAME_H_
00011 #define THECHESS_MODEL_GAME_H_
00012 
00013 #include <string>
00014 #include <vector>
00015 
00016 #include <Wt/WObject>
00017 #include <Wt/WString>
00018 #include <Wt/Dbo/Dbo>
00019 #include <Wt/Dbo/ptr>
00020 namespace dbo = Wt::Dbo;
00021 #include <Wt/WDateTime>
00022 #include <Wt/Dbo/WtSqlTraits>
00023 
00024 namespace thechess {
00025 namespace model {
00026 class Game;
00027 typedef dbo::ptr<Game> GamePtr;
00028 typedef dbo::collection<GamePtr> Games;
00029 typedef std::vector<GamePtr> GamesVector;
00030 }
00031 }
00032 
00033 #include "model/GameParameters.hpp"
00034 #include "model/User.hpp"
00035 #include "model/Competition.hpp"
00036 #include "model/td.hpp"
00037 #include "model/Object.hpp"
00038 
00039 namespace thechess {
00040 namespace model {
00041 
00051 class Game : public GameParameters, public dbo::Dbo<Game> {
00052 public:
00053     enum State {
00054         proposed = 0, 
00055         confirmed = 10, 
00056         active = 20, 
00057         pause = 30, 
00058 #ifndef DOXYGEN_ONLY
00059         min_ended = 50,
00060 #endif
00061         draw_stalemate = 50, 
00062         draw_agreed = 51, 
00063         draw_50 = 52, 
00064         draw_3 = 53, 
00065         draw_2_kings = 54, 
00066         surrendered = 61, 
00067         timeout = 62, 
00068         cancelled = 63, 
00069         mate = 64, 
00070         no_draw_stalemate = 65 
00071     };
00072 
00073 #ifndef DOXYGEN_ONLY
00074     Game();
00075 #endif
00076 
00078     /* @{ */
00079 
00081     Game(bool);
00082 
00083 #ifndef DOXYGEN_ONLY
00084     template<class Action>
00085     void persist(Action& a) {
00086         GameParameters::persist(a);
00087         dbo::field(a, state_, "state");
00088         dbo::belongsTo(a, white_, "white");
00089         dbo::belongsTo(a, black_, "black");
00090         dbo::belongsTo(a, winner_, "winner_game");
00091         dbo::belongsTo(a, init_, "init_game");
00092         dbo::field(a, competition_confirmer_[chess::white], "competition_confirmer_white");
00093         dbo::field(a, competition_confirmer_[chess::black], "competition_confirmer_black");
00094         dbo::field(a, colors_random_, "colors_random");
00095         dbo::field(a, created_, "created");
00096         dbo::field(a, confirmed_, "confirmed");
00097         dbo::field(a, started_, "started");
00098         dbo::field(a, lastmove_, "lastmove");
00099         dbo::field(a, ended_, "ended");
00100         dbo::field(a, limit_private_[chess::white], "limit_private_white");
00101         dbo::field(a, limit_private_[chess::black], "limit_private_black");
00102         dbo::belongsTo(a, competition_, "competition");
00103         dbo::field(a, competition_stage_, "competition_stage");
00104         dbo::field(a, pause_until_, "pause_until");
00105         dbo::field(a, pause_limit_, "pause_limit");
00106         dbo::field(a, pause_proposed_td_, "pause_proposed_td");
00107         dbo::field(a, pause_proposer_, "pause_proposer");
00108         dbo::field(a, mistake_move_, "mistake_move");
00109         dbo::field(a, mistake_proposer_, "mistake_proposer");
00110         dbo::field(a, draw_proposer_, "draw_proposer");
00111         dbo::field(a, rating_after_[chess::white], "rating_after_white");
00112         dbo::field(a, rating_after_[chess::black], "rating_after_black");
00113         dbo::field(a, comment_, "comment");
00114     }
00115 #endif
00116 
00122     void propose_game(UserPtr init, UserPtr u,
00123                       chess::Color c);
00124 
00129     void propose_challenge(UserPtr init, chess::Color c);
00130 
00138     void make_competition_game(UserPtr white, UserPtr black,
00139                                CompetitionPtr competition, int competition_stage=-1, bool random=false);
00140 
00141     /* @} */
00142 
00144     /* @{ */
00145 
00159     void check(Objects& objects);
00160 
00162     Wt::WDateTime next_check() const;
00163 
00164     /* @} */
00165 
00167     /* @{ */
00168 
00170     bool is_challenge() const;
00171 
00173     bool is_creation() const;
00174 
00178     bool can_join(UserPtr user) const;
00179 
00183     void join(UserPtr user);
00184 
00188     bool can_confirm(UserPtr user) const;
00189 
00193     void confirm(UserPtr user);
00194 
00198     bool can_cancel(UserPtr user) const;
00199 
00203     void cancel(UserPtr user);
00204 
00205     /* @} */
00206 
00208     /* @{ */
00209 
00211     bool can_pause_propose(const UserPtr user) const;
00212 
00214     bool can_pause_propose(const UserPtr user, const Td& td) const;
00215 
00217     void pause_propose(const UserPtr user, const Td& td);
00218 
00220     bool is_pause_proposed() const;
00221 
00223     const UserPtr pause_proposer() const {
00224         return pause_proposer_;
00225     }
00226 
00228     Td pause_limit() const {
00229         return pause_limit_;
00230     }
00231 
00233     Td pause_proposed_td() const {
00234         return pause_proposed_td_;
00235     }
00236 
00238     const Wt::WDateTime& pause_until() const {
00239         return pause_until_;
00240     }
00241 
00243     Wt::WDateTime pause_started() const;
00244 
00246     bool can_pause_agree(const UserPtr user) const;
00247 
00249     void pause_agree(const UserPtr user);
00250 
00252     bool can_pause_discard(const UserPtr user) const;
00253 
00255     void pause_discard(const UserPtr user);
00256 
00257     /* @} */
00258 
00260     /* @{ */
00261 
00263     bool can_mistake_propose(const UserPtr user) const;
00264 
00266     bool can_mistake_propose(const UserPtr user, int mistake_move) const;
00267 
00269     void mistake_propose(const UserPtr user, int mistake_move);
00270 
00272     bool is_mistake_proposed() const;
00273 
00275     const UserPtr mistake_proposer() const {
00276         return mistake_proposer_;
00277     }
00278 
00280     int mistake_move() const {
00281         return mistake_move_;
00282     }
00283 
00285     bool can_mistake_agree(const UserPtr user) const;
00286 
00288     void mistake_agree(const UserPtr user);
00289 
00291     bool can_mistake_discard(const UserPtr user) const;
00292 
00294     void mistake_discard(const UserPtr user);
00295 
00296     /* @} */
00297 
00299     /* @{ */
00300 
00302     bool can_draw_propose(const UserPtr user) const;
00303 
00305     void draw_propose(const UserPtr user);
00306 
00308     const UserPtr draw_proposer() const {
00309         return draw_proposer_;
00310     }
00311 
00313     bool is_draw_proposed() const {
00314         return draw_proposer_;
00315     }
00316 
00318     bool can_draw_agree(const UserPtr user) const;
00319 
00321     void draw_agree(const UserPtr user);
00322 
00324     bool can_draw_discard(const UserPtr user) const;
00325 
00327     void draw_discard(const UserPtr user);
00328 
00329     /* @} */
00330 
00332     /* @{ */
00333 
00335     chess::Color order_color() const;
00336 
00338     UserPtr order_user() const;
00339 
00341     UserPtr init() const {
00342         return init_;
00343     }
00344 
00346     UserPtr white() const {
00347         return white_;
00348     }
00349 
00351     UserPtr black() const {
00352         return black_;
00353     }
00354 
00356     UserPtr winner() const {
00357         return winner_;
00358     }
00359 
00361     chess::Color color_of(const UserPtr user) const;
00362 
00364     bool is_member(const UserPtr user) const;
00365 
00367     UserPtr user_of(chess::Color color) const;
00368 
00370     UserPtr other_user(const UserPtr user) const;
00371 
00372     /* @} */
00373 
00375     /* @{ */
00376 
00378     int size() const {
00379         return moves_.size();
00380     }
00381 
00383     int size_without_init() const;
00384 
00386     bool meet_first_draw() const;
00387 
00389     bool real_rating() const;
00390 
00392     int human_size() const {
00393         return chess::Moves::size_to_human(size());
00394     }
00395 
00397     bool is_ended() const;
00398 
00400     bool is_draw() const;
00401 
00403     bool is_win() const;
00404 
00406     Wt::WString str_state() const;
00407 
00409     State state() const {
00410         return state_;
00411     }
00412 
00414     bool colors_random() const {
00415         return colors_random_;
00416     }
00417 
00419     int rating_after(chess::Color color) const;
00420 
00421     /* @} */
00422 
00424     /* @{ */
00425 
00427     bool can_move(UserPtr user) const;
00428 
00433     void add_move(const chess::Move& move,
00434                   const chess::Board& board_after);
00435 
00436     /* @} */
00437 
00439     /* @{ */
00440 
00442     Td limit_private(chess::Color color) const;
00443 
00445     Td limit_private(UserPtr user) const;
00446 
00448     Td limit_private() const {
00449         return limit_private(order_color());
00450     }
00451 
00453     const Wt::WDateTime& created() const {
00454         return created_;
00455     }
00456 
00458     const Wt::WDateTime& when_confirmed() const {
00459         return confirmed_;
00460     }
00461 
00463     const Wt::WDateTime& started() const {
00464         return started_;
00465     }
00466 
00470     const Wt::WDateTime& lastmove() const {
00471         return lastmove_;
00472     }
00473 
00475     const Wt::WDateTime& ended() const {
00476         return ended_;
00477     }
00478 
00480     Td spent_time() const;
00481 
00483     Td spent_time(UserPtr user) const;
00484 
00486     Td total_limit(UserPtr user) const;
00487 
00489     Td total_limit_now(UserPtr user) const;
00490 
00492     Td limit_private_now(UserPtr user) const;
00493 
00495     Td limit_std_now(UserPtr user) const;
00496 
00497     /* @} */
00498 
00500     /* @{ */
00501 
00503     const Wt::WString& comment() const {
00504         return comment_;
00505     }
00506 
00508     bool can_comment(const UserPtr user) const;
00509 
00511     void set_comment(const UserPtr user, const Wt::WString& t);
00512 
00513     /* @} */
00514 
00516     /* @{ */
00517 
00519     CompetitionPtr competition() const {
00520         return competition_;
00521     }
00522 
00524     int competition_stage() const {
00525         return competition_stage_;
00526     }
00527 
00529     bool has_competition_confirmed(UserPtr user) const;
00530 
00532     bool can_competition_confirm(UserPtr user) const;
00533 
00535     void competition_confirm(UserPtr user);
00536 
00538     bool can_competition_discard(UserPtr user) const;
00539 
00541     void competition_discard(UserPtr user);
00542 
00546     void confirm_by_competition();
00547 
00548     /* @} */
00549 
00555     void pgn(std::ostream& out, bool reduced=false) const;
00556 
00558     static const char* state2str_id(State state);
00559 
00560 private:
00561     State state_;
00562 
00563     UserPtr white_;
00564     UserPtr black_;
00565     UserPtr winner_;
00566 
00567     UserPtr init_;
00568     bool competition_confirmer_[2]; // used with competition games only
00569     bool colors_random_;
00570 
00571     Wt::WDateTime created_;
00572     Wt::WDateTime confirmed_;
00573     Wt::WDateTime started_;
00574     Wt::WDateTime lastmove_;
00575     Wt::WDateTime ended_;
00576 
00577     Td limit_private_[2];
00578 
00579     CompetitionPtr competition_;
00580     int competition_stage_;
00581 
00582     Wt::WDateTime pause_until_;
00583     Td pause_limit_;
00584     Td pause_proposed_td_;
00585     UserPtr pause_proposer_;
00586 
00587     int mistake_move_; // -1 => no mistake proposed
00588     UserPtr mistake_proposer_;
00589 
00590     UserPtr draw_proposer_;
00591 
00592     int rating_after_[2];
00593 
00594     Wt::WString comment_;
00595 
00596     void set_white_(UserPtr user) {
00597         white_ = user;
00598     }
00599     void set_black_(UserPtr user) {
00600         black_ = user;
00601     }
00602     void set_of_color_(UserPtr user, chess::Color color);
00603     void set_random_(UserPtr user1, UserPtr user2);
00604 
00605     void confirm_();
00606     void start_();
00607     void stop_pause_();
00608     void finish_(State state, UserPtr winner=UserPtr());
00609     void elo_change_();
00610 
00611     void push_move_(chess::Move move);
00612     void pop_moves_(int number);
00613 
00614     const char* pgn_termination_() const;
00615     void pgn_init_moves_(std::ostream& out) const;
00616     void pgn_additional_(std::ostream& out) const;
00617 };
00618 
00619 }
00620 }
00621 
00622 #endif // THECHESS_MODEL_GAME_H_
00623 
 All Classes Functions Enumerations Enumerator