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 #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