void playmp_controller::process_network_data(bool chat_only) { if(end_turn_ == END_TURN_SYNCED || is_regular_game_end() || player_type_changed_) { return; } turn_info::PROCESS_DATA_RESULT res = turn_info::PROCESS_CONTINUE; config cfg; if(!resources::recorder->at_end()) { res = turn_info::replay_to_process_data_result(do_replay()); } else if(network_reader_.read(cfg)) { res = turn_data_.process_network_data(cfg, chat_only); } if (res == turn_info::PROCESS_CANNOT_HANDLE) { network_reader_.push_front(std::move(cfg)); } else if (res == turn_info::PROCESS_RESTART_TURN) { player_type_changed_ = true; } else if (res == turn_info::PROCESS_END_TURN) { end_turn_ = END_TURN_SYNCED; } else if (res == turn_info::PROCESS_END_LEVEL) { } else if (res == turn_info::PROCESS_END_LINGER) { replay::process_error("Received unexpected next_scenario during the game"); } }
static int start_file(char *name) { char buf[MAXFILENAME+20]; int fd; if (play_f!=-1) { replay_abort(); close(play_f); play_f=-1; CancelWaitableTimer(timer); replay_pause(); set_buttons(0); } fd=open_stream(-1, name, SM_READ, 0); if (fd==-1) return 0; play_f=fd; play_format=ttyrec_r_find_format(0, name, "baudrate"); play_filename=name; replay_start(); snprintf(buf, sizeof(buf), "Termplay: %s (%s)", filename, play_format); SetWindowText(wndMain, buf); set_toolbar_state(1); play_state=2; do_replay(); return 1; }
possible_end_play_signal playmp_controller::play_network_turn(){ LOG_NG << "is networked...\n"; end_turn_enable(false); turn_data_.send_data(); for(;;) { if (!network_processing_stopped_){ config cfg; if(network_reader_.read(cfg)) { if (replay_last_turn_ <= turn()){ if (skip_replay_) { skip_replay_ = false; } } turn_info::PROCESS_DATA_RESULT result; HANDLE_END_PLAY_SIGNAL ( result = turn_data_.process_network_data(cfg, skip_replay_) ); if(player_type_changed_ == true) { //we received a player change/quit during waiting in get_user_choice/synced_context::pull_remote_user_input return boost::none; } if (result == turn_info::PROCESS_RESTART_TURN || result == turn_info::PROCESS_RESTART_TURN_TEMPORARY_LOCAL) { player_type_changed_ = true; return boost::none; } else if (result == turn_info::PROCESS_END_TURN) { break; } } /* we might have data left in replay that we recieved during prestart events. (or maybe other events.) */ else if(!recorder.at_end()) { bool was_skipping = recorder.is_skipping(); recorder.set_skip(skip_replay_); if(do_replay() == REPLAY_FOUND_END_TURN) { break; } recorder.set_skip(was_skipping); } } HANDLE_END_PLAY_SIGNAL( play_slice() ); HANDLE_END_PLAY_SIGNAL( check_end_level() ); if (!network_processing_stopped_){ turn_data_.send_data(); } gui_->draw(); } LOG_NG << "finished networked...\n"; return boost::none; }
turn_info::PROCESS_DATA_RESULT turn_info::handle_turn(const config& t) { //t can contain a [command] or a [upload_log] assert(t.all_children_count() == 1); /** @todo FIXME: Check what commands we execute when it's our turn! */ //note, that this function might call itself recursively: do_replay -> ... -> get_user_choice -> ... -> playmp_controller::pull_remote_choice -> sync_network -> handle_turn resources::recorder->add_config(t, replay::MARK_AS_SENT); PROCESS_DATA_RESULT retv = replay_to_process_data_result(do_replay()); return retv; }
//make only one side move void replay_controller::play_side(const unsigned int /*team_index*/, bool){ DBG_REPLAY << "Status turn number: " << turn() << "\n"; DBG_REPLAY << "Replay_Controller turn number: " << current_turn_ << "\n"; DBG_REPLAY << "Player number: " << player_number_ << "\n"; try{ // If a side is empty skip over it. bool has_end_turn = true; if (!current_team().is_empty()) { statistics::reset_turn_stats(current_team().save_id()); play_controller::init_side(player_number_ - 1, true); DBG_REPLAY << "doing replay " << player_number_ << "\n"; // if have reached the end we don't want to execute finish_side_turn and finish_turn // becasue we might not have enough data to execute them (like advancements during turn_end for example) // !has_end_turn == we reached the end of teh replay without finding and end turn tag. has_end_turn = do_replay(player_number_); if(!has_end_turn) { return; } finish_side_turn(); } player_number_++; if (static_cast<size_t>(player_number_) > teams_.size()) { //during the orginal game player_number_ would also be teams_.size(), player_number_ = teams_.size(); finish_turn(); tod_manager_.next_turn(); it_is_a_new_turn_ = true; player_number_ = 1; current_turn_++; gui_->new_turn(); } // This is necessary for replays in order to show possible movements. BOOST_FOREACH(unit &u, units_) { if (u.side() == player_number_) { u.new_turn(); } } update_teams(); update_gui(); } catch(end_level_exception& e){ //VICTORY/DEFEAT end_level_exception shall not return to title screen if (e.result != VICTORY && e.result != DEFEAT) throw; } }
static void replay_speed(int x) { if (play_state==-1) { speed=x; return; } replay_pause(); speed=x; replay_resume(); do_replay(); }
void replay_controller::play_side(const unsigned int /*team_index*/, bool){ if (recorder.at_end()){ return; } DBG_REPLAY << "Status turn number: " << turn() << "\n"; DBG_REPLAY << "Replay_Controller turn number: " << current_turn_ << "\n"; DBG_REPLAY << "Player number: " << player_number_ << "\n"; try{ // If a side is empty skip over it. if (!current_team().is_empty()) { statistics::reset_turn_stats(current_team().save_id()); play_controller::init_side(player_number_ - 1, true); DBG_REPLAY << "doing replay " << player_number_ << "\n"; do_replay(player_number_); finish_side_turn(); // This is necessary for replays in order to show possible movements. for (unit_map::iterator uit = units_.begin(); uit != units_.end(); ++uit) { if (uit->second.side() != player_number_) { uit->second.new_turn(); } } } player_number_++; if (static_cast<size_t>(player_number_) > teams_.size()) { next_turn(); finish_turn(); player_number_ = 1; current_turn_++; } update_teams(); update_gui(); } catch(end_level_exception& e){ //VICTORY/DEFEAT end_level_exception shall not return to title screen if ((e.result != VICTORY) && (e.result != DEFEAT)) { throw e; } } }
static void gui_drawingarea_cb_key (I, GuiDrawingAreaKeyEvent event) { iam (RunnerMFC); if (my graphics == NULL) return; // Could be the case in the very beginning. ExperimentMFC experiment = (ExperimentMFC) my data; if (my data == NULL) return; double reactionTime = Melder_clock () - experiment -> startingTime; if (! experiment -> blankWhilePlaying) reactionTime -= experiment -> stimulusInitialSilenceDuration; if (experiment -> trial == 0) { } else if (experiment -> pausing) { } else if (experiment -> trial <= experiment -> numberOfTrials) { long iresponse; if (experiment -> ok_key != NULL && experiment -> ok_key [0] == event -> key && experiment -> responses [experiment -> trial] != 0 && (experiment -> numberOfGoodnessCategories == 0 || experiment -> goodnesses [experiment -> trial] != 0)) { do_ok (me); } else if (experiment -> replay_key != NULL && experiment -> replay_key [0] == event -> key && my numberOfReplays < experiment -> maximumNumberOfReplays) { do_replay (me); } else if (experiment -> oops_key != NULL && experiment -> oops_key [0] == event -> key) { if (experiment -> trial > 1) { do_oops (me); } } else if (experiment -> responses [experiment -> trial] == 0) { for (iresponse = 1; iresponse <= experiment -> numberOfDifferentResponses; iresponse ++) { ResponseMFC response = & experiment -> response [iresponse]; if (response -> key != NULL && response -> key [0] == event -> key) { experiment -> responses [experiment -> trial] = iresponse; experiment -> reactionTimes [experiment -> trial] = reactionTime; if (experiment -> responsesAreSounds) { ExperimentMFC_playResponse (experiment, iresponse); } if (experiment -> ok_right <= experiment -> ok_left && experiment -> numberOfGoodnessCategories == 0) { do_ok (me); } else { my broadcastDataChanged (); Graphics_updateWs (my graphics); } } } } } }
turn_info::PROCESS_DATA_RESULT turn_info::sync_network() { //there should be nothing left on the replay and we should get turn_info::PROCESS_CONTINUE back. turn_info::PROCESS_DATA_RESULT retv = replay_to_process_data_result(do_replay()); if(resources::controller->is_networked_mp()) { //receive data first, and then send data. When we sent the end of //the AI's turn, we don't want there to be any chance where we //could get data back pertaining to the next turn. config cfg; while( (retv == turn_info::PROCESS_CONTINUE) && network_reader_.read(cfg)) { retv = process_network_data(cfg); cfg.clear(); } send_data(); } return retv; }
static void adjust_pos(int d) { int oldstate=play_state; if (play_state==-1) return; replay_pause(); tr.tv_sec+=d; if (tr.tv_sec<0) tr.tv_sec=tr.tv_usec=0; if (tcmp(tr, tmax)==1) tr=tmax; replay_seek(); play_state=oldstate; redraw_term(); set_prog(); do_replay(); }
static void prog_scrolled(void) { uint64_t v; int oldstate=play_state; int pos=SendMessage(wndProg, TBM_GETPOS, 0, 0); if (pos<0) pos=0; replay_pause(); v=pos; v*=progdiv; tr.tv_sec=v/1000000; tr.tv_usec=v%1000000; replay_seek(); play_state=oldstate; redraw_term(); do_replay(); }
void turn_info::handle_turn( bool& turn_end, const config& t, const bool skip_replay, std::deque<config>& backlog) { if(turn_end == false) { /** @todo FIXME: Check what commands we execute when it's our turn! */ replay_.append(t); replay_.set_skip(skip_replay); turn_end = do_replay(team_num_, &replay_); recorder.add_config(t, replay::MARK_AS_SENT); } else { //this turn has finished, so push the remaining moves //into the backlog backlog.push_back(config()); backlog.back().add_child("turn", t); } }
//make only one side move void replay_controller::play_side(const unsigned int /*team_index*/, bool){ DBG_REPLAY << "Status turn number: " << turn() << "\n"; DBG_REPLAY << "Replay_Controller turn number: " << current_turn_ << "\n"; DBG_REPLAY << "Player number: " << player_number_ << "\n"; try{ // If a side is empty skip over it. if (!current_team().is_empty()) { statistics::reset_turn_stats(current_team().save_id()); play_controller::init_side(player_number_ - 1, true); DBG_REPLAY << "doing replay " << player_number_ << "\n"; do_replay(player_number_); finish_side_turn(); // This is necessary for replays in order to show possible movements. foreach (unit &u, units_) { if (u.side() != player_number_) { u.new_turn(); } } } player_number_++; if (static_cast<size_t>(player_number_) > teams_.size()) { finish_turn(); tod_manager_.next_turn(); it_is_a_new_turn_ = true; player_number_ = 1; current_turn_++; gui_->new_turn(); } update_teams(); update_gui(); }
static void gui_drawingarea_cb_click (I, GuiDrawingAreaClickEvent event) { iam (RunnerMFC); if (my graphics == NULL) return; // Could be the case in the very beginning. ExperimentMFC experiment = (ExperimentMFC) my data; if (my data == NULL) return; double reactionTime = Melder_clock () - experiment -> startingTime; if (! experiment -> blankWhilePlaying) reactionTime -= experiment -> stimulusInitialSilenceDuration; double x, y; Graphics_DCtoWC (my graphics, event -> x, event -> y, & x, & y); if (experiment -> trial == 0) { // the first click of the experiment experiment -> trial ++; my broadcastDataChanged (); if (experiment -> blankWhilePlaying) { Graphics_setGrey (my graphics, 0.8); Graphics_fillRectangle (my graphics, 0, 1, 0, 1); Graphics_setGrey (my graphics, 0.0); Graphics_flushWs (my graphics); } Graphics_updateWs (my graphics); if (experiment -> stimuliAreSounds) { if (experiment -> numberOfTrials < 1) { Melder_flushError ("There are zero trials in this experiment."); forget (me); return; } autoMelderAudioSaveMaximumAsynchronicity saveMaximumAsynchronicity; if (experiment -> blankWhilePlaying) MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_SYNCHRONOUS); ExperimentMFC_playStimulus (experiment, experiment -> stimuli [1]); // works only if there is at least one trial } } else if (experiment -> pausing) { // a click to leave the break if (x > experiment -> oops_left && x < experiment -> oops_right && y > experiment -> oops_bottom && y < experiment -> oops_top && experiment -> trial > 1) { do_oops (me); } else { experiment -> pausing = FALSE; experiment -> trial ++; my broadcastDataChanged (); if (experiment -> blankWhilePlaying) { Graphics_setGrey (my graphics, 0.8); Graphics_fillRectangle (my graphics, 0, 1, 0, 1); Graphics_setGrey (my graphics, 0.0); Graphics_flushWs (my graphics); } Graphics_updateWs (my graphics); if (experiment -> stimuliAreSounds) { autoMelderAudioSaveMaximumAsynchronicity saveMaximumAsynchronicity; if (experiment -> blankWhilePlaying) MelderAudio_setOutputMaximumAsynchronicity (kMelder_asynchronicityLevel_SYNCHRONOUS); ExperimentMFC_playStimulus (experiment, experiment -> stimuli [experiment -> trial]); } } } else if (experiment -> trial <= experiment -> numberOfTrials) { long iresponse; if (x > experiment -> ok_left && x < experiment -> ok_right && y > experiment -> ok_bottom && y < experiment -> ok_top && experiment -> responses [experiment -> trial] != 0 && (experiment -> numberOfGoodnessCategories == 0 || experiment -> goodnesses [experiment -> trial] != 0)) { do_ok (me); } else if (x > experiment -> replay_left && x < experiment -> replay_right && y > experiment -> replay_bottom && y < experiment -> replay_top && my numberOfReplays < experiment -> maximumNumberOfReplays) { do_replay (me); } else if (x > experiment -> oops_left && x < experiment -> oops_right && y > experiment -> oops_bottom && y < experiment -> oops_top && experiment -> trial > 1) { do_oops (me); } else if (experiment -> responses [experiment -> trial] == 0 || experiment -> ok_right > experiment -> ok_left) { for (iresponse = 1; iresponse <= experiment -> numberOfDifferentResponses; iresponse ++) { ResponseMFC response = & experiment -> response [iresponse]; if (x > response -> left && x < response -> right && y > response -> bottom && y < response -> top && response -> name [0] != '\0') { experiment -> responses [experiment -> trial] = iresponse; experiment -> reactionTimes [experiment -> trial] = reactionTime; if (experiment -> responsesAreSounds) { ExperimentMFC_playResponse (experiment, iresponse); } if (experiment -> ok_right <= experiment -> ok_left && experiment -> numberOfGoodnessCategories == 0) { do_ok (me); } else { my broadcastDataChanged (); Graphics_updateWs (my graphics); } } } if (experiment -> responses [experiment -> trial] != 0 && experiment -> ok_right > experiment -> ok_left) { for (iresponse = 1; iresponse <= experiment -> numberOfGoodnessCategories; iresponse ++) { GoodnessMFC cat = & experiment -> goodness [iresponse]; if (x > cat -> left && x < cat -> right && y > cat -> bottom && y < cat -> top) { experiment -> goodnesses [experiment -> trial] = iresponse; my broadcastDataChanged (); Graphics_updateWs (my graphics); } } } } else if (experiment -> responses [experiment -> trial] != 0) { Melder_assert (experiment -> ok_right <= experiment -> ok_left); for (iresponse = 1; iresponse <= experiment -> numberOfGoodnessCategories; iresponse ++) { GoodnessMFC cat = & experiment -> goodness [iresponse]; if (x > cat -> left && x < cat -> right && y > cat -> bottom && y < cat -> top) { experiment -> goodnesses [experiment -> trial] = iresponse; do_ok (me); } } } } else { if (x > experiment -> oops_left && x < experiment -> oops_right && y > experiment -> oops_bottom && y < experiment -> oops_top) { do_oops (me); return; } if (my iexperiment < my experiments -> size) { my iexperiment ++; if (! RunnerMFC_startExperiment (me)) { Melder_flushError (NULL); forget (me); return; } } } }
//make only one side move possible_end_play_signal replay_controller::play_side() { DBG_REPLAY << "Status turn number: " << turn() << "\n"; DBG_REPLAY << "Replay_Controller turn number: " << current_turn_ << "\n"; DBG_REPLAY << "Player number: " << player_number_ << "\n"; // If a side is empty skip over it. if (!current_team().is_empty()) { statistics::reset_turn_stats(current_team().save_id()); possible_end_play_signal signal = play_controller::init_side(true); if (signal) { switch (boost::apply_visitor(get_signal_type(), *signal) ) { case END_TURN: return signal; case END_LEVEL: //VICTORY/DEFEAT end_level_exception shall not return to title screen LEVEL_RESULT res = boost::apply_visitor(get_result(), *signal); if ( res != VICTORY && res != DEFEAT ) return signal; } } DBG_REPLAY << "doing replay " << player_number_ << "\n"; // if have reached the end we don't want to execute finish_side_turn and finish_turn // becasue we might not have enough data to execute them (like advancements during turn_end for example) try { if(do_replay() != REPLAY_FOUND_END_TURN) { // We reached the end of teh replay without finding and end turn tag. return boost::none; } } catch(end_level_exception& e){ //VICTORY/DEFEAT end_level_exception shall not return to title screen if (e.result != VICTORY && e.result != DEFEAT) { return possible_end_play_signal(e.to_struct()); } } catch (end_turn_exception & e) { return possible_end_play_signal(e.to_struct()); } finish_side_turn(); } player_number_++; if (static_cast<size_t>(player_number_) > gamestate_.board_.teams().size()) { //during the orginal game player_number_ would also be gamestate_.board_.teams().size(), player_number_ = gamestate_.board_.teams().size(); finish_turn(); gamestate_.tod_manager_.next_turn(*resources::gamedata); it_is_a_new_turn_ = true; player_number_ = 1; current_turn_++; gui_->new_turn(); } // This is necessary for replays in order to show possible movements. gamestate_.board_.new_turn(player_number_); update_teams(); update_gui(); return boost::none; }
LRESULT APIENTRY MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: create_toolbar(hwnd); create_term(hwnd); create_sysmenu(hwnd); return 0; case WM_SIZE: SendMessage(wndTB, TB_AUTOSIZE, 0, 0); get_def_size(LOWORD(lParam), HIWORD(lParam)); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case BUT_OPEN: open_file(); break; case BUT_REWIND: but_rewind: if (play_state==-1) break; EnterCriticalSection(&vt_mutex); replay_pause(); tr.tv_sec=0; tr.tv_usec=0; set_prog(); replay_seek(); LeaveCriticalSection(&vt_mutex); play_state=1; replay_resume(); do_replay(); break; case BUT_PAUSE: if (play_state==1) goto but_unpause; but_pause: CancelWaitableTimer(timer); replay_pause(); set_buttons(1); break; case BUT_PLAY: if (play_state>1) goto but_pause; but_unpause: replay_resume(); do_replay(); set_buttons(1); break; case BUT_SELSTART: if (play_state==-1) break; get_pos(); selstart=tr; set_prog_sel(); break; case BUT_SELEND: if (play_state==-1) break; selend=tr; set_prog_sel(); break; case BUT_EXPORT: if (play_state==-1) break; if (tcmp(selstart, selend)>=0) break; export_file(); break; } return 0; case WM_SYSCOMMAND: switch (LOWORD(wParam)) { default: return DefWindowProc(hwnd, uMsg, wParam, lParam); case BUT_FONT: choose_font(); } return 0; case WM_HSCROLL: if ((HANDLE)lParam==wndSpeed) speed_scrolled(); else if ((HANDLE)lParam==wndProg) prog_scrolled(); return 0; case WM_KEYDOWN: switch (wParam) { case VK_ADD: case 'F': adjust_speed(+1); break; case VK_SUBTRACT: case 'S': adjust_speed(-1); break; case '1': SendMessage(wndSpeed, TBM_SETPOS, 1, 2); speed_scrolled(); break; case 'Q': DestroyWindow(wndMain); break; case 'O': open_file(); break; case VK_SPACE: switch (play_state) { case -1: open_file(); break; case 0: play_state=2; goto but_rewind; case 1: goto but_unpause; case 2: case 3: goto but_pause; } break; case 'R': goto but_rewind; break; case VK_RIGHT: adjust_pos(+10); break; case VK_LEFT: adjust_pos(-10); break; case VK_UP: adjust_pos(+60); break; case VK_DOWN: adjust_pos(-60); break; case VK_PRIOR: adjust_pos(+600); break; case VK_NEXT: adjust_pos(-600); break; } return 0; case WM_SIZING: constrain_size((LPRECT)lParam); return 1; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; }