void GameSession::black_requestsTakeback() { if(game_.position().moveNumber()>1) { ChessCoord prevCursorPos; unsigned nmoves = game_.moves().size(); if(nmoves>=2) prevCursorPos = game_.moves()[nmoves-2].from; // bool accept = false; whitePlayer_->opponentRequestsTakeback(accept); // if(accept) { game_.takebackOneFullMove(); updateSessionInfo(); // g_localChessGui.dropLastFullMove(); g_localChessGui.setInitialMoveCursorPos(prevCursorPos); g_localChessGui.updatePosition(game_.position(), game_.lastMove(), game_.possibleMoves()); updateCapturedPieces(); //updateClockDisplay(); } } requestMove(blackPlayer_); }
void GameSession::black_moves(const ChessMove& move) { if(game_.position().sideToMove()!=pcBlack) { assert(false); // report error: attempt to move out of turn return; } // if(!game_.applyMove(move)) { blackPlayer_->illegalMove(); g_localChessGui.showSessionMessage(g_msg("IllegalMove").arg(move.toString().c_str())); requestMove(blackPlayer_); } else { updateSessionInfo(); // if(whiteDrawOfferActive_) { whitePlayer_->opponentRejectsDraw(); } // if(game_.position().moveNumber()==2) { enableInGameCommands(); } // blackDrawOfferActive_ = false; // blackClock_.remainingTime += blackClock_.moveIncrement; // outputLastMove(); //updateClockDisplay(); g_localChessGui.updatePosition(game_.position(), game_.lastMove(), game_.possibleMoves()); updateCapturedPieces(); // whitePlayer_->opponentMoves(move); if(game_.result()==resultNone && whiteClock_.remainingTime > 0) { requestMove(whitePlayer_); } } }
void Game::start() { if (!white_ && !black_) throw NoPlayersSet(); else if (!white_ || !black_) throw OnlyOnePlayerSet(); currentPlayer_ = white_.get(); gameState_->currentMove = 1; gameState_->currentPlayer = currentPlayer_->type(); requestMove(); }
void Game::prepareNextMoveRequest() { switchCurrentPlayer(); GameResult result; if (GameResult::ONGOING != (result = gameStateIndicator_->indicateGameEnd( gameState_->currentPlayer, gameState_->currentBoard))) { endGame(result); return; } requestMove(); }
void GameSession::black_requestsAbort() { bool accepted = true; if(game_.position().moveNumber()>1) whitePlayer_->opponentRequestsAbort(accepted); if(accepted) { endGame(reasonGameAborted, resultNone); } else { requestMove(blackPlayer_); } }
void Game::receiveMove(const Move& move) { if (validator_->validate(move, currentPlayer_->type())) { currentPlayer_->responseAck(true); if (!applyMove(move)) return; prepareNextMoveRequest(); } else { currentPlayer_->responseAck(false); requestMove(); } }
Controller::Controller(sf::Window &theWindow, sfg::Desktop &theDesktop, CallbackSystem &callbackSystem): desktop(theDesktop), boardWindow(sfg::Window::Create(sfg::Window::BACKGROUND)), settingsButton(sfg::Button::Create("Settings")), canvas(theWindow), m_whiteClock(Clock::Create()), m_blackClock(Clock::Create()), settingsWindow(desktop), premove({{0,0},{0,0}}), premoveOn(false), netWindow(m_currentEvent), player1(sfg::Label::Create()), player2(sfg::Label::Create()) { boardWindow->SetRequisition(static_cast<sf::Vector2f>(theWindow.getSize())); canvas.requestMove.connect(boost::bind(&Controller::requestMove, this,_1)); settingsWindow.settingsDone.connect([this](const PieceToTexPos& pieceToTexPos){ settingsWindow.enable(false); canvas.setPieceColors(pieceToTexPos); }); messages.connect(Messages::ID::TextReady, [this](const Messages::Message& message){ auto received = boost::polymorphic_downcast<const Messages::TextReady*>(&message); netWindow.addLine(received->text); }); ButtonBox buttons; buttons.flip->GetSignal(sfg::Button::OnLeftClick).Connect(std::bind(&Canvas::flipBoard, &canvas)); buttons.settings->GetSignal(sfg::Button::OnLeftClick).Connect([]{ //settingsWindow.enable(true); }); buttons.resign->GetSignal(sfg::Button::OnLeftClick).Connect([this]{ messages.triggerEvent(Messages::TextToClient("resign")); }); buttons.draw->GetSignal(sfg::Button::OnLeftClick).Connect([this]{ messages.triggerEvent(Messages::TextToClient("draw")); }); auto promotionLayout = sfg::Box::Create(sfg::Box::Orientation::VERTICAL); auto promotionGroup = sfg::RadioButtonGroup::Create(); auto createPromotionButton = [this, promotionGroup, promotionLayout](const std::string& name, char letter){ auto promotionButton = sfg::RadioButton::Create(name, promotionGroup); promotionLayout->Pack(promotionButton); promotionButton->GetSignal(sfg::ToggleButton::OnToggle).Connect([this, promotionButton, letter]{ if (promotionButton->IsActive()){ std::string promote("promote "); promote += letter; messages.triggerEvent(Messages::TextToClient(promote)); } }); return promotionButton; }; auto promotionQueen = createPromotionButton("Queen", 'q'); createPromotionButton("Bishop", 'b'); createPromotionButton("Knight", 'n'); createPromotionButton("Rook", 'r'); auto promotionFrame = sfg::Frame::Create("Promotion"); promotionFrame->Add(promotionLayout); auto sideLayout = sfg::Box::Create(sfg::Box::Orientation::VERTICAL); sideLayout->Pack(player1); sideLayout->Pack(m_whiteClock); sideLayout->Pack(player2); sideLayout->Pack(m_blackClock); sideLayout->Pack(status.getView()); sfg::Table::Ptr mainLayout(sfg::Table::Create()); mainLayout->SetRowSpacings(2.f); mainLayout->SetColumnSpacings(2.f); mainLayout->Attach(canvas.getBoardWidget(),{0, 0, 3, 2},sfg::Table::EXPAND, sfg::Table::EXPAND, sf::Vector2f( 10.f, 0.f )); mainLayout->Attach(promotionFrame, {0, 2, 1, 1}); mainLayout->Attach(sideLayout, {3,0, 3, 1}); mainLayout->Attach(moveList.getView(),{3, 1, 3, 3}); mainLayout->Attach(buttons.layout,{0,4,6,1}); desktop.Add(settingsWindow.getWidget()); sfg::Notebook::Ptr notebook(sfg::Notebook::Create()); notebook->AppendPage(mainLayout,sfg::Label::Create("Board")); notebook->AppendPage(netWindow.getWidget(),sfg::Label::Create("Server")); notebook->GetSignal(sfg::Notebook::OnTabChange).Connect([this]{ netWindow.grabEntryFocus(); }); callbackSystem.connect(Action::Tab, [notebook](thor::ActionContext<Action> context){ if (context.event->key.control){ if (context.event->key.shift) notebook->PreviousPage(); else notebook->NextPage(); } }); boardWindow->Add(notebook); desktop.Add(boardWindow); buttons.connect->GetSignal(sfg::Button::OnLeftClick).Connect([this, notebook]{ client.connect(); notebook->SetCurrentPage(1); }); messages.connect(Messages::ID::GameState, [this](const Messages::Message& message){ auto received = boost::polymorphic_downcast<const Messages::GameState*>(&message); m_whiteClock->setTimeLeft(received->white_time); m_blackClock->setTimeLeft(received->black_time); if (received->turnColor == Color::White){ m_blackClock->stop(); m_whiteClock->start(); }else{ assert(received->turnColor==Color::Black); m_whiteClock->stop(); m_blackClock->start(); } if (premoveOn) { premoveOn = false; canvas.clearArrows(); requestMove(premove); } }); messages.connect(Messages::ID::GameStart, [this, promotionQueen, notebook](const Messages::Message& message){ auto received = boost::polymorphic_downcast<const Messages::GameStart*>(&message); player1->SetText(received->p1); player2->SetText(received->p2); premoveOn = false; promotionQueen->SetActive(true); updateClocks(); notebook->SetCurrentPage(0); }); messages.connect(Messages::ID::GameEnd, [this](const Messages::Message&){ //auto received = boost::polymorphic_downcast<const EndGameMessage*>(&message); premoveOn = false; canvas.clearArrows(); m_whiteClock->stop(); m_blackClock->stop(); }); callbackSystem.connect(Action::Scroll, [this](thor::ActionContext<Action> context){ int delta = context.event->mouseWheelScroll.delta; netWindow.scroll(delta); }); }
void GameSession::startGame() { whiteClock_ = sessionInfo_.profile.whiteClock; blackClock_ = sessionInfo_.profile.blackClock; // if(whiteClock_.untimed) { whiteClock_.initialTime = 10*60*1000; whiteClock_.remainingTime = whiteClock_.initialTime; whiteClock_.moveIncrement = 0; } // if(blackClock_.untimed) { blackClock_.initialTime = 10*60*1000; blackClock_.remainingTime = blackClock_.initialTime; blackClock_.moveIncrement = 0; } // g_localChessGui.beginGame(whitePlayer_->name(), blackPlayer_->name(), sessionInfo_.profile, !sessionInfo_.moves.empty()); // whitePlayer_->beginGame(pcWhite, blackPlayer_->name(), whiteClock_); blackPlayer_->beginGame(pcBlack, whitePlayer_->name(), blackClock_); // game_.start(sessionInfo_.initialPosition); // start from the given initial position // default position for standard chess // but may be different for chess960 // whitePlayer_->setInitialPosition(game_.position()); blackPlayer_->setInitialPosition(game_.position()); // if(!sessionInfo_.moves.empty()) { // replay moves one by one // std::vector<ChessMove>::const_iterator it = sessionInfo_.moves.begin(), itEnd = sessionInfo_.moves.end(); for(;it!=itEnd;++it) { whitePlayer_->replayMove(*it); blackPlayer_->replayMove(*it); // bool moveOk = game_.applyMove(*it); // assert(moveOk); } } // if(game_.result()!=resultNone) { // a game end signal has come while replaying moves return; } // if(game_.position().moveNumber()>=2) { enableInGameCommands(); } // if(!game_.moves().empty()) { if(g_settings.useRussianNotation()) g_localChessGui.appendToMoveList(game_.ruMoves()); else g_localChessGui.appendToMoveList(game_.sanMoves()); } // // finished setting up position, can actually start the game // g_localChessGui.updatePosition(game_.position(), game_.lastMove(), game_.possibleMoves()); updateCapturedPieces(); //updateClockDisplay(); // counter_.restart(); // clockUpdateTimer_.setInterval(cClockUpdateInterval); clockUpdateTimer_.setSingleShot(false); clockUpdateTimer_.start(); // if(game_.position().sideToMove()==pcWhite) requestMove(whitePlayer_); else requestMove(blackPlayer_); // }