Merge branch 'test_recall_list'

This commit is contained in:
Chris Beck 2014-12-28 13:52:30 -05:00
commit 4cd2f6b88b
7 changed files with 157 additions and 66 deletions

View file

@ -739,6 +739,7 @@ test_sources = Split("""
tests/test_rng.cpp
tests/test_mp_connect.cpp
tests/test_network_worker.cpp
tests/test_recall_list.cpp
tests/test_sdl_utils.cpp
tests/test_serialization.cpp
tests/test_team.cpp

View file

@ -1528,22 +1528,22 @@ void attack_unit_and_advance(const map_location &attacker, const map_location &d
}
unit get_advanced_unit(const unit &u, const std::string& advance_to)
unit_ptr get_advanced_unit(const unit &u, const std::string& advance_to)
{
const unit_type *new_type = unit_types.find(advance_to);
if (!new_type) {
throw game::game_error("Could not find the unit being advanced"
" to: " + advance_to);
}
unit new_unit(u);
new_unit.set_experience(new_unit.experience() - new_unit.max_experience());
new_unit.advance_to(*new_type);
new_unit.heal_all();
new_unit.set_state(unit::STATE_POISONED, false);
new_unit.set_state(unit::STATE_SLOWED, false);
new_unit.set_state(unit::STATE_PETRIFIED, false);
new_unit.set_user_end_turn(false);
new_unit.set_hidden(false);
unit_ptr new_unit(new unit(u));
new_unit->set_experience(new_unit->experience() - new_unit->max_experience());
new_unit->advance_to(*new_type);
new_unit->heal_all();
new_unit->set_state(unit::STATE_POISONED, false);
new_unit->set_state(unit::STATE_SLOWED, false);
new_unit->set_state(unit::STATE_PETRIFIED, false);
new_unit->set_user_end_turn(false);
new_unit->set_hidden(false);
return new_unit;
}
@ -1551,11 +1551,11 @@ unit get_advanced_unit(const unit &u, const std::string& advance_to)
/**
* Returns the AMLA-advanced version of a unit (with traits and items retained).
*/
unit get_amla_unit(const unit &u, const config &mod_option)
unit_ptr get_amla_unit(const unit &u, const config &mod_option)
{
unit amla_unit(u);
amla_unit.set_experience(amla_unit.experience() - amla_unit.max_experience());
amla_unit.add_modification("advance", mod_option);
unit_ptr amla_unit(new unit(u));
amla_unit->set_experience(amla_unit->experience() - amla_unit->max_experience());
amla_unit->add_modification("advance", mod_option);
return amla_unit;
}
@ -1593,19 +1593,19 @@ void advance_unit(map_location loc, const std::string &advance_to,
// Create the advanced unit.
bool use_amla = mod_option != NULL;
unit new_unit = use_amla ? get_amla_unit(*u, *mod_option) :
unit_ptr new_unit = use_amla ? get_amla_unit(*u, *mod_option) :
get_advanced_unit(*u, advance_to);
if ( !use_amla )
{
statistics::advance_unit(new_unit);
preferences::encountered_units().insert(new_unit.type_id());
LOG_CF << "Added '" << new_unit.type_id() << "' to the encountered units.\n";
statistics::advance_unit(*new_unit);
preferences::encountered_units().insert(new_unit->type_id());
LOG_CF << "Added '" << new_unit->type_id() << "' to the encountered units.\n";
}
u = resources::units->replace(loc, new_unit).first;
u = resources::units->replace(loc, *new_unit).first;
// Update fog/shroud.
actions::shroud_clearer clearer;
clearer.clear_unit(loc, new_unit);
clearer.clear_unit(loc, *new_unit);
// "post_advance" event.
if(fire_event)

View file

@ -230,12 +230,12 @@ void advance_unit_at(const advance_unit_params& params);
/**
* Returns the advanced version of a unit (with traits and items retained).
*/
unit get_advanced_unit(const unit &u, const std::string &advance_to);
unit_ptr get_advanced_unit(const unit &u, const std::string &advance_to);
/**
* Returns the AMLA-advanced version of a unit (with traits and items retained).
*/
unit get_amla_unit(const unit &u, const config &mod_option);
unit_ptr get_amla_unit(const unit &u, const config &mod_option);
/**
* Function which will advance the unit at @a loc to 'advance_to'.

View file

@ -63,6 +63,7 @@
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
//#ifdef _WIN32
//#include "locale.h"
@ -91,20 +92,33 @@ namespace
class delete_recall_unit : public gui::dialog_button_action
{
public:
delete_recall_unit(display& disp, gui::filter_textbox& filter, const std::vector<unit_const_ptr >& units) : disp_(disp), filter_(filter), units_(units) {}
delete_recall_unit(display& disp, gui::filter_textbox& filter, const boost::shared_ptr<std::vector<unit_const_ptr > >& units) : disp_(disp), filter_(filter), units_(units) {}
private:
gui::dialog_button_action::RESULT button_pressed(int menu_selection);
display& disp_;
gui::filter_textbox& filter_;
const std::vector<unit_const_ptr >& units_;
boost::shared_ptr<std::vector<unit_const_ptr > > units_;
};
template<typename T> void dump(const T & units)
{
log_scope2(log_display, "dump()")
LOG_DP << "size: " << units.size() << "\n";
size_t idx = 0;
BOOST_FOREACH(const unit_const_ptr & u_ptr, units) {
LOG_DP << "unit[" << (idx++) << "]: " << u_ptr->id() << " name = '" << u_ptr->name() << "'\n";
}
}
gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_selection)
{
const size_t index = size_t(filter_.get_index(menu_selection));
if(index < units_.size()) {
const unit_const_ptr & u_ptr = units_[index];
LOG_DP << "units_:\n"; dump(*units_);
if(index < units_->size()) {
const unit_const_ptr & u_ptr = units_->at(index);
const unit & u = *u_ptr;
//If the unit is of level > 1, or is close to advancing,
@ -131,11 +145,18 @@ gui::dialog_button_action::RESULT delete_recall_unit::button_pressed(int menu_se
return gui::CONTINUE_DIALOG;
}
}
// Remove the item from our dialog's list
units_->erase(units_->begin() + index);
// Remove the item from filter_textbox memory
filter_.delete_item(menu_selection);
//add dismissal to the undo stack
resources::undo_stack->add_dismissal(u_ptr);
LOG_DP << "Dismissing a unit, side = " << u.side() << " id = '" << u.id() << "'\n";
LOG_DP << "That side's recall list:\n";
dump((*resources::teams)[u.side() -1].recall_list());
// Find the unit in the recall list.
unit_ptr dismissed_unit = (*resources::teams)[u.side() -1].recall_list().find_if_matches_id(u.id());
assert(dismissed_unit);
@ -161,10 +182,10 @@ int advance_unit_dialog(const map_location &loc)
std::vector<std::string> lang_options;
std::vector<unit> sample_units;
boost::shared_ptr<std::vector<unit_const_ptr> > sample_units(boost::make_shared<std::vector<unit_const_ptr> >());
for(std::vector<std::string>::const_iterator op = options.begin(); op != options.end(); ++op) {
sample_units.push_back(::get_advanced_unit(*u, *op));
const unit& type = sample_units.back();
sample_units->push_back(::get_advanced_unit(*u, *op));
const unit& type = *sample_units->back();
#ifdef LOW_MEM
lang_options.push_back(IMAGE_PREFIX
@ -180,8 +201,8 @@ int advance_unit_dialog(const map_location &loc)
BOOST_FOREACH(const config &mod, u->get_modification_advances())
{
if (mod["always_display"].to_bool()) always_display = true;
sample_units.push_back(::get_amla_unit(*u, mod));
const unit& type = sample_units.back();
sample_units->push_back(::get_amla_unit(*u, mod));
const unit& type = *sample_units->back();
if (!mod["image"].empty()) {
lang_options.push_back(IMAGE_PREFIX + mod["image"].str() + COLUMN_SEPARATOR + mod["description"].str());
} else {
@ -296,7 +317,7 @@ void show_unit_list(display& gui)
items.push_back(heading);
std::vector<map_location> locations_list;
std::vector<unit> units_list;
boost::shared_ptr<std::vector<unit_const_ptr> > units_list = boost::make_shared<std::vector<unit_const_ptr> >();
int selected = 0;
@ -310,7 +331,7 @@ void show_unit_list(display& gui)
// If a unit is already selected on the map, we do the same in the unit list dialog
if (gui.selected_hex() == i->get_location()) {
row << DEFAULT_ITEM;
selected = units_list.size();
selected = units_list->size();
}
// If unit is leader, show name in special color, e.g. gold/silver
/** @todo TODO: hero just has overlay "misc/hero-icon.png" - needs an ability to query */
@ -378,7 +399,7 @@ void show_unit_list(display& gui)
items.push_back(row.str());
locations_list.push_back(i->get_location());
units_list.push_back(*i);
units_list->push_back(i.get_shared_ptr());
}
{
@ -445,9 +466,9 @@ int recruit_dialog(display& disp, std::vector< const unit_type* >& units, const
#ifdef LOW_MEM
int recall_dialog(display& disp, std::vector< unit_const_ptr >& units, int /*side*/, const std::string& title_suffix, const int team_recall_cost)
int recall_dialog(display& disp, const boost::shared_ptr<std::vector< unit_const_ptr > > & units, int /*side*/, const std::string& title_suffix, const int team_recall_cost)
#else
int recall_dialog(display& disp, std::vector< unit_const_ptr >& units, int side, const std::string& title_suffix, const int team_recall_cost)
int recall_dialog(display& disp, const boost::shared_ptr<std::vector< unit_const_ptr > > & units, int side, const std::string& title_suffix, const int team_recall_cost)
#endif
{
std::vector<std::string> options, options_to_filter;
@ -466,7 +487,7 @@ int recall_dialog(display& disp, std::vector< unit_const_ptr >& units, int side,
options.push_back(heading.str());
options_to_filter.push_back(options.back());
BOOST_FOREACH(const unit_const_ptr & u, units)
BOOST_FOREACH(const unit_const_ptr & u, *units)
{
std::stringstream option, option_to_filter;
std::string name = u->name();
@ -1364,36 +1385,28 @@ void unit_preview_pane::draw_contents()
#endif
}
units_list_preview_pane::units_list_preview_pane(unit_const_ptr u, TYPE type, bool on_left_side) :
unit_preview_pane(NULL, type, on_left_side),
units_(1, u)
units_(boost::make_shared<const std::vector<unit_const_ptr> >(1, u))
{
}
units_list_preview_pane::units_list_preview_pane(const std::vector<unit_const_ptr > &units,
units_list_preview_pane::units_list_preview_pane(const boost::shared_ptr<const std::vector<unit_const_ptr > > &units,
const gui::filter_textbox* filter, TYPE type, bool on_left_side) :
unit_preview_pane(filter, type, on_left_side),
units_(units)
{
}
units_list_preview_pane::units_list_preview_pane(const std::vector<unit> &units,
const gui::filter_textbox* filter, TYPE type, bool on_left_side) :
unit_preview_pane(filter, type, on_left_side),
units_(units.size())
{
for (unsigned i = 0; i < units.size(); ++i)
units_[i] = unit_const_ptr (new unit(units[i]));
}
size_t units_list_preview_pane::size() const
{
return units_.size();
return units_->size();
}
const unit_preview_pane::details units_list_preview_pane::get_details() const
{
const unit &u = *units_[index_];
const unit &u = *units_->at(index_);
details det;
/** Get an SDL surface, ready for display for place where we need a still-image of the unit. */
@ -1453,7 +1466,7 @@ const unit_preview_pane::details units_list_preview_pane::get_details() const
void units_list_preview_pane::process_event()
{
if (details_button_.pressed() && index_ >= 0 && index_ < int(size())) {
help::show_unit_description(*units_[index_]);
help::show_unit_description(*units_->at(index_));
}
}

View file

@ -60,7 +60,7 @@ std::string load_game_dialog(display& disp, const config& terrain_config, bool*
int recruit_dialog(display& disp, std::vector<const unit_type*>& units, const std::vector<std::string>& items, int side, const std::string& title_suffix);
int recall_dialog(display& disp, std::vector<unit_const_ptr >& units, int side, const std::string& title_suffix, const int team_recall_cost);
int recall_dialog(display& disp, const boost::shared_ptr<std::vector<unit_const_ptr > > & units, int side, const std::string& title_suffix, const int team_recall_cost);
/** Show unit-stats in a side-pane to unit-list, recall-list, etc. */
class unit_preview_pane : public gui::preview_pane
@ -116,10 +116,7 @@ class units_list_preview_pane : public dialogs::unit_preview_pane
{
public:
units_list_preview_pane(unit_const_ptr u, TYPE type = SHOW_ALL, bool left_side = true);
units_list_preview_pane(const std::vector<unit_const_ptr > &units,
const gui::filter_textbox *filter = NULL,
TYPE type = SHOW_ALL, bool left_side = true);
units_list_preview_pane(const std::vector<unit> &units,
units_list_preview_pane(const boost::shared_ptr<const std::vector<unit_const_ptr > > & units,
const gui::filter_textbox *filter = NULL,
TYPE type = SHOW_ALL, bool left_side = true);
@ -128,7 +125,7 @@ private:
const details get_details() const;
void process_event();
std::vector<unit_const_ptr > units_;
boost::shared_ptr<const std::vector<unit_const_ptr > > units_;
};

View file

@ -685,16 +685,16 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
return;
}
std::vector<unit_const_ptr > recall_list_team;
boost::shared_ptr<std::vector<unit_const_ptr > > recall_list_team = boost::make_shared<std::vector<unit_const_ptr> >();
{ wb::future_map future; // ensures recall list has planned recalls removed
recall_list_team = actions::get_recalls(side_num, last_hex);
*recall_list_team = actions::get_recalls(side_num, last_hex);
}
gui_->draw(); //clear the old menu
DBG_WB <<"menu_handler::recall: Contents of wb-modified recall list:\n";
BOOST_FOREACH(const unit_const_ptr & unit, recall_list_team)
BOOST_FOREACH(const unit_const_ptr & unit, *recall_list_team)
{
DBG_WB << unit->name() << " [" << unit->id() <<"]\n";
}
@ -705,7 +705,7 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
" veteran survivors from a previous scenario)"));
return;
}
if(recall_list_team.empty()) {
if(recall_list_team->empty()) {
gui2::show_transient_message(gui_->video(), "",
_("You currently can't recall at the highlighted location"));
return;
@ -720,8 +720,8 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
// if it does we use it elsewise we use the team.recall_cost()
// the magic number -1 is what it gets set to if the unit doesn't
// have a special recall_cost of its own.
else if(recall_list_team[res]->recall_cost() > -1) {
unit_cost = recall_list_team[res]->recall_cost();
else if(recall_list_team->at(res)->recall_cost() > -1) {
unit_cost = recall_list_team->at(res)->recall_cost();
}
int wb_gold = pc_.get_whiteboard() ? pc_.get_whiteboard()->get_spent_gold_for(side_num) : 0;
@ -743,16 +743,16 @@ void menu_handler::recall(int side_num, const map_location &last_hex)
map_location recall_from = map_location::null_location();
std::string err;
{ wb::future_map_if_active future; // future unit map removes invisible units from map, don't do this outside of planning mode
err = actions::find_recall_location(side_num, recall_location, recall_from, *(recall_list_team[res]));
err = actions::find_recall_location(side_num, recall_location, recall_from, *(recall_list_team->at(res)));
} // end planned unit map scope
if(!err.empty()) {
gui2::show_transient_message(gui_->video(), "", err);
return;
}
if (!pc_.get_whiteboard() || !pc_.get_whiteboard()->save_recall(*recall_list_team[res], side_num, recall_location)) {
if (!pc_.get_whiteboard() || !pc_.get_whiteboard()->save_recall(*recall_list_team->at(res), side_num, recall_location)) {
bool success = synced_context::run_in_synced_context("recall",
replay_helper::get_recall(recall_list_team[res]->id(), recall_location, recall_from),
replay_helper::get_recall(recall_list_team->at(res)->id(), recall_location, recall_from),
true,
true,
true,

View file

@ -0,0 +1,80 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include <boost/test/unit_test.hpp>
#include "config.hpp"
#include "config_assign.hpp"
#include "recall_list_manager.hpp"
#include "tests/utils/game_config_manager.hpp"
#include "unit.hpp"
#include "unit_ptr.hpp"
BOOST_AUTO_TEST_SUITE( recall_list_suite )
BOOST_AUTO_TEST_CASE( test_1 ) {
config game_config(test_utils::get_test_config());
config orc_config = config_of
("id", "Orcish Grunt")
("random_traits", false)
("animate", false);
unit_type orc_type(orc_config);
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit_ptr orc1(new unit(orc_type, 1, false));
unit_ptr orc2(new unit(orc_type, 1, false));
orc1->set_name("Larry");
orc2->set_name("Moe");
orc1->set_id("larry");
orc2->set_id("moe");
recall_list_manager recall_man;
BOOST_CHECK_EQUAL(recall_man.size(), 0);
BOOST_CHECK_MESSAGE(recall_man.begin() == recall_man.end(), "failed begin() == end() for an empty container");
recall_man.add(orc1);
BOOST_CHECK_EQUAL(recall_man.size(), 1);
BOOST_CHECK_MESSAGE(recall_man[0] == orc1, "unexpected result at index [0]");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("larry") == orc1, "found something unexpected");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("moe") == false, "found something unexpected");
recall_man.add(orc2);
BOOST_CHECK_EQUAL(recall_man.size(), 2);
BOOST_CHECK_MESSAGE(recall_man[0] == orc1, "unexpected result at index [0]");
BOOST_CHECK_MESSAGE(recall_man[1] == orc2, "unexpected result at index [1]");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("larry") == orc1, "found something unexpected");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("moe") == orc2, "found something unexpected");
recall_man.erase_if_matches_id("larry");
BOOST_CHECK_EQUAL(recall_man.size(), 1);
BOOST_CHECK_MESSAGE(recall_man[0] == orc2, "unexpected result at index [0]");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("larry") == false, "found something unexpected");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("moe") == orc2, "found something unexpected");
recall_man.add(orc1);
BOOST_CHECK_EQUAL(recall_man.size(), 2);
BOOST_CHECK_MESSAGE(recall_man[0] == orc2, "unexpected result at index [0]");
BOOST_CHECK_MESSAGE(recall_man[1] == orc1, "unexpected result at index [1]");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("larry") == orc1, "found something unexpected");
BOOST_CHECK_MESSAGE(recall_man.find_if_matches_id("moe") == orc2, "found something unexpected");
}
BOOST_AUTO_TEST_SUITE_END()