00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "side_actions.hpp"
00021
00022 #include "action.hpp"
00023 #include "attack.hpp"
00024 #include "manager.hpp"
00025 #include "move.hpp"
00026 #include "recall.hpp"
00027 #include "recruit.hpp"
00028 #include "suppose_dead.hpp"
00029 #include "highlight_visitor.hpp"
00030 #include "utility.hpp"
00031 #include "validate_visitor.hpp"
00032
00033 #include "actions.hpp"
00034 #include "foreach.hpp"
00035 #include "game_display.hpp"
00036 #include "game_end_exceptions.hpp"
00037 #include "map.hpp"
00038 #include "resources.hpp"
00039
00040 #include <set>
00041 #include <sstream>
00042
00043 namespace wb
00044 {
00045
00046
00047 std::ostream &operator<<(std::ostream &s, wb::side_actions const& side_actions)
00048 {
00049 s << "Content of side_actions:";
00050 int turn = 1;
00051 foreach(action_queue const& turn_queue, side_actions.actions())
00052 {
00053 s << "\n Turn " << turn;
00054 ++turn;
00055
00056 int count = 1;
00057 foreach(action_ptr const& action, turn_queue)
00058 {
00059 s << "\n (" << count << ") " << action;
00060 ++count;
00061 }
00062 }
00063 if (turn == 1) s << " (empty)";
00064 return s;
00065 }
00066
00067 side_actions::side_actions()
00068 : actions_()
00069 , team_index_(0)
00070 , team_index_defined_(false)
00071 , gold_spent_(0)
00072 , hidden_(false)
00073 {
00074 }
00075
00076 side_actions::~side_actions()
00077 {
00078 }
00079
00080 void side_actions::set_team_index(size_t team_index)
00081 {
00082 assert(!team_index_defined_);
00083 team_index_ = team_index;
00084 team_index_defined_ = true;
00085 }
00086
00087 void side_actions::get_numbers(const map_location& hex, numbers_t& result)
00088 {
00089 if(empty()) {
00090 return;
00091 }
00092
00093 std::vector<int>& numbers_to_draw = result.numbers_to_draw;
00094 std::vector<size_t>& team_numbers = result.team_numbers;
00095 int& main_number = result.main_number;
00096 std::set<size_t>& secondary_numbers = result.secondary_numbers;
00097 boost::shared_ptr<highlight_visitor> highlighter =
00098 resources::whiteboard->get_highlighter().lock();
00099
00100 const_iterator it;
00101 for(it = begin(); it != end(); ++it)
00102 {
00103 if((*it)->is_numbering_hex(hex))
00104 {
00105
00106 size_t number = (it - begin()) + 1;
00107 size_t index = numbers_to_draw.size();
00108 numbers_to_draw.push_back(number);
00109 team_numbers.push_back(team_index());
00110
00111 if (highlighter)
00112 {
00113 if (highlighter->get_main_highlight().lock() == *it) {
00114 main_number = index;
00115 }
00116
00117 foreach(weak_action_ptr action, highlighter->get_secondary_highlights())
00118 {
00119 if (action.lock() == *it)
00120 {
00121 secondary_numbers.insert(index);
00122 }
00123 }
00124 }
00125 }
00126 }
00127 }
00128
00129 bool side_actions::execute_next()
00130 {
00131 if(!empty() && !actions_.front().empty())
00132 return execute(begin());
00133 else
00134 return false;
00135 }
00136
00137 bool side_actions::execute(side_actions::iterator position)
00138 {
00139 if (resources::whiteboard->has_planned_unit_map())
00140 {
00141 ERR_WB << "Modifying action queue while temp modifiers are applied!!!\n";
00142 }
00143
00144 assert(position.turn_num_ == 0);
00145
00146 if(actions_.empty() || !validate_iterator(position))
00147 return false;
00148
00149 LOG_WB << "Before execution, " << *this << "\n";
00150
00151 action_ptr action = *position;
00152
00153 if (!action->is_valid())
00154 {
00155 LOG_WB << "Invalid action sent to execution, deleting.\n";
00156 synced_erase(position);
00157 return true;
00158 }
00159
00160 bool action_successful;
00161
00162 bool action_complete;
00163 try {
00164 action->execute(action_successful,action_complete);
00165 } catch (end_turn_exception&) {
00166 synced_erase(position);
00167 LOG_WB << "End turn exception caught during execution, deleting action. " << *this << "\n";
00168
00169 resources::whiteboard->on_gamestate_change();
00170 throw;
00171 }
00172
00173 if(resources::whiteboard->should_clear_undo())
00174 resources::whiteboard->clear_undo();
00175
00176 std::stringstream ss;
00177 ss << "After " << (action_successful? "successful": "failed") << " execution ";
00178 if(action_complete)
00179 {
00180 ss << "with deletion, ";
00181 synced_erase(position);
00182 }
00183 else
00184 {
00185 ss << "without deletion, ";
00186 resources::whiteboard->queue_net_cmd(team_index_,make_net_cmd_replace(position,*position));
00187
00188
00189
00190
00191 }
00192 ss << *this << "\n";
00193 LOG_WB << ss.str();
00194
00195 validate_actions();
00196 return action_successful;
00197 }
00198
00199 size_t side_actions::size() const
00200 {
00201 size_t result = 0;
00202 foreach(action_queue const& queue, actions_)
00203 result += queue.size();
00204 return result;
00205 }
00206
00207 side_actions::iterator side_actions::turn_begin(size_t turn_num)
00208 {
00209 if(turn_num < num_turns())
00210 return iterator(actions_[turn_num].begin(),turn_num,*this);
00211 else
00212 return end();
00213 }
00214 side_actions::iterator side_actions::turn_end(size_t turn_num)
00215 {return turn_begin(turn_num+1);}
00216 side_actions::reverse_iterator side_actions::turn_rbegin(size_t turn_num)
00217 {return reverse_iterator(turn_end(turn_num));}
00218 side_actions::reverse_iterator side_actions::turn_rend(size_t turn_num)
00219 {return reverse_iterator(turn_begin(turn_num));}
00220
00221 side_actions::range_t side_actions::iter_turn(size_t turn_num)
00222 {return range_t(turn_begin(turn_num),turn_end(turn_num));}
00223 side_actions::rrange_t side_actions::riter_turn(size_t turn_num)
00224 {return rrange_t(turn_rbegin(turn_num),turn_rend(turn_num));}
00225
00226 void side_actions::hide()
00227 {
00228 if(hidden_)
00229 return;
00230
00231 hidden_ = true;
00232
00233 if(empty()) {
00234 return;
00235 }
00236
00237 foreach(action_ptr act, *this)
00238 act->hide();
00239 }
00240 void side_actions::show()
00241 {
00242 if(!hidden_)
00243 return;
00244
00245 hidden_ = false;
00246
00247 foreach(action_ptr act, *this)
00248 act->show();
00249 }
00250
00251 side_actions::iterator side_actions::queue_move(size_t turn, unit& mover, const pathfind::marked_route& route, arrow_ptr arrow, fake_unit_ptr fake_unit)
00252 {
00253 move_ptr new_move(new move(team_index(), hidden_, mover, route, arrow, fake_unit));
00254 return queue_action(turn,new_move);
00255 }
00256
00257 side_actions::iterator side_actions::queue_attack(size_t turn, unit& mover, const map_location& target_hex, int weapon_choice,
00258 const pathfind::marked_route& route,
00259 arrow_ptr arrow, fake_unit_ptr fake_unit)
00260 {
00261 attack_ptr new_attack(new attack(team_index(), hidden_, mover, target_hex, weapon_choice, route, arrow, fake_unit));
00262 return queue_action(turn,new_attack);
00263 }
00264
00265 side_actions::iterator side_actions::queue_recruit(size_t turn, const std::string& unit_name, const map_location& recruit_hex)
00266 {
00267 recruit_ptr new_recruit(new recruit(team_index(), hidden_, unit_name, recruit_hex));
00268 return queue_action(turn,new_recruit);
00269 }
00270
00271 side_actions::iterator side_actions::queue_recall(size_t turn, const unit& unit, const map_location& recall_hex)
00272 {
00273 recall_ptr new_recall(new recall(team_index(), hidden_, unit, recall_hex));
00274 return queue_action(turn,new_recall);
00275 }
00276
00277 side_actions::iterator side_actions::queue_suppose_dead(size_t turn, unit& curr_unit, map_location const& loc)
00278 {
00279 suppose_dead_ptr new_suppose_dead(new suppose_dead(team_index(),hidden_,curr_unit,loc));
00280 return queue_action(turn,new_suppose_dead);
00281 }
00282
00283 side_actions::iterator side_actions::insert_action(iterator position, action_ptr action)
00284 {
00285 if (resources::whiteboard->has_planned_unit_map())
00286 {
00287 ERR_WB << "Modifying action queue while temp modifiers are applied!!!\n";
00288 }
00289 iterator valid_position = synced_insert(position, action);
00290 LOG_WB << "Inserted into turn #" << (valid_position.turn_num_+1) << " at position #"
00291 << (valid_position.base_-actions_[valid_position.turn_num_].begin()+1) << " : " << action <<"\n";
00292 validate_actions();
00293 return valid_position;
00294 }
00295
00296 side_actions::iterator side_actions::queue_action(size_t turn_num, action_ptr action)
00297 {
00298 if(resources::whiteboard->has_planned_unit_map())
00299 {
00300 ERR_WB << "Modifying action queue while temp modifiers are applied!!!\n";
00301 }
00302 iterator result = synced_enqueue(turn_num, action);
00303 LOG_WB << "Inserted into turn #" << (turn_num+1) << " at position #" << actions_[turn_num].size()
00304 << " : " << action <<"\n";
00305 validate_actions();
00306 return result;
00307 }
00308
00309
00310 side_actions::iterator side_actions::bump_earlier(side_actions::iterator position)
00311 {
00312 if (resources::whiteboard->has_planned_unit_map())
00313 {
00314 ERR_WB << "Modifying action queue while temp modifiers are applied!!!\n";
00315 }
00316
00317 assert(validate_iterator(position));
00318
00319
00320
00321 if(position.base_ == actions_[position.turn_num_].begin())
00322 return end();
00323
00324 side_actions::iterator previous = position - 1;
00325
00326 {
00327 unit const* previous_ptr = (*previous)->get_unit();
00328 unit const* current_ptr = (*position)->get_unit();
00329 if (previous_ptr && current_ptr && previous_ptr == current_ptr)
00330 return end();
00331 }
00332
00333 {
00334 using boost::dynamic_pointer_cast;
00335
00336 if (move_ptr bump_earlier = dynamic_pointer_cast<move>(*position))
00337 {
00338 if (move_ptr previous_move = dynamic_pointer_cast<move>(*previous))
00339 {
00340 if (bump_earlier->get_dest_hex() == previous_move->get_source_hex())
00341 {
00342 return end();
00343 }
00344 }
00345
00346 map_location recruit_recall_loc;
00347 if (recruit_ptr previous_recruit = dynamic_pointer_cast<recruit>(*previous))
00348 {
00349 recruit_recall_loc = previous_recruit->get_recruit_hex();
00350 } else if (recall_ptr previous_recall = dynamic_pointer_cast<recall>(*previous))
00351 {
00352 recruit_recall_loc = previous_recall->get_recall_hex();
00353 }
00354 if (recruit_recall_loc.valid())
00355 {
00356 unit const* leader = bump_earlier->get_unit();
00357 if(leader->can_recruit() &&
00358 resources::game_map->is_keep(leader->get_location()) &&
00359 can_recruit_on(*resources::game_map, leader->get_location(), recruit_recall_loc))
00360 {
00361 if(unit const* backup_leader = find_backup_leader(*leader))
00362 {
00363 side_actions::iterator it = find_first_action_of(backup_leader);
00364 if (!(it == end() || position < it))
00365 return end();
00366 }
00367 else
00368 {
00369 return end();
00370 }
00371 }
00372 }
00373 }
00374 }
00375
00376 LOG_WB << "Before bumping earlier, " << *this << "\n";
00377
00378 int action_number = std::distance(actions_[position.turn_num_].begin(), position.base_) + 1;
00379 int last_position = actions_[position.turn_num_].size();
00380 LOG_WB << "In turn-queue #" << (position.turn_num_+1)
00381 << ", bumping action #" << action_number << "/" << last_position
00382 << " to position #" << action_number - 1 << "/" << last_position << ".\n";
00383
00384 action_ptr action = *position;
00385 resources::whiteboard->queue_net_cmd(team_index_,make_net_cmd_bump_later(position-1));
00386 iterator after = raw_erase(position);
00387
00388 iterator destination = after - 1;
00389 iterator valid_position = raw_insert(destination, action);
00390 assert(validate_iterator(valid_position));
00391 validate_actions();
00392 LOG_WB << "After bumping earlier, " << *this << "\n";
00393 return valid_position;
00394 }
00395
00396
00397 side_actions::iterator side_actions::bump_later(side_actions::iterator position)
00398 {
00399 iterator end_itor = end();
00400 assert(position != end_itor);
00401
00402 ++position;
00403 if(position == end_itor)
00404 return end_itor;
00405 position = bump_earlier(position);
00406 if(position == end())
00407 return end_itor;
00408 return position+1;
00409 }
00410
00411 side_actions::iterator side_actions::remove_action(side_actions::iterator position, bool validate_after_delete)
00412 {
00413 if (resources::whiteboard->has_planned_unit_map())
00414 {
00415 ERR_WB << "Modifying action queue while temp modifiers are applied!!!\n";
00416 }
00417
00418 assert(!actions_.empty());
00419 assert(validate_iterator(position));
00420 size_t distance = std::distance(begin(), position);
00421 if (!actions_.empty() && validate_iterator(position))
00422 {
00423 LOG_WB << "Erasing action at position #" << distance + 1 << "\n";
00424
00425 synced_erase(position);
00426
00427 if (validate_after_delete)
00428 {
00429 validate_actions();
00430 }
00431 }
00432 return begin() + distance;
00433 }
00434
00435 side_actions::iterator side_actions::get_position_of(action_ptr action)
00436 {
00437 if (!actions_.empty())
00438 {
00439 iterator position = begin();
00440 iterator end_itor = end();
00441 for(; position != end_itor; ++position)
00442 if (*position == action)
00443 return position;
00444 }
00445 return end();
00446 }
00447
00448 side_actions::iterator side_actions::find_first_action_of(unit const* unit, side_actions::iterator start_position)
00449 {
00450 if (!empty() && validate_iterator(start_position))
00451 {
00452 side_actions::iterator position;
00453 for (position = start_position; position != end(); ++position)
00454 {
00455 action_ptr action = *position;
00456 if (action->get_unit() == unit)
00457 {
00458 return position;
00459 }
00460 }
00461 }
00462 return end();
00463 }
00464
00465 side_actions::iterator side_actions::find_first_action_of(unit const* unit)
00466 {
00467 if (empty())
00468 return end();
00469 else
00470 return find_first_action_of(unit, begin());
00471 }
00472
00473 side_actions::iterator side_actions::find_last_action_of(unit const* unit, side_actions::iterator start_position)
00474 {
00475 if (!empty() && validate_iterator(start_position))
00476 {
00477 reverse_iterator position(start_position);
00478 for (--position ; position != rend(); ++position)
00479 {
00480 if ((*position)->get_unit() == unit)
00481 {
00482 iterator found_position(position);
00483
00484 return --found_position;
00485 }
00486 }
00487 }
00488 return end();
00489 }
00490
00491 side_actions::iterator side_actions::find_last_action_of(unit const* unit)
00492 {
00493 if (empty())
00494 return end();
00495 else
00496 return find_last_action_of(unit, end() - 1);
00497 }
00498
00499 bool side_actions::unit_has_actions(unit const* unit)
00500 {
00501 if (empty())
00502 return false;
00503 else
00504 return find_first_action_of(unit) != end();
00505 }
00506
00507 size_t side_actions::count_actions_of(unit const* unit)
00508 {
00509 size_t count = 0;
00510 foreach(action_ptr action, *this)
00511 {
00512 if (action->get_unit() == unit)
00513 {
00514 ++count;
00515 }
00516 }
00517 return count;
00518 }
00519
00520 void side_actions::remove_invalid_of(unit const* u)
00521 {
00522 iterator i = begin();
00523 while(i != end())
00524 {
00525 action& act = **i;
00526 if(!act.is_valid() && u == act.get_unit())
00527 i = remove_action(i,false);
00528 else ++i;
00529 }
00530 }
00531
00532 static side_actions::const_iterator find_last_valid_of(unit const& u, side_actions const& sa_const)
00533 {
00534 side_actions& sa = const_cast<side_actions&>(sa_const);
00535 side_actions::iterator end = sa.end();
00536
00537 if(sa.empty())
00538 return sa.end();
00539
00540 side_actions::iterator begin = sa.begin();
00541 side_actions::iterator itor = end;
00542 do {
00543 if(itor==begin && !(*itor)->is_valid())
00544 return end;
00545 itor = sa.find_last_action_of(&u,itor - 1);
00546 } while(itor!=end && !(*itor)->is_valid());
00547
00548 return itor;
00549 }
00550 size_t side_actions::get_turn_num_of(unit const& u) const
00551 {
00552 const_iterator itor = find_last_valid_of(u,*this);
00553 if(itor == end())
00554 return 0;
00555 return itor.base_.turn_num_;
00556 }
00557
00558 void side_actions::validate_actions()
00559 {
00560 assert(!resources::whiteboard->has_planned_unit_map());
00561
00562 bool validation_finished = false;
00563 int passes = 1;
00564 while(!validation_finished){
00565 log_scope2("whiteboard", "Validating actions for side "
00566 + lexical_cast<std::string>(team_index() + 1) + ", pass "
00567 + lexical_cast<std::string>(passes));
00568 validate_visitor validator(*resources::units);
00569 validation_finished = validator.validate_actions();
00570 ++passes;
00571 }
00572 }
00573
00574 void side_actions::change_gold_spent_by(int difference)
00575 {
00576 DBG_WB << "Changing gold spent for side " << (team_index() + 1) << "; old value: "
00577 << gold_spent_ << "; new value: " << (gold_spent_ + difference) << "\n";
00578 gold_spent_ += difference; assert(gold_spent_ >= 0);
00579 }
00580
00581 void side_actions::reset_gold_spent()
00582 {
00583 DBG_WB << "Resetting gold spent for side " << (team_index() + 1) << " to 0.\n";
00584 gold_spent_ = 0;
00585 }
00586
00587
00588 void side_actions::update_size()
00589 {
00590 while(!actions_.empty() && actions_.back().empty())
00591 actions_.pop_back();
00592 }
00593
00594 side_actions::iterator side_actions::raw_erase(iterator itor)
00595 {
00596
00597 assert(itor!=end());
00598
00599
00600 iterator next = itor+1;
00601 bool deleting_last_element = (next == end());
00602 size_t turn_num = itor.turn_num_;
00603 bool next_is_still_valid = (turn_num != next.turn_num_);
00604
00605
00606 action_queue::iterator after_erase = actions_[turn_num].erase(itor.base_);
00607
00608
00609 if(deleting_last_element)
00610 {
00611 update_size();
00612 return end();
00613 }
00614 else if(next_is_still_valid)
00615 return next;
00616 else
00617 return iterator(after_erase, turn_num, *this);
00618 }
00619
00620 side_actions::iterator side_actions::raw_insert(iterator itor, action_ptr act)
00621 {
00622 size_t turn_num = itor.turn_num_;
00623 action_queue::iterator new_itor = actions_[itor.turn_num_].insert(itor.base_,act);
00624 return iterator(new_itor,turn_num,*this);
00625 }
00626
00627 side_actions::iterator side_actions::raw_enqueue(size_t turn_num, action_ptr act)
00628 {
00629
00630 assert(turn_num <= actions_.size() || turn_num <= 2);
00631
00632 if(turn_num >= actions_.size())
00633 actions_.resize(turn_num+1);
00634 actions_[turn_num].push_back(act);
00635 return iterator(actions_[turn_num].end()-1,turn_num,*this);
00636 }
00637
00638 side_actions::iterator side_actions::safe_insert(size_t turn, size_t pos, action_ptr act)
00639 {
00640 assert(act);
00641
00642 iterator result;
00643
00644 size_t queue_count = actions_.size();
00645 if((turn == queue_count && pos == 0)
00646 || (turn < queue_count && pos == actions_[turn].size()))
00647 result = raw_enqueue(turn,act);
00648 else if(turn < queue_count && pos < actions_[turn].size())
00649 {
00650 result = iterator(actions_[turn].begin()+pos,turn,*this);
00651 result = raw_insert(result,act);
00652 }
00653 else
00654 result = end();
00655
00656 return result;
00657 }
00658
00659 side_actions::iterator side_actions::synced_erase(iterator itor)
00660 {
00661 resources::whiteboard->queue_net_cmd(team_index_,make_net_cmd_remove(itor));
00662 return safe_erase(itor);
00663 }
00664
00665 side_actions::iterator side_actions::synced_insert(iterator itor, action_ptr act)
00666 {
00667 resources::whiteboard->queue_net_cmd(team_index_,make_net_cmd_insert(itor,act));
00668 return raw_insert(itor,act);
00669 }
00670
00671 side_actions::iterator side_actions::synced_enqueue(size_t turn_num, action_ptr act)
00672 {
00673
00674
00675 iterator result = raw_enqueue(turn_num,act);
00676 resources::whiteboard->queue_net_cmd(team_index_,make_net_cmd_insert(turn_num,actions_[turn_num].size()-1,act));
00677 return result;
00678 }
00679
00680 side_actions::iterator side_actions::safe_erase(iterator const& itor)
00681 {
00682 action_ptr action = *itor;
00683 resources::whiteboard->pre_delete_action(action);
00684 iterator return_itor = raw_erase(itor);
00685 resources::whiteboard->post_delete_action(action);
00686 return return_itor;
00687 }
00688
00689 void side_actions::execute_net_cmd(net_cmd const& cmd)
00690 {
00691 std::string type = cmd["type"];
00692
00693 if(type=="insert")
00694 {
00695 size_t turn = cmd["turn"].to_int();
00696 size_t pos = cmd["pos"].to_int();
00697 action_ptr act = action::from_config(cmd.child("action"),hidden_);
00698 if(!act)
00699 {
00700 ERR_WB << "side_actions::execute_network_command(): received invalid action data!\n";
00701 return;
00702 }
00703
00704 iterator itor = safe_insert(turn,pos,act);
00705 if(itor == end())
00706 {
00707 ERR_WB << "side_actions::execute_network_command(): received invalid insertion position!\n";
00708 return;
00709 }
00710
00711
00712 ++itor;
00713 iterator end_itor = end();
00714 for( ; itor!=end_itor; ++itor)
00715 resources::screen->invalidate((*itor)->get_numbering_hex());
00716 }
00717 else if(type=="replace")
00718 {
00719 size_t turn = cmd["turn"].to_int();
00720 size_t pos = cmd["pos"].to_int();
00721 action_ptr act = action::from_config(cmd.child("action"),hidden_);
00722 if(!act)
00723 {
00724 ERR_WB << "side_actions::execute_network_command(): received invalid action data!\n";
00725 return;
00726 }
00727
00728 if(turn >= actions_.size()
00729 || pos >= actions_[turn].size())
00730 {
00731 ERR_WB << "side_actions::execute_network_command(): received invalid pos!\n";
00732 return;
00733 }
00734
00735 iterator itor = turn_begin(turn)+pos;
00736 itor = raw_insert(itor,act);
00737 safe_erase(++itor);
00738 }
00739 else if(type=="remove")
00740 {
00741 size_t turn = cmd["turn"].to_int();
00742 size_t pos = cmd["pos"].to_int();
00743 if(turn >= actions_.size()
00744 || pos >= actions_[turn].size())
00745 {
00746 ERR_WB << "side_actions::execute_network_command(): received invalid pos!\n";
00747 return;
00748 }
00749
00750 iterator itor = turn_begin(turn)+pos;
00751 itor = safe_erase(itor);
00752
00753
00754 iterator end_itor = end();
00755 for( ; itor!=end_itor; ++itor)
00756 resources::screen->invalidate((*itor)->get_numbering_hex());
00757 }
00758 else if(type=="bump_later")
00759 {
00760 size_t turn = cmd["turn"].to_int();
00761 size_t pos = cmd["pos"].to_int();
00762 if(turn >= actions_.size()
00763 || pos+1 >= actions_[turn].size())
00764 {
00765 ERR_WB << "side_actions::execute_network_command(): received invalid pos!\n";
00766 return;
00767 }
00768
00769 action_queue::iterator itor = actions_[turn].begin()+pos;
00770 action_ptr first_action = *itor;
00771 itor = actions_[turn].erase(itor);
00772 action_ptr second_action = *itor;
00773 actions_[turn].insert(++itor,first_action);
00774
00775
00776 resources::screen->invalidate(first_action->get_numbering_hex());
00777 resources::screen->invalidate(second_action->get_numbering_hex());
00778 }
00779 else if(type=="clear")
00780 {
00781 safe_clear();
00782 }
00783 else if(type=="refresh")
00784 {
00785 safe_clear();
00786 foreach(net_cmd const& sub_cmd, cmd.child_range("net_cmd"))
00787 execute_net_cmd(sub_cmd);
00788 }
00789 else
00790 {
00791 ERR_WB << "side_actions::execute_network_command(): received invalid type!\n";
00792 return;
00793 }
00794
00795 validate_actions();
00796 }
00797
00798 side_actions::net_cmd side_actions::make_net_cmd_insert(size_t turn_num, size_t pos, action_const_ptr act) const
00799 {
00800 net_cmd result;
00801 result["type"] = "insert";
00802 result["turn"] = static_cast<int>(turn_num);
00803 result["pos"] = static_cast<int>(pos);
00804 result.add_child("action",act->to_config());
00805 return result;
00806 }
00807 side_actions::net_cmd side_actions::make_net_cmd_insert(const_iterator const& pos, action_const_ptr act) const
00808 {
00809 return make_net_cmd_insert(pos.base_.turn_num_,std::distance<action_queue::const_iterator>(actions_[pos.base_.turn_num_].begin(),pos.base_.base_),act);
00810 }
00811 side_actions::net_cmd side_actions::make_net_cmd_replace(const_iterator const& pos, action_const_ptr act) const
00812 {
00813 net_cmd result;
00814 result["type"] = "replace";
00815 result["turn"] = static_cast<int>(pos.base_.turn_num_);
00816 result["pos"] = static_cast<int>(std::distance<action_queue::const_iterator>(actions_[pos.base_.turn_num_].begin(),pos.base_.base_));
00817 result.add_child("action",act->to_config());
00818 return result;
00819 }
00820 side_actions::net_cmd side_actions::make_net_cmd_remove(const_iterator const& pos) const
00821 {
00822 net_cmd result;
00823 result["type"] = "remove";
00824 result["turn"] = static_cast<int>(pos.base_.turn_num_);
00825 result["pos"] = static_cast<int>(std::distance<action_queue::const_iterator>(actions_[pos.base_.turn_num_].begin(),pos.base_.base_));
00826 return result;
00827 }
00828 side_actions::net_cmd side_actions::make_net_cmd_bump_later(const_iterator const& pos) const
00829 {
00830 net_cmd result;
00831 result["type"] = "bump_later";
00832 result["turn"] = static_cast<int>(pos.base_.turn_num_);
00833 result["pos"] = static_cast<int>(std::distance<action_queue::const_iterator>(actions_[pos.base_.turn_num_].begin(),pos.base_.base_));
00834 return result;
00835 }
00836 side_actions::net_cmd side_actions::make_net_cmd_clear() const
00837 {
00838 net_cmd result;
00839 result["type"] = "clear";
00840 return result;
00841 }
00842 side_actions::net_cmd side_actions::make_net_cmd_refresh() const
00843 {
00844 net_cmd result;
00845 result["type"] = "refresh";
00846
00847 const_iterator end = this->end();
00848 for(const_iterator itor=begin(); itor!=end; ++itor)
00849 result.add_child("net_cmd",make_net_cmd_insert(itor.base_.turn_num_,std::distance<action_queue::const_iterator>(actions_[itor.base_.turn_num_].begin(),itor.base_.base_),*itor));
00850
00851 return result;
00852 }
00853
00854
00855 side_actions::iterator side_actions::null(action_queue::iterator(),0,NULL);
00856
00857 bool side_actions::validate_iterator(iterator position) { return position != end(); }
00858
00859 side_actions::iterator side_actions::begin()
00860 {
00861 if(actions_.empty())
00862 return null;
00863 return iterator(actions_.front().begin(),0,*this);
00864 }
00865 side_actions::reverse_iterator side_actions::rbegin()
00866 { return reverse_iterator(end()); }
00867 side_actions::const_iterator side_actions::begin() const
00868 { return const_iterator(const_cast<side_actions*>(this)->begin()); }
00869 side_actions::const_reverse_iterator side_actions::rbegin() const
00870 { return const_reverse_iterator(const_cast<side_actions*>(this)->rbegin()); }
00871
00872 side_actions::iterator side_actions::end()
00873 {
00874 if(actions_.empty())
00875 return null;
00876 return iterator(actions_.back().end(),actions_.size()-1,*this);
00877 }
00878 side_actions::reverse_iterator side_actions::rend()
00879 { return reverse_iterator(begin()); }
00880 side_actions::const_iterator side_actions::end() const
00881 { return const_iterator(const_cast<side_actions*>(this)->end()); }
00882 side_actions::const_reverse_iterator side_actions::rend() const
00883 { return const_reverse_iterator(const_cast<side_actions*>(this)->rend()); }
00884
00885 void side_actions::raw_turn_shift()
00886 {
00887
00888 if(actions_.size() < 2)
00889 return;
00890
00891
00892 std::set<unit const*> lazy_units;
00893 foreach(action_ptr const& act, iter_turn(0))
00894 {
00895 unit const* u = act->get_unit();
00896 if(u)
00897 lazy_units.insert(u);
00898 }
00899
00900
00901 std::set<unit const*>::iterator lazy_end = lazy_units.end();
00902 iterator itor = end();
00903 while(itor != begin())
00904 {
00905 --itor;
00906 action_ptr act = *itor;
00907
00908 if(lazy_units.find(act->get_unit()) != lazy_end)
00909 {
00910 safe_insert(itor.turn_num_+1,0,act);
00911 itor = raw_erase(itor);
00912 }
00913 }
00914
00915
00916 foreach(action_ptr act, actions_.front())
00917 actions_[1].push_front(act);
00918 actions_.front().clear();
00919
00920
00921 actions_.pop_front();
00922 }
00923
00924 void side_actions::synced_turn_shift()
00925 {
00926 raw_turn_shift();
00927 resources::whiteboard->queue_net_cmd(team_index(),make_net_cmd_refresh());
00928 }
00929
00930 }