Example #1
0
pathfind::teleport_map::teleport_map(
		  const std::vector<teleport_group>& groups
		, const unit& u
		, const team &viewing_team
		, const bool see_all
		, const bool ignore_units)
	: teleport_map_()
	, sources_()
	, targets_()
{

	foreach(const teleport_group& group, groups) {

		teleport_pair locations;
		group.get_teleport_pair(locations, u, ignore_units);
		if (!see_all && !group.always_visible() && viewing_team.is_enemy(u.side())) {
			teleport_pair filter_locs;
			foreach(const map_location &loc, locations.first)
				if(!viewing_team.fogged(loc))
					filter_locs.first.insert(loc);
			foreach(const map_location &loc, locations.second)
				if(!viewing_team.fogged(loc))
					filter_locs.second.insert(loc);
			locations.first.swap(filter_locs.first);
			locations.second.swap(filter_locs.second);
		}
Example #2
0
bool recall_result::test_enough_gold(const team &my_team)
{
	if (my_team.gold() < my_team.recall_cost() ) {
		set_error(E_NO_GOLD);
		return false;
	}
	return true;
}
Example #3
0
void show_objectives(const config &level, const team& t)
{
	static const std::string no_objectives(_("No objectives available"));
	const std::string& objectives = t.objectives();

	gui2::show_transient_message(resources::screen->video(), level["name"],	
		t.form_results_of_battle_tip(objectives.empty() ? no_objectives : objectives), "", true);
}
Example #4
0
bool recall_result::test_available_for_recalling(const team &my_team, bool)
{
	const std::vector<unit>::const_iterator rec = std::find_if(my_team.recall_list().begin(), my_team.recall_list().end(), boost::bind(&unit::matches_id, _1, unit_id_));
	if (rec == my_team.recall_list().end()) {
		set_error(E_NOT_AVAILABLE_FOR_RECALLING);
		return false;
	}
	return true;
}
Example #5
0
carryover::carryover(const team& t, const int gold, const bool add)
		: add_ (add)
		, current_player_(t.current_player())
		, gold_(gold)
		, previous_recruits_(t.recruits())
		, recall_list_()
		, save_id_(t.save_id())
		, variables_(t.variables())
{
	for(const unit_const_ptr & u : t.recall_list()) {
		recall_list_.emplace_back();
		u->write(recall_list_.back());
	}
}
Example #6
0
bool recall_result::test_enough_gold(const team &my_team,  bool)
{
	if (my_team.gold() < game_config::recall_cost ) {
		set_error(E_NO_GOLD);
		return false;
	}
	return true;
}
Example #7
0
bool recruit_result::test_enough_gold(const team &my_team, const unit_type &type, bool)
{
	if (my_team.gold() < type.cost()) {
		set_error(E_NO_GOLD);
		return false;
	}
	return true;
}
Example #8
0
unit_const_ptr recall_result::get_recall_unit(const team &my_team)
{
	unit_const_ptr rec = my_team.recall_list().find_if_matches_id(unit_id_);
	if (!rec) {
		set_error(E_NOT_AVAILABLE_FOR_RECALLING);
	}
	return rec;
}
Example #9
0
void strategy_formulation_with_rca::on_create()
{
	const std::vector<team> teams = *resources::teams;
	const int own_side = this->get_side();
	const team own_team = teams[own_side-1];

	rca_->on_create();

	for(size_t i = 0; i != teams.size(); ++i){
		if(own_side+i <= teams.size()){
			enemy_this_turn_.push_back(own_team.is_enemy(own_side+i));
		} else {
			enemy_this_turn_.push_back(own_team.is_enemy((own_side+i)%teams.size()));
		}
	}

	enemy_this_turn_.push_back(false);
}
Example #10
0
static bool check_side_number(const team &t, const std::string &str)
{
		std::vector<std::string> list = utils::split(str);
		std::string side_number = str_cast(t.side());
		if (std::find(list.begin(),list.end(),side_number)==list.end())
		{
			return false;
		}
		return true;
}
Example #11
0
bool game_board::team_is_defeated(const team& t) const
{
	switch(t.defeat_condition().v)
	{
	case team::DEFEAT_CONDITION::ALWAYS:
		return true;
	case team::DEFEAT_CONDITION::NO_LEADER:
		return !units_.find_leader(t.side()).valid();
	case team::DEFEAT_CONDITION::NO_UNITS:
		for (const unit& u : units_)
		{
			if(u.side() == t.side())
				return false;
		}
		return true;
	case team::DEFEAT_CONDITION::NEVER:
	default:
		return false;
	}
}
Example #12
0
void sim1(team &T1,team &T2)
{
    system("cls");

	int a,b,p = 0,q = 0,i,j = 9000;
	float k =0;
    srand(time(NULL));
	
    a = rand()%5;
    b = rand()%5;
  
    if (a>b)
    {       
		T1.add();
		T1.points+=3;
		T1.w++;
		T2.l++;
	}
           
    else if(a==b)
    {
       T1.points+=1;
       T2.points+=1;
       T1.rem+=2000;
       T2.rem+=2000;
       T1.d++;
       T2.d++;
    }
   
    else
    {
       T2.points+=3;
       T2.add();
       T2.w++;
	   T1.l++;
    }
   
    T1.deduct();

}
Example #13
0
std::set<map_location> get_teleport_locations(const unit &u,
	const unit_map &units, const team &viewing_team,
	bool see_all, bool ignore_units)
{
	std::set<map_location> res;
	if (!u.get_ability_bool("teleport")) return res;

	const team &current_team = (*resources::teams)[u.side() - 1];
	const map_location &loc = u.get_location();
	foreach (const map_location &l, current_team.villages())
	{
		// This must be a vacant village (or occupied by the unit)
		// to be able to teleport.
		if (!see_all && viewing_team.is_enemy(u.side()) && viewing_team.fogged(l))
			continue;
		if (!ignore_units && l != loc &&
		    get_visible_unit(units, l, viewing_team, see_all))
			continue;
		res.insert(l);
	}
	return res;
}
team_data display_context::calculate_team_data(const team& tm) const
{
	team_data res;
	res.units = side_units(tm.side());
	res.upkeep = side_upkeep(tm.side());
	res.villages = tm.villages().size();
	res.expenses = std::max<int>(0,res.upkeep - tm.support());
	res.net_income = tm.total_income() - res.expenses;
	res.gold = tm.gold();
	res.teamname = tm.user_team_name();
	return res;
}
bool revivaled_can_auto_end_turn(const team& t)
{
	if (tent::mode == mode_tag::TOWER || tent::mode == mode_tag::LAYOUT) {
		return true;
	}

	const std::pair<unit**, size_t> p = t.field_troop();
	for (size_t i = 0; i < p.second; i ++) {
		unit& u = *p.first[i];
		if (u.get_state(ustate_tag::REVIVALED) && u.attacks_left()) {
			return false;
		}
	}
	return true;
}
Example #16
0
carryover::carryover(const team& t, const int gold, const bool add)
		: add_ (add)
		, color_(t.color())
		, current_player_(t.current_player())
		, gold_(gold)
		, name_(t.name())
		, previous_recruits_(t.recruits())
		, recall_list_(t.recall_list())
		, save_id_(t.save_id())
		{}
Example #17
0
/**
 * Sets @a jamming to the (newly calculated) "jamming" map for @a view_team.
 */
static void create_jamming_map(std::map<map_location, int> & jamming,
                               const team & view_team)
{
	// Reset the map.
	jamming.clear();

	// Build the map.
	for (const unit &u : resources::gameboard->units())
	{
		if ( u.jamming() < 1  ||  !view_team.is_enemy(u.side()) )
			continue;

		pathfind::jamming_path jam_path(u, u.get_location());
		for (const pathfind::paths::step& st : jam_path.destinations) {
			if ( jamming[st.curr] < st.move_left )
				jamming[st.curr] = st.move_left;
		}
	}
}
carryover::carryover(const team& t, const int gold, const bool add)
		: add_ (add)
		, color_(t.color())
		, current_player_(t.current_player())
		, gold_(gold)
		, name_(t.name())
		, previous_recruits_(t.recruits())
		, recall_list_()
		, save_id_(t.save_id())
{
	BOOST_FOREACH(const unit_const_ptr & u, t.recall_list()) {
		recall_list_.push_back(config());
		u->write(recall_list_.back());
	}
}
Example #19
0
void aspect_attacks::do_attack_analysis(
    const map_location& loc,
    const move_map& srcdst, const move_map& dstsrc,
    const move_map& fullmove_srcdst, const move_map& fullmove_dstsrc,
    const move_map& enemy_srcdst, const move_map& enemy_dstsrc,
    const map_location* tiles, bool* used_locations,
    std::vector<map_location>& units,
    std::vector<attack_analysis>& result,
    attack_analysis& cur_analysis,
    const team &current_team
) const
{
    // This function is called fairly frequently, so interact with the user here.

    ai::manager::raise_user_interact();
    const int default_attack_depth = 5;
    if(cur_analysis.movements.size() >= size_t(default_attack_depth)) {
        //std::cerr << "ANALYSIS " << cur_analysis.movements.size() << " >= " << get_attack_depth() << "\n";
        return;
    }
    gamemap &map_ = *resources::game_map;
    unit_map &units_ = *resources::units;
    std::vector<team> &teams_ = *resources::teams;


    const size_t max_positions = 1000;
    if(result.size() > max_positions && !cur_analysis.movements.empty()) {
        LOG_AI << "cut analysis short with number of positions\n";
        return;
    }

    for(size_t i = 0; i != units.size(); ++i) {
        const map_location current_unit = units[i];

        unit_map::iterator unit_itor = units_.find(current_unit);
        assert(unit_itor != units_.end());

        // See if the unit has the backstab ability.
        // Units with backstab will want to try to have a
        // friendly unit opposite the position they move to.
        //
        // See if the unit has the slow ability -- units with slow only attack first.
        bool backstab = false, slow = false;
        std::vector<attack_type>& attacks = unit_itor->attacks();
        for(std::vector<attack_type>::iterator a = attacks.begin(); a != attacks.end(); ++a) {
            a->set_specials_context(map_location(), map_location(), units_, true, NULL);
            if(a->get_special_bool("backstab")) {
                backstab = true;
            }

            if(a->get_special_bool("slow")) {
                slow = true;
            }
        }

        if(slow && cur_analysis.movements.empty() == false) {
            continue;
        }

        // Check if the friendly unit is surrounded,
        // A unit is surrounded if it is flanked by enemy units
        // and at least one other enemy unit is nearby
        // or if the unit is totaly surrounded by enemies
        // with max. one tile to escape.
        bool is_surrounded = false;
        bool is_flanked = false;
        int enemy_units_around = 0;
        int accessible_tiles = 0;
        map_location adj[6];
        get_adjacent_tiles(current_unit, adj);

        size_t tile;
        for(tile = 0; tile != 3; ++tile) {

            const unit_map::const_iterator tmp_unit = units_.find(adj[tile]);
            bool possible_flanked = false;

            if(map_.on_board(adj[tile]))
            {
                accessible_tiles++;
                if (tmp_unit != units_.end() && current_team.is_enemy(tmp_unit->side()))
                {
                    enemy_units_around++;
                    possible_flanked = true;
                }
            }

            const unit_map::const_iterator tmp_opposite_unit = units_.find(adj[tile + 3]);
            if(map_.on_board(adj[tile + 3]))
            {
                accessible_tiles++;
                if (tmp_opposite_unit != units_.end() && current_team.is_enemy(tmp_opposite_unit->side()))
                {
                    enemy_units_around++;
                    if(possible_flanked)
                    {
                        is_flanked = true;
                    }
                }
            }
        }

        if((is_flanked && enemy_units_around > 2) || enemy_units_around >= accessible_tiles - 1)
            is_surrounded = true;



        double best_vulnerability = 0.0, best_support = 0.0;
        int best_rating = 0;
        int cur_position = -1;

        // Iterate over positions adjacent to the unit, finding the best rated one.
        for(int j = 0; j != 6; ++j) {

            // If in this planned attack, a unit is already in this location.
            if(used_locations[j]) {
                continue;
            }

            // See if the current unit can reach that position.
            if (tiles[j] != current_unit) {
                typedef std::multimap<map_location,map_location>::const_iterator Itor;
                std::pair<Itor,Itor> its = dstsrc.equal_range(tiles[j]);
                while(its.first != its.second) {
                    if(its.first->second == current_unit)
                        break;
                    ++its.first;
                }

                // If the unit can't move to this location.
                if(its.first == its.second || units_.find(tiles[j]) != units_.end()) {
                    continue;
                }
            }

            unit_ability_list abil = unit_itor->get_abilities("leadership",tiles[j]);
            int best_leadership_bonus = abil.highest("value").first;
            double leadership_bonus = static_cast<double>(best_leadership_bonus+100)/100.0;
            if (leadership_bonus > 1.1) {
                LOG_AI << unit_itor->name() << " is getting leadership " << leadership_bonus << "\n";
            }

            // Check to see whether this move would be a backstab.
            int backstab_bonus = 1;
            double surround_bonus = 1.0;

            if(tiles[(j+3)%6] != current_unit) {
                const unit_map::const_iterator itor = units_.find(tiles[(j+3)%6]);

                // Note that we *could* also check if a unit plans to move there
                // before we're at this stage, but we don't because, since the
                // attack calculations don't actually take backstab into account (too complicated),
                // this could actually make our analysis look *worse* instead of better.
                // So we only check for 'concrete' backstab opportunities.
                // That would also break backstab_check, since it assumes
                // the defender is in place.
                if(itor != units_.end() &&
                        backstab_check(tiles[j], loc, units_, teams_)) {
                    if(backstab) {
                        backstab_bonus = 2;
                    }

                    // No surround bonus if target is skirmisher
                    if (!itor->get_ability_bool("skirmisher"))
                        surround_bonus = 1.2;
                }


            }

            // See if this position is the best rated we've seen so far.
            int rating = static_cast<int>(rate_terrain(*unit_itor, tiles[j]) * backstab_bonus * leadership_bonus);
            if(cur_position >= 0 && rating < best_rating) {
                continue;
            }

            // Find out how vulnerable we are to attack from enemy units in this hex.
            //FIXME: suokko's r29531 multiplied this by a constant 1.5. ?
            const double vulnerability = power_projection(tiles[j],enemy_dstsrc);//?

            // Calculate how much support we have on this hex from allies.
            const double support = power_projection(tiles[j], fullmove_dstsrc);//?

            // If this is a position with equal defense to another position,
            // but more vulnerability then we don't want to use it.
#ifdef SUOKKO
            //FIXME: this code was in sukko's r29531  Correct?
            // scale vulnerability to 60 hp unit
            if(cur_position >= 0 && rating < best_rating
                    && (vulnerability/surround_bonus*30.0)/unit_itor->second.hitpoints() -
                    (support*surround_bonus*30.0)/unit_itor->second.max_hitpoints()
                    > best_vulnerability - best_support) {
                continue;
            }
#else
            if(cur_position >= 0 && rating == best_rating && vulnerability/surround_bonus - support*surround_bonus >= best_vulnerability - best_support) {
                continue;
            }
#endif
            cur_position = j;
            best_rating = rating;
#ifdef SUOKKO
            //FIXME: this code was in sukko's r29531  Correct?
            best_vulnerability = (vulnerability/surround_bonus*30.0)/unit_itor->second.hitpoints();
            best_support = (support*surround_bonus*30.0)/unit_itor->second.max_hitpoints();
#else
            best_vulnerability = vulnerability/surround_bonus;
            best_support = support*surround_bonus;
#endif
        }

        if(cur_position != -1) {
            units.erase(units.begin() + i);

            cur_analysis.movements.push_back(std::pair<map_location,map_location>(current_unit,tiles[cur_position]));

            cur_analysis.vulnerability += best_vulnerability;

            cur_analysis.support += best_support;

            cur_analysis.is_surrounded = is_surrounded;
            cur_analysis.analyze(map_, units_, *this, dstsrc, srcdst, enemy_dstsrc, get_aggression());
            result.push_back(cur_analysis);
            used_locations[cur_position] = true;
            do_attack_analysis(loc,srcdst,dstsrc,fullmove_srcdst,fullmove_dstsrc,enemy_srcdst,enemy_dstsrc,
                               tiles,used_locations,
                               units,result,cur_analysis, current_team);
            used_locations[cur_position] = false;


            cur_analysis.vulnerability -= best_vulnerability;
            cur_analysis.support -= best_support;

            cur_analysis.movements.pop_back();

            units.insert(units.begin() + i, current_unit);
        }
    }
}
Example #20
0
void sim2(team &T1,team &T2)
{
    system("cls");
    fstream f("team.dat",ios::in);
    player p1;
    int l,sum=0;

	for(int i=0;i<5;i++)
	{
        f.read((char *)&p1,sizeof(player));
        sum+=p1.rate;
    }
    
    f.close();
	
	int res;
	
    if((sum>380)&&(sum<410))
	   res=1;
	
    else if((sum>410)&&(sum<430))
	   res=2;
	
    else if((sum>430)&&(sum<450))
	   res=3;
	
    else if((sum>450)&&(sum<470))
	   res=4;
	
    else if((sum>470)&&(sum<500))
	res=5;
	
	
	int a,b,p = 0,q = 0,i,j = 9000;
	float k =0;
    srand(time(NULL));
    
    gotoxy(58,6);
	cout<<"___________________\n";
	gotoxy(58,12);
	cout<<"___________________\n";
	gotoxy(58,7);
	cout<<"|";
	gotoxy(58,8);
	cout<<"|";
	gotoxy(58,9);
	cout<<"|";
	gotoxy(58,10);
	cout<<"|";
	gotoxy(58,11);
	cout<<"|";
	gotoxy(58,12);
	cout<<"|";
	gotoxy(76,7);
	cout<<"|";
	gotoxy(76,8);
	cout<<"|";
	gotoxy(76,9);
	cout<<"|";
	gotoxy(76,10);
	cout<<"|";
	gotoxy(76,11);
	cout<<"|";
	gotoxy(76,12);
	cout<<"|";
	
	gotoxy(60,8);
    cout<<T1.retname();
    gotoxy(70,8);
    cout<<T2.retname();
	
    while(j--)
	{
              k = k + 0.01;
              gotoxy(63,4);
              cout<<"TIME : "<<(int)k;
    }
   
    a = rand()%3+res;
    b = rand()%5;
  
    gotoxy(60,10);
    cout<<"  "<<a;
    gotoxy(70,10);
    cout<<"  "<<b; 
        
    gotoxy(10,8);
	
    if (a>b)
    {       
		char ch;
        T1.add();
		T1.points+=3;
		T1.w++;
		T2.l++;
		cout<<"\n\n\n\nBrilliant!!!!:D You are the new champions League Winner.";
		final();
Example #21
0
void sim(team &T1,team &T2)
{
    system("cls");
    fstream f("team.dat",ios::in);
    player p1;
    int l,sum=0;
	for(int i=0;i<5;i++)
	{
        f.read((char *)&p1,sizeof(player));
        sum+=p1.rate;
    }
    
    f.close();
	
	int res;

	if((sum>380)&&(sum<410))
	   res=1;
	
    else if((sum>410)&&(sum<430))
	   res=2;
	
    else if((sum>430)&&(sum<450))
	   res=3;
	
    else if((sum>450)&&(sum<470))
	   res=4;
	
    else if((sum>470)&&(sum<500))
	   res=5;
	
	
	int a,b,p = 0,q = 0,i,j = 9000;
    float k =0;
    srand(time(NULL));
	gotoxy(58,6);
	cout<<"___________________\n";
	gotoxy(58,12);
	cout<<"___________________\n";
	gotoxy(58,7);
	cout<<"|";
	gotoxy(58,8);
	cout<<"|";
	gotoxy(58,9);
	cout<<"|";
	gotoxy(58,10);
	cout<<"|";
	gotoxy(58,11);
	cout<<"|";
	gotoxy(58,12);
	cout<<"|";
	gotoxy(76,7);
	cout<<"|";
	gotoxy(76,8);
	cout<<"|";
	gotoxy(76,9);
	cout<<"|";
	gotoxy(76,10);
	cout<<"|";
	gotoxy(76,11);
	cout<<"|";
	gotoxy(76,12);
	cout<<"|";
	gotoxy(60,8);
    cout<<T1.retname();
    gotoxy(70,8);
    cout<<T2.retname();
	
    while(j--)
	{
        k = k + 0.01;
        gotoxy(63,4);
        cout<<"TIME : "<<(int)k;
    }
   
    a = rand()%3+res;//d
    b = rand()%5;
  
    gotoxy(60,10);
    cout<<"  "<<a;
    gotoxy(70,10);
    cout<<"  "<<b; 
        
   gotoxy(10,8);
    if (a>b)
    {       
		win();
        cout<<"\n\n\n\n\n\n\n\n\n\n\n\n\nCONGRATULATIONS!!!!  ";
        cout<<T1.retname()<<" won\nYou have won 5000";
		T1.add();
		T1.points+=3;
		T1.w++;
		T2.l++;
	}
           
    else if(a==b)
    {
       draw();
       cout<<"\n\n\n\n\n\n\n\n\n\n\n\n\nDraw match";
       T1.points+=1;
       T2.points+=1;
       T1.rem+=2000;
       T2.rem+=2000;
       T1.d++;
       T2.d++;
       cout<<"\nYou win 2000";
    }
   
    else
    {
       lose();
       cout<<"\n\n\n\n\n\n\n\n\n\n\n\n\nHARD LUCK ";
       cout<<T1.retname()<<" lost";
       T2.points+=3;
       T2.add();
       T2.w++;
	   T1.l++;
    }
   
    T1.deduct();
   
}
Example #22
0
bool team_has_visible_plan(team &t)
{
	return !t.get_side_actions()->hidden();
}
Example #23
0
/**
 * Clears shroud from a single location.
 * This also records sighted events for later firing.
 *
 * In a few cases, this will also clear corner hexes that otherwise would
 * not normally get cleared.
 * @param tm               The team whose fog/shroud is affected.
 * @param loc              The location to clear.
 * @param view_loc         The location viewer is assumed at (for sighted events).
 * @param event_non_loc    The unit at this location cannot be sighted
 *                         (used to prevent a unit from sighting itself).
 * @param viewer_id        The underlying ID of the unit doing the sighting (for events).
 * @param check_units      If false, there is no checking for an uncovered unit.
 * @param enemy_count      Incremented if an enemy is uncovered.
 * @param friend_count     Incremented if a friend is uncovered.
 * @param spectator        Will be told if a unit is uncovered.
 *
 * @return whether or not information was uncovered (i.e. returns true if
 *         the specified location was fogged/ shrouded under shared vision/maps).
 */
bool shroud_clearer::clear_loc(team &tm, const map_location &loc,
                               const map_location &view_loc,
                               const map_location &event_non_loc,
                               std::size_t viewer_id, bool check_units,
                               std::size_t &enemy_count, std::size_t &friend_count,
                               move_unit_spectator * spectator)
{
	const gamemap &map = resources::gameboard->map();
	// This counts as clearing a tile for the return value if it is on the
	// board and currently fogged under shared vision. (No need to explicitly
	// check for shrouded since shrouded implies fogged.)
	bool was_fogged = tm.fogged(loc);
	bool result = was_fogged && map.on_board(loc);

	// Clear the border as well as the board, so that the half-hexes
	// at the edge can also be cleared of fog/shroud.
	if ( map.on_board_with_border(loc) ) {
		// Both functions should be executed so don't use || which
		// uses short-cut evaluation.
		// (This is different than the return value because shared vision does
		// not apply here.)
		if ( tm.clear_shroud(loc) | tm.clear_fog(loc) ) {
			// If we are near a corner, the corner might also need to be cleared.
			// This happens at the lower-left corner and at either the upper- or
			// lower- right corner (depending on the width).

			// Lower-left corner:
			if ( loc.x == 0  &&  loc.y == map.h()-1 ) {
				const map_location corner(-1, map.h());
				tm.clear_shroud(corner);
				tm.clear_fog(corner);
			}
			// Lower-right corner, odd width:
			else if ( is_odd(map.w())  &&  loc.x == map.w()-1  &&  loc.y == map.h()-1 ) {
				const map_location corner(map.w(), map.h());
				tm.clear_shroud(corner);
				tm.clear_fog(corner);
			}
			// Upper-right corner, even width:
			else if ( is_even(map.w())  &&  loc.x == map.w()-1  &&  loc.y == 0) {
				const map_location corner(map.w(), -1);
				tm.clear_shroud(corner);
				tm.clear_fog(corner);
			}
		}
	}

	// Possible screen invalidation.
	if ( was_fogged ) {
		display::get_singleton()->invalidate(loc);
		// Need to also invalidate adjacent hexes to get rid of the
		// "fog edge" graphics.
		adjacent_loc_array_t adjacent;
		get_adjacent_tiles(loc, adjacent.data());
		for (unsigned i = 0; i < adjacent.size(); ++i )
			display::get_singleton()->invalidate(adjacent[i]);
	}

	// Check for units?
	if ( result  &&  check_units  &&  loc != event_non_loc ) {
		// Uncovered a unit?
		unit_map::const_iterator sight_it = resources::gameboard->find_visible_unit(loc, tm);
		if ( sight_it.valid() ) {
			record_sighting(*sight_it, loc, viewer_id, view_loc);

			// Track this?
			if ( !sight_it->get_state(unit::STATE_PETRIFIED) ) {
				if ( tm.is_enemy(sight_it->side()) ) {
					++enemy_count;
					if ( spectator )
						spectator->add_seen_enemy(sight_it);
				} else {
					++friend_count;
					if ( spectator )
						spectator->add_seen_friend(sight_it);
				}
			}
		}
	}

	return result;
}
Example #24
0
bool side_filter::match_internal(const team &t) const
{
	if (cfg_.has_attribute("side_in")) {
		if (!check_side_number(t,cfg_["side_in"])) {
			return false;
		}
	}
	if (cfg_.has_attribute("side")) {
		if (!check_side_number(t,cfg_["side"])) {
			return false;
		}
	}
	if (!side_string_.empty()) {
		if (!check_side_number(t,side_string_)) {
			return false;
		}
	}

	config::attribute_value cfg_team_name = cfg_["team_name"];
	if (!cfg_team_name.blank()) {
		const std::string& that_team_name = cfg_team_name;
		const std::string& this_team_name = t.team_name();

		if(std::find(this_team_name.begin(), this_team_name.end(), ',') == this_team_name.end()) {
			if(this_team_name != that_team_name) return false;
		}
		else {
			const std::vector<std::string>& these_team_names = utils::split(this_team_name);
			bool search_futile = true;
			BOOST_FOREACH (const std::string& this_single_team_name, these_team_names) {
				if(this_single_team_name == that_team_name) {
					search_futile = false;
					break;
				}
			}
			if(search_futile) return false;
		}
	}

	//Allow filtering on units
	if(cfg_.has_child("has_unit")) {
		const vconfig& unit_filter = cfg_.child("has_unit");
		bool found = false;
		for (unit_map::iterator it = resources::units->begin(); it != resources::units->end(); ++ it) {
			unit* u = dynamic_cast<unit*>(&*it);
			if (u->side() != t.side()) {
				continue;
			}
			if (u->matches_filter(unit_filter, u->get_location(), flat_)) {
				found = true;
				break;
			}
		}

		if (!found) {
			return false;
		}
	}

	const vconfig& enemy_of = cfg_.child("enemy_of");
	if(!enemy_of.null()) {
		side_filter s_filter(enemy_of);
		const std::vector<int>& teams = s_filter.get_teams();
		if(teams.empty()) return false;
		BOOST_FOREACH (const int side, teams) {
			if(!(*resources::teams)[side - 1].is_enemy(t.side()))
				return false;
		}
	}
Example #25
0
void campaign_controller::report_victory(
	std::ostringstream &report, team& t,
	int finishing_bonus_per_turn, int turns_left, int finishing_bonus)
{
	report << "<small>" << _("Remaining gold: ") << utils::half_signed_value(t.gold()) << "</small>";

	if(t.carryover_bonus() != 0) {
		if (turns_left > -1) {
			report << "\n\n<b>" << _("Turns finished early: ") << turns_left << "</b>\n"
				   << "<small>" << _("Early finish bonus: ") << finishing_bonus_per_turn << _(" per turn") << "</small>\n"
				   << "<small>" << _("Total bonus: ") << finishing_bonus << "</small>\n";
		}
		report << "<small>" << _("Total gold: ") << utils::half_signed_value(t.gold() + finishing_bonus) << "</small>";
	}
	if (t.gold() > 0) {
		report << "\n<small>" << _("Carryover percentage: ") << t.carryover_percentage() << "</small>";
	}
	if(t.carryover_add()) {
		report << "\n\n<big><b>" << _("Bonus gold: ") << utils::half_signed_value(t.carryover_gold()) << "</b></big>";
	} else {
		report << "\n\n<big><b>" << _("Retained gold: ") << utils::half_signed_value(t.carryover_gold()) << "</b></big>";
	}

	std::string goldmsg;
	utils::string_map symbols;

	symbols["gold"] = lexical_cast_default<std::string>(t.carryover_gold());

	// Note that both strings are the same in English, but some languages will
	// want to translate them differently.
	if(t.carryover_add()) {
		if(t.carryover_gold() > 0) {
			goldmsg = vngettext(
					"You will start the next scenario with $gold "
					"on top of the defined minimum starting gold.",
					"You will start the next scenario with $gold "
					"on top of the defined minimum starting gold.",
					t.carryover_gold(), symbols);

		} else {
			goldmsg = vngettext(
					"You will start the next scenario with "
					"the defined minimum starting gold.",
					"You will start the next scenario with "
					"the defined minimum starting gold.",
					t.carryover_gold(), symbols);
		}
	} else {
		goldmsg = vngettext(
			"You will start the next scenario with $gold "
			"or its defined minimum starting gold, "
			"whichever is higher.",
			"You will start the next scenario with $gold "
			"or its defined minimum starting gold, "
			"whichever is higher.",
			t.carryover_gold(), symbols);
	}

	// xgettext:no-c-format
	report << "\n" << goldmsg;
}
Example #26
0
report generate_report(TYPE type,
                       const team &viewing_team, int current_side, int playing_side,
                       const map_location& loc, const map_location& mouseover,
                       const std::set<std::string> &observers,
                       const config& level, bool show_everything)
{
	unit_map& units = *resources::units;
	gamemap& map = *resources::game_map;
	std::vector<team>& teams = *resources::teams;

	const unit *u = NULL;

	if ((int(type) >= int(UNIT_REPORTS_BEGIN) && int(type) < int(UNIT_REPORTS_END)) || type == POSITION){
		u = get_visible_unit(loc, viewing_team, show_everything);
		if (!u && type != POSITION) {
			return report();
		}
	}

	std::ostringstream str;
	std::ostringstream tooltip;
	using utils::signed_percent;
	using font::span_color;

	switch(type) {
	case UNIT_NAME:
		// str << font::SMALL_TEXT << u->name();
		str << u->name();

		tooltip << _("Name: ") << u->name();

		return report(str.str(), "", tooltip.str());
	case UNIT_TYPE: {
		if (!u->packed()) {
			str << "<245,230,193>" << u->type_name();
		} else {
			str << "<245,230,193>" << u->packee_type()->type_name();
			str << "[" << u->type_name() << "]";
		}
		if (game_config::tiny_gui) {
			str << "(" << hero::adaptability_str2(ftofxp12(u->adaptability_[u->arms()])) << ")";
		}

		tooltip << _("Type: ")
			<< u->type_name();

		const std::string help_page = "unit_" + u->type_id();

		return report(str.str(), "", tooltip.str(), help_page);
	}
	case UNIT_RACE: {
		str << "<166,146,117>" << u->race()->name(u->gender());

		const std::string help_page = "..race_" + u->race()->id();

		return report(str.str(), "", tooltip.str(), help_page);
	}
	case UNIT_SIDE: {
		std::string flag_icon = teams[u->side() - 1].flag_icon();
		std::string old_rgb = game_config::flag_rgb;
		std::string new_rgb = team::get_side_color_index(u->side());
		std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";

		if(flag_icon.empty()) {
			flag_icon = game_config::images::flag_icon;
		}

		image::locator flag_icon_img(flag_icon, mods);
		return report("", flag_icon_img, teams[u->side() - 1].current_player());
	}
	case UNIT_LEVEL: {
		str << u->level();

		tooltip << _("Level: ")
			<< "<b>" << u->level() << "</b>\n";

		const std::vector<std::string>& adv_to = u->advances_to();
		if(adv_to.empty()) {
			tooltip << _("No advancement");
		} else {
			tooltip << _("Advances to:") << "\n"
					<< "<b>\t" << utils::join(adv_to, "\n\t") << "</b>";
		}

		return report(str.str(), "", tooltip.str());
	}
	case UNIT_AMLA: {
		report res;
		typedef std::pair<std::string, std::string> pair_string;
		foreach(const pair_string& ps, u->amla_icons()) {
			res.add_image(ps.first,ps.second);
		}
		return(res);
	}
	case UNIT_TRAITS: {
		report res;
		const std::vector<t_string>& traits = u->trait_names();
		unsigned int nb = traits.size();
		for(unsigned int i = 0; i < nb; ++i) {
			str << traits[i];
			if(i != nb - 1 )
				str << ", ";
			tooltip << _("Trait: ")
				<< "<b>" << traits[i] << "</b>\n";

			res.add_text(flush(str), flush(tooltip));
		}

		return res;
	}
	case UNIT_STATUS: {
		report res;
		if (map.on_board(loc) && u->invisible(loc)) {
			add_status(res, "misc/invisible.png", N_("invisible: "),
				N_("This unit is invisible. It cannot be seen or attacked by enemy units."));
		}
		if (u->get_state(unit::STATE_SLOWED)) {
			add_status(res, "misc/slowed.png", N_("slowed: "),
				N_("This unit has been slowed. It will only deal half its normal damage when attacking and its movement cost is doubled."));
		}
		if (u->get_state(unit::STATE_BROKEN)) {
			add_status(res, "misc/broken.png", N_("broken: "),
				N_("This unit has been broken. It will suffer 1.5 times its normal damage when defending."));
		}
		if (u->get_state(unit::STATE_POISONED)) {
			add_status(res, "misc/poisoned.png", N_("poisoned: "),
				N_("This unit is poisoned. It will lose 8 HP every turn until it can seek a cure to the poison in a village or from a friendly unit with the 'cures' ability.\n\nUnits cannot be killed by poison alone. The poison will not reduce it below 1 HP."));
		}
		if (u->get_state(unit::STATE_PETRIFIED)) {
			add_status(res, "misc/petrified.png", N_("petrified: "),
				N_("This unit has been petrified. It may not move or attack."));
		}
		return res;
	}

	case UNIT_ALIGNMENT: {
		const std::string &align = unit_type::alignment_description(u->alignment(), u->gender());
		const std::string &align_id = unit_type::alignment_id(u->alignment());
		int cm = combat_modifier(loc, u->alignment(), u->is_fearless());

		str << align << " (" << signed_percent(cm) << ")";
		tooltip << _("Alignment: ")
			<< "<b>" << align << "</b>\n"
			<< string_table[align_id + "_description"];
		return report(str.str(), "", tooltip.str(), "time_of_day");
	}
	case UNIT_ABILITIES: {
		report res;
		const std::vector<std::string> &abilities = u->ability_tooltips();
		for(std::vector<std::string>::const_iterator i = abilities.begin(); i != abilities.end(); ++i) {
			const std::string& name = gettext(i->c_str());
			str << name;
			if(i+2 != abilities.end())
				str << ", ";
			++i;
			//FIXME pull out ability's name from description
			tooltip << _("Ability: ")
				<< *i;
			const std::string help_page = "ability_" + name;

			res.add_text(flush(str), flush(tooltip), help_page);
		}

		return res;
	}
	case UNIT_HP: {
		str << font::color2markup(u->hp_color()) << u->hitpoints()
			<< '/' << u->max_hitpoints();

		return report(str.str(), "", tooltip.str());
	}
	case UNIT_XP: {
		str << font::color2markup(u->xp_color()) << u->experience()
			<< '/' << u->max_experience();

		return report(str.str(), "", tooltip.str());
	}
	case UNIT_ADVANCEMENT_OPTIONS: {
		report res;
		typedef std::pair<std::string, std::string> pair_string;
		foreach(const pair_string& ps, u->advancement_icons()){
			res.add_image(ps.first,ps.second);
		}
		return res;
	}
	case UNIT_WEAPONS: {
		if (u->second().valid()) {
			str << u->second().name();
		}
		if (u->third().valid()) {
			str << " " << u->third().name();
		}
		return report(str.str(), "", tooltip.str());
	}
	case UNIT_IMAGE:
	{
//		const std::vector<Uint32>& old_rgb = u->second.team_rgb_range();
//		color_range new_rgb = team::get_side_color_range(u->second.side());

		report res("", image::locator(u->absolute_image(), u->image_mods()), "");
		if (!u->is_artifical() && u->character() != NO_CHARACTER) {
			res.add_image(unit_types.character(u->character()).image_, "");
			res.back().rect.w = 16;
			res.back().rect.h = 16;
		}
		return res;
	}
	case TIME_OF_DAY: {
		time_of_day tod;

		if (viewing_team.shrouded(mouseover)) {
			// Don't show time on shrouded tiles.
			tod = resources::tod_manager->get_time_of_day();
		} else if (viewing_team.fogged(mouseover)) {
			// Don't show illuminated time on fogged tiles.
			tod = resources::tod_manager->get_time_of_day(mouseover);
		} else {
			tod = resources::tod_manager->time_of_day_at(mouseover);
		}

		int b = tod.lawful_bonus;
		int c = tod.liminal_bonus;
		tooltip << tod.name << '\n'
			<< _("Lawful units: ") << signed_percent(b) << "\n"
			<< _("Neutral units: ") << signed_percent(0) << "\n"
			<< _("Chaotic units: ") << signed_percent(-b);

		if (tod.liminal_present)
		tooltip <<  "\n" << _("Liminal units: ") << signed_percent(c);

		std::string tod_image = tod.image;
		if (tod.lawful_bonus_modified > 0) tod_image += "~BRIGHTEN()";
		else if (tod.lawful_bonus_modified < 0) tod_image += "~DARKEN()";
		if (preferences::flip_time()) tod_image += "~FL(horiz)";

		if (game_config::tiny_gui) {
			return report("", tod_image, "");
		} else {
			return report("", tod_image, tooltip.str(), "time_of_day");
		}
	}
	case TURN: {
		str << 	teams[playing_side-1].name() << "[" << resources::tod_manager->turn() << "]";
		int nb = resources::tod_manager->number_of_turns();
		if (nb != -1) str << '/' << nb;
		break;
	}
	// For the following status reports, show them in gray text
	// when it is not the active player's turn.
	case GOLD: {
		//Supposes the full/"pathfind" unit map is applied
		int fake_gold = viewing_team.gold();
		if (current_side != playing_side) {
			str << font::GRAY_TEXT;
		} else if (fake_gold < 0) {
			str << font::RED_TEXT;
		}

		int cost_exponent = viewing_team.cost_exponent();
		int hundred = cost_exponent / 100;

		str << viewing_team.gold() << "(" << hundred << "." << (cost_exponent - hundred * 100) / 10 << ")";
		break;
	}
	case VILLAGES: {
		const team_data data = calculate_team_data(viewing_team,current_side);
		if (current_side != playing_side)
			str << font::GRAY_TEXT;
		str << data.villages << '/';
		if (viewing_team.uses_shroud()) {
			int unshrouded_villages = 0;
			std::vector<map_location>::const_iterator i = map.villages().begin();
			for (; i != map.villages().end(); ++i) {
				if (!viewing_team.shrouded(*i))
					++unshrouded_villages;
			}
			str << unshrouded_villages;
		} else {
			str << map.villages().size();
		}
		break;
	}
	case UPKEEP: {
		const team_data data = calculate_team_data(viewing_team,current_side);
		if (current_side != playing_side)
			str << font::GRAY_TEXT;
		str << data.expenses << "(" << data.upkeep << ")";
		break;
	}
	case EXPENSES: {
		const team_data data = calculate_team_data(viewing_team,current_side);
		if (current_side != playing_side)
			str << font::GRAY_TEXT;
		str << data.expenses;
		break;
	}
	case INCOME: {
		team_data data = calculate_team_data(viewing_team, current_side);
		if (current_side != playing_side)
			str << font::GRAY_TEXT;
		else if (data.net_income < 0)
			str << font::BAD_TEXT;

		str << data.net_income;
		break;
	}
	case TACTIC: {
		int tactic_point = viewing_team.tactic_point();
		if (current_side != playing_side) {
			str << font::GRAY_TEXT;
		} else if (tactic_point >= game_config::max_tactic_point) {
			str << font::RED_TEXT;
		} else if (tactic_point > game_config::max_tactic_point * 2 / 3) {
			str << "<255,255,0>";
		} else {
			str << font::GOOD_TEXT;
		}

		str << viewing_team.tactic_point();
		break;
	}
	case TERRAIN: {
		if(!map.on_board(mouseover) || viewing_team.shrouded(mouseover))
			break;

		const t_translation::t_terrain terrain = map.get_terrain(mouseover);
		if (terrain == t_translation::OFF_MAP_USER)
			break;

		const t_translation::t_list& underlying = map.underlying_union_terrain(terrain);

		if(map.is_village(mouseover)) {
			int owner = village_owner(mouseover, teams) + 1;
			if(owner == 0 || viewing_team.fogged(mouseover)) {
				str << map.get_terrain_info(terrain).income_description();
			} else if(owner == current_side) {
				str << map.get_terrain_info(terrain).income_description_own();
			} else if(viewing_team.is_enemy(owner)) {
				str << map.get_terrain_info(terrain).income_description_enemy();
			} else {
				str << map.get_terrain_info(terrain).income_description_ally();
			}
			str << " ";
		} else {
		        str << map.get_terrain_info(terrain).description();
		}

		if(underlying.size() != 1 || underlying.front() != terrain) {
			str << " (";

			for(t_translation::t_list::const_iterator i =
					underlying.begin(); i != underlying.end(); ++i) {

			str << map.get_terrain_info(*i).name();
				if(i+1 != underlying.end()) {
					str << ",";
				}
			}
			str << ")";
		}
		break;
	}
	case POSITION: {
		// coordinate  [terrain] resitance
		if (!map.on_board(mouseover)) {
			break;
		}

		const t_translation::t_terrain terrain = map[mouseover];

		if (terrain == t_translation::OFF_MAP_USER)
			break;

		str << mouseover;
		if (game_config::tiny_gui) {
			str << "\n";
		}

		if (!viewing_team.shrouded(mouseover)) {
			const t_translation::t_list& underlying = map.underlying_union_terrain(terrain);

			if (!game_config::tiny_gui) {
				str << _("Terrains") << ":";
			}

			if (map.is_village(mouseover)) {
				int owner = village_owner(mouseover, teams) + 1;
				if(owner == 0 || viewing_team.fogged(mouseover)) {
					str << map.get_terrain_info(terrain).income_description();
				} else if(owner == current_side) {
					str << map.get_terrain_info(terrain).income_description_own();
				} else if(viewing_team.is_enemy(owner)) {
					str << map.get_terrain_info(terrain).income_description_enemy();
				} else {
					str << map.get_terrain_info(terrain).income_description_ally();
				}
				str << " ";
			} else {
				str << map.get_terrain_info(terrain).description();
			}

			if (underlying.size() != 1 || underlying.front() != terrain) {
				str << " (";

				for(t_translation::t_list::const_iterator i =
						underlying.begin(); i != underlying.end(); ++i) {

				str << map.get_terrain_info(*i).name();
					if(i+1 != underlying.end()) {
						str << ",";
					}
				}
				str << ")";
			}

			// display ownership
			std::map<const map_location, int>::const_iterator it = unit_map::economy_areas_.find(mouseover);
			if (it != unit_map::economy_areas_.end()) {
				str << "(" << units.city_from_cityno(it->second)->name() << ")";
			} else if (terrain == t_translation::TERRAIN_ECONOMY_AREA) {
				str << "(--)";
			}

			str << "    ";
			if (game_config::tiny_gui) {
				str << "\n";
			}
		}

		if (!u)
			break;
		if (viewing_team.shrouded(mouseover))
			break;

		int move_cost = u->movement_cost(terrain);
		int defense = 100 - u->defense_modifier(terrain);

		if (!game_config::tiny_gui) {
			str << " ";
		}
		if (move_cost < unit_movement_type::UNREACHABLE) {
			str << "(" << defense << "%," << move_cost << ")";
		} else if (mouseover == loc) {
			str << "(" << defense << "%,-)";
		} else {
			str << "(-,-)";
		}

		break;
	}
	case STRATUM: {
		const hero* rpg_hero = rpg::h;
		std::string stratum_icon;
		if (rpg::stratum == hero_stratum_wander) {
			stratum_icon = "/misc/stratum-wander.png";
		} else if (rpg::stratum == hero_stratum_citizen) {
			stratum_icon = "/misc/stratum-citizen.png";
		} else if (rpg::stratum == hero_stratum_mayor) {
			stratum_icon = "/misc/stratum-mayor.png";
		} else if (rpg::stratum == hero_stratum_leader) {
			stratum_icon = "/misc/stratum-leader.png";
		}
		image::locator stratum_icon_img(stratum_icon);
		return report("", stratum_icon_img, "");
	}
	case MERITORIOUS: {
		str << rpg::h->meritorious_;
		break;
	}
	case SIDE_PLAYING: {
		std::string flag_icon = teams[playing_side-1].flag_icon();
		std::string old_rgb = game_config::flag_rgb;
		std::string new_rgb = team::get_side_color_index(playing_side);
		std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";

		if(flag_icon.empty()) {
			flag_icon = game_config::images::flag_icon;
		}

		image::locator flag_icon_img(flag_icon, mods);
		return report("", flag_icon_img, teams[playing_side-1].name());
	}

	case OBSERVERS: {
		if(observers.empty()) {
			return report();
		}

		str << _("Observers:") << "\n";

		for(std::set<std::string>::const_iterator i = observers.begin(); i != observers.end(); ++i) {
			str << *i << "\n";
		}

		return report("",game_config::images::observer,str.str());
	}
#ifdef DISABLE_EDITOR
	case EDITOR_SELECTED_TERRAIN:
	case EDITOR_LEFT_BUTTON_FUNCTION:
		return report();
#else
	case EDITOR_SELECTED_TERRAIN: {
		if (editor::selected_terrain.empty())
			return report();
		else
			return report(editor::selected_terrain);
	}
	case EDITOR_LEFT_BUTTON_FUNCTION: {
		if (editor::left_button_function.empty())
			return report();
		else
			return report(editor::left_button_function);
	}
#endif
	case REPORT_COUNTDOWN: {
		int min;
		int sec;
		if (viewing_team.countdown_time() > 0){
			sec = viewing_team.countdown_time() / 1000;
			char const *end = naps;
			if (current_side != playing_side)
				str << span_color(font::GRAY_COLOR);
			else if (sec < 60)
				str << "<span foreground=\"#c80000\">";
			else if (sec < 120)
				str << "<span foreground=\"#c8c800\">";
			else
				end = "";

			min = sec / 60;
			str << min << ":";
			sec = sec % 60;
			if (sec < 10) {
				str << "0";
			}
			str << sec << end;
			break;
		} // Intentional fall-through to REPORT_CLOCK
		  // if the time countdown isn't valid.
		  // If there is no turn time limit,
		  // then we display the clock instead.
		}
	case REPORT_CLOCK: {
		time_t t = std::time(NULL);
		struct tm *lt = std::localtime(&t);
		if (lt) {
			char temp[10];
			size_t s = std::strftime(temp, 10, preferences::clock_format().c_str(), lt);
			if(s>0) {
				return report(temp);
			} else {
				return report();
			}
		} else {
			return report();
		}
	}
	default:
		assert(false);
		break;
	}
	return report(str.str());
}
Example #27
0
marked_route mark_route(const plain_route &rt,
	const std::vector<map_location>& waypoints, const unit &u,
	const team &viewing_team, const unit_map &units,
	const std::vector<team> &teams, const gamemap &map)
{
	marked_route res;

	if (rt.steps.empty()) return res;
	res.steps = rt.steps;

	int turns = 0;
	int movement = u.movement_left();
	const team& unit_team = teams[u.side()-1];
	bool zoc = false;

	std::vector<map_location>::const_iterator i = rt.steps.begin(),
			w = waypoints.begin();

	// TODO fix the name confusion with waypoints and route.waypoints
	for (; i !=rt.steps.end(); i++) {
		bool last_step = (i+1 == rt.steps.end());

		// move_cost of the next step is irrelevant for the last step
		assert(last_step || map.on_board(*(i+1)));
		const int move_cost = last_step ? 0 : u.movement_cost(map[*(i+1)]);
		bool capture = false;
		bool pass_here = false;
		if (w != waypoints.end() && *i == *w) {
			w++;
			pass_here = true;
		}

		if (last_step || zoc || move_cost > movement) {
			// check if we stop an a village and so maybe capture it
			// if it's an enemy unit and a fogged village, we assume a capture
			// (if he already owns it, we can't know that)
			// if it's not an enemy, we can always know if he owns the village
			bool capture = map.is_village(*i) && ( !unit_team.owns_village(*i)
				 || (viewing_team.is_enemy(u.side()) && viewing_team.fogged(*i)) );

			++turns;

			bool invisible = u.invisible(*i,units,teams,false);

			res.waypoints[*i] = marked_route::waypoint(turns, pass_here, zoc, capture, invisible);

			if (last_step) break; // finished and we used dummy move_cost

			movement = u.total_movement();
			if(move_cost > movement) {
				return res; //we can't reach destination
			}
		} else if (pass_here) {
			bool invisible = u.invisible(*i,units,teams,false);
			res.waypoints[*i] = marked_route::waypoint(0, pass_here, zoc, false, invisible);
		}

		zoc = enemy_zoc(units, teams, *(i + 1), viewing_team,u.side())
					&& !u.get_ability_bool("skirmisher", *(i+1));

		if (zoc || capture) {
			movement = 0;
		} else {
			movement -= move_cost;
		}
	}

	return res;
}
Example #28
0
report generate_report(TYPE type,
                       std::map<reports::TYPE, std::string> report_contents,
                       const team &current_team, int current_side, int playing_side,
                       const map_location& loc, const map_location& mouseover, const map_location& displayed_unit_hex,
                       const std::set<std::string> &observers,
                       const config& level, bool show_everything)
{
	unit_map &units = *resources::units;
	gamemap &map = *resources::game_map;
	std::vector<team> &teams = *resources::teams;

	const unit *u = NULL;

	if((int(type) >= int(UNIT_REPORTS_BEGIN) && int(type) < int(UNIT_REPORTS_END)) || type == POSITION){
		u = get_visible_unit(units, displayed_unit_hex, current_team, show_everything);
		if (!u && type != POSITION) {
			return report();
		}
	}

	std::ostringstream str;

	switch(type) {
	case UNIT_NAME:
		str << "<b>" << u->name() << "</b>";
		return report(str.str(), "", u->name());
	case UNIT_TYPE:
		str << span_color(font::unit_type_color) << u->type_name() << naps;
		return report(str.str(), "", u->unit_description());
	case UNIT_RACE:
		str << span_color(font::race_color)
			<< u->race()->name(u->gender()) << naps;
		break;
	case UNIT_SIDE: {
		std::string flag_icon = teams[u->side() - 1].flag_icon();
		std::string old_rgb = game_config::flag_rgb;
		std::string new_rgb = team::get_side_colour_index(u->side());
		std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";

		if(flag_icon.empty()) {
			flag_icon = game_config::flag_icon_image;
		}

		image::locator flag_icon_img(flag_icon, mods);
		return report("", flag_icon_img, teams[u->side() - 1].current_player());
	}
	case UNIT_LEVEL:
		str << u->level();
		break;
	case UNIT_AMLA: {
	  report res;
		const std::vector<std::pair<std::string,std::string> > &amla_icons=u->amla_icons();
	  for(std::vector<std::pair<std::string,std::string> >::const_iterator i=amla_icons.begin();i!=amla_icons.end();i++){
	    res.add_image(i->first,i->second);
	  }
	  return(res);
	}
	case UNIT_TRAITS:
		return report(u->traits_description(), "", u->modification_description("trait"));

	case UNIT_STATUS: {
		report res;
		if (map.on_board(displayed_unit_hex) &&
		    u->invisible(displayed_unit_hex, units, teams))
		{
			add_status(res, "misc/invisible.png", N_("invisible: "),
				N_("This unit is invisible. It cannot be seen or attacked by enemy units."));
		}
		if (u->get_state(unit::STATE_SLOWED)) {
			add_status(res, "misc/slowed.png", N_("slowed: "),
				N_("This unit has been slowed. It will only deal half its normal damage when attacking and its movement cost is doubled."));
		}
		if (u->get_state(unit::STATE_POISONED)) {
			add_status(res, "misc/poisoned.png", N_("poisoned: "),
				N_("This unit is poisoned. It will lose 8 HP every turn until it can seek a cure to the poison in a village or from a friendly unit with the 'cures' ability.\n\nUnits cannot be killed by poison alone. The poison will not reduce it below 1 HP."));
		}
		if (u->get_state(unit::STATE_PETRIFIED)) {
			add_status(res, "misc/petrified.png", N_("petrified: "),
				N_("This unit has been petrified. It may not move or attack."));
		}
		return res;
	}

	case UNIT_ALIGNMENT: {
		const std::string &align = unit_type::alignment_description(u->alignment(), u->gender());
		const std::string &align_id = unit_type::alignment_id(u->alignment());
		std::stringstream ss;
		int cm = combat_modifier(units, displayed_unit_hex, u->alignment(), u->is_fearless());
		ss << align << " (" << (cm >= 0 ? "+" : "−") << abs(cm) << "%)";
		return report(ss.str(), "", string_table[align_id + "_description"]);
	}
	case UNIT_ABILITIES: {
		report res;
		const std::vector<std::string> &abilities = u->ability_tooltips();
		for(std::vector<std::string>::const_iterator i = abilities.begin(); i != abilities.end(); ++i) {
			str << gettext(i->c_str());
			if(i+2 != abilities.end())
				str << ",";
			++i;
			res.add_text(flush(str), *i);
		}

		return res;
	}
	case UNIT_HP: {
		std::ostringstream tooltip;
		str << span_color(u->hp_color()) << u->hitpoints()
			<< '/' << u->max_hitpoints() << naps;

		std::set<std::string> resistances_table;

		string_map resistances = u->get_base_resistances();

		bool att_def_diff = false;
		for(string_map::iterator resist = resistances.begin();
				resist != resistances.end(); ++resist) {
			std::ostringstream line;
			line << gettext(resist->first.c_str()) << ": ";

			// Some units have different resistances when
			// attacking or defending.
			int res_att = 100 - u->resistance_against(resist->first, true, displayed_unit_hex);
			int res_def = 100 - u->resistance_against(resist->first, false, displayed_unit_hex);
			if (res_att == res_def) {
				line << res_def << "%\n";
			} else {
				line << res_att << "% / " << res_def << "%\n";
				att_def_diff = true;
			}
			resistances_table.insert(line.str());
		}

		tooltip << _("Resistances: ");
		if (att_def_diff)
			tooltip << _("(Att / Def)");
		tooltip << "\n";

		// the STL set will give alphabetical sorting
		for(std::set<std::string>::iterator line = resistances_table.begin();
				line != resistances_table.end(); ++line) {
			tooltip << (*line);
		}

		return report(str.str(), "", tooltip.str());
	}
	case UNIT_XP: {
		std::ostringstream tooltip;

		str << span_color(u->xp_color()) << u->experience()
			<< '/' << u->max_experience() << naps;

		tooltip << _("Experience Modifier: ") << ((level["experience_modifier"] != "") ? level["experience_modifier"] : "100") << "%";
		return report(str.str(), "", tooltip.str());
	}
	case UNIT_ADVANCEMENT_OPTIONS: {
		report res;
		const std::map<std::string,std::string> &adv_icons = u->advancement_icons();
		for(std::map<std::string,std::string>::const_iterator i=adv_icons.begin();i!=adv_icons.end();i++){
			res.add_image(i->first,i->second);
		}
		return res;
	}
	case UNIT_DEFENSE: {
		const t_translation::t_terrain terrain = map[displayed_unit_hex];
		int def = 100 - u->defense_modifier(terrain);
		SDL_Color color = int_to_color(game_config::red_to_green(def));
		str << span_color(color) << def << "%</span>";
		break;
	}
	case UNIT_MOVES: {
		float movement_frac = 1.0;
		if (u->side() == playing_side) {
			movement_frac = static_cast<float>(u->movement_left()) / std::max(1.0f, static_cast<float>(u->total_movement()));
			if (movement_frac > 1.0)
				movement_frac = 1.0;
		}

		int grey = 128 + static_cast<int>((255-128) * movement_frac);
		SDL_Color c = { grey, grey, grey, 0 };
		str << span_color(c) << u->movement_left()
			<< '/' << u->total_movement() << naps;
		break;
	}
	case UNIT_WEAPONS: {
		report res;
		std::ostringstream tooltip;

		size_t team_index = u->side() - 1;
		if(team_index >= teams.size()) {
			std::cerr << "illegal team index in reporting: " << team_index << "\n";
			return res;
		}

		foreach (const attack_type &at, u->attacks())
		{
			at.set_specials_context(displayed_unit_hex, map_location(), *u);
			std::string lang_type = gettext(at.type().c_str());
			str << span_color(font::weapon_color);
			if (u->get_state(unit::STATE_SLOWED)) {
				str << round_damage(at.damage(), 1, 2) << '-';
			} else {
				str << at.damage() << '-';
			}
			int nattacks = at.num_attacks();
			// Compute swarm attacks:
			unit_ability_list swarm = at.get_specials("swarm");
			if(!swarm.empty()) {
				int swarm_max_attacks = swarm.highest("swarm_attacks_max",nattacks).first;
				int swarm_min_attacks = swarm.highest("swarm_attacks_min").first;
				int hitp = u->hitpoints();
				int mhitp = u->max_hitpoints();

				nattacks = swarm_min_attacks + (swarm_max_attacks - swarm_min_attacks) * hitp / mhitp;

			}
			str << nattacks;
			str << ' ' << at.name() << ' ' << at.accuracy_parry_description();
			tooltip << at.name() << "\n";
			int effdmg;
			if (u->get_state(unit::STATE_SLOWED)) {
				effdmg = round_damage(at.damage(),1,2);
			} else {
				effdmg = at.damage();
			}
			tooltip << effdmg   << ' ' << _n("tooltip^damage", "damage",  effdmg) << ", ";
			tooltip << nattacks << ' ' << _n("tooltip^attack", "attacks", nattacks);

			int accuracy = at.accuracy();
			if(accuracy) {
				// Help xgettext with a directive to recognise the string as a non C printf-like string
				// xgettext:no-c-format
				tooltip << " " << (accuracy > 0 ? "+" : "") << accuracy << _("tooltip^% accuracy");
			}

			int parry = at.parry();
			if(parry) {
				// xgettext:no-c-format
				tooltip << " " << (parry > 0 ? "+" : "") << parry << _("tooltip^% parry");
			}

			str << "</span>\n";
			res.add_text(flush(str), flush(tooltip));

			std::string range = gettext(at.range().c_str());
			str << span_color(font::weapon_details_color) << "  "
				<< range << "--" << lang_type << "</span>\n";

			tooltip << _("weapon range: ") << range <<"\n";
			tooltip << _("damage type: ")  << lang_type << "\n";
			// Find all the unit types on the map, and
			// show this weapon's bonus against all the different units.
			// Don't show invisible units, except if they are in our team or allied.
			std::set<std::string> seen_units;
			std::map<int,std::vector<std::string> > resistances;
			for(unit_map::const_iterator u_it = units.begin(); u_it != units.end(); ++u_it) {
				if(teams[team_index].is_enemy(u_it->second.side()) &&
				   !current_team.fogged(u_it->first) &&
				   seen_units.count(u_it->second.type_id()) == 0 &&
				   ( !current_team.is_enemy(u_it->second.side()) ||
				     !u_it->second.invisible(u_it->first,units,teams)))
				{
					seen_units.insert(u_it->second.type_id());
					int resistance = u_it->second.resistance_against(at, false, u_it->first) - 100;
					resistances[resistance].push_back(u_it->second.type_name());
				}
			}

			for(std::map<int,std::vector<std::string> >::reverse_iterator resist = resistances.rbegin(); resist != resistances.rend(); ++resist) {
				std::sort(resist->second.begin(),resist->second.end());
				tooltip << (resist->first >= 0 ? "+" : "") << resist->first << "% " << _("vs") << " ";
				for(std::vector<std::string>::const_iterator i = resist->second.begin(); i != resist->second.end(); ++i) {
					if(i != resist->second.begin()) {
						tooltip << ", ";
					}

					tooltip << *i;
				}
				tooltip << "\n";
			}

			res.add_text(flush(str), flush(tooltip));


			const std::vector<t_string> &specials = at.special_tooltips();

			if(! specials.empty()) {
				for(std::vector<t_string>::const_iterator sp_it = specials.begin(); sp_it != specials.end(); ++sp_it) {
					str << span_color(font::weapon_details_color)
						<< "  " << *sp_it << "</span>\n";
					++sp_it;
					tooltip << *sp_it << '\n';
				}
				res.add_text(flush(str), flush(tooltip));
			}
		}

		return res;
	}
	case UNIT_IMAGE:
	{
//		const std::vector<Uint32>& old_rgb = u->second.team_rgb_range();
//		color_range new_rgb = team::get_side_color_range(u->second.side());
		return report("", image::locator(u->absolute_image(), u->image_mods()), "");
	}
	case UNIT_PROFILE:
		return report("", u->profile(), "");
	case TIME_OF_DAY: {
		time_of_day tod = resources::tod_manager->time_of_day_at(units, mouseover, *resources::game_map);
		const std::string tod_image = tod.image + (preferences::flip_time() ? "~FL(horiz)" : "");

		// Don't show illuminated time on fogged/shrouded tiles
		if (current_team.fogged(mouseover) || current_team.shrouded(mouseover)) {
			tod = resources::tod_manager->get_time_of_day(false, mouseover);
		}
		std::stringstream tooltip;

		tooltip << tod.name << "\n"
				<< _("Lawful units: ")
				<< (tod.lawful_bonus > 0 ? "+" : "") << tod.lawful_bonus << "%\n"
				<< _("Neutral units: ") << "0%\n"
				<< _("Chaotic units: ")
				<< (tod.lawful_bonus < 0 ? "+" : "") << (tod.lawful_bonus*-1) << "%";

		return report("",tod_image,tooltip.str());
	}
	case TURN: {
		str << resources::tod_manager->turn();
		int nb = resources::tod_manager->number_of_turns();
		if (nb != -1) str << '/' << nb;
		break;
	}
	// For the following status reports, show them in gray text
	// when it is not the active player's turn.
	case GOLD: {
		char const *end = naps;
		if (current_side != playing_side)
			str << span_color(font::GRAY_COLOUR);
		else if (current_team.gold() < 0)
			str << span_color(font::BAD_COLOUR);
		else
			end = "";
		str << current_team.gold() << end;
		break;
	}
	case VILLAGES: {
		const team_data data = calculate_team_data(current_team,current_side,units);
		if (current_side != playing_side)
			str << span_color(font::GRAY_COLOUR);
		str << data.villages << '/';
		if (current_team.uses_shroud()) {
			int unshrouded_villages = 0;
			std::vector<map_location>::const_iterator i = map.villages().begin();
			for (; i != map.villages().end(); i++) {
				if (!current_team.shrouded(*i))
					unshrouded_villages++;
			}
			str << unshrouded_villages;
		} else {
			str << map.villages().size();
		}
		if (current_side != playing_side)
			str << naps;
		break;
	}
	case NUM_UNITS: {
		if (current_side != playing_side)
			str << span_color(font::GRAY_COLOUR);
		str << side_units(units, current_side);
		if (current_side != playing_side)
			str << naps;
		break;
	}
	case UPKEEP: {
		const team_data data = calculate_team_data(current_team,current_side,units);
		if (current_side != playing_side)
			str << span_color(font::GRAY_COLOUR);
		str << data.expenses << " (" << data.upkeep << ")";
		if (current_side != playing_side)
			str << naps;
		break;
	}
	case EXPENSES: {
		const team_data data = calculate_team_data(current_team,current_side,units);
		if (current_side != playing_side)
			str << span_color(font::GRAY_COLOUR);
		str << data.expenses;
		if (current_side != playing_side)
			str << naps;
		break;
	}
	case INCOME: {
		team_data data = calculate_team_data(current_team, current_side, units);
		char const *end = naps;
		if (current_side != playing_side)
			str << span_color(font::GRAY_COLOUR);
		else if (data.net_income < 0)
			str << span_color(font::BAD_COLOUR);
		else
			end = "";
		str << data.net_income << end;
		break;
	}
	case TERRAIN: {
		if(!map.on_board(mouseover) || current_team.shrouded(mouseover))
			break;

		const t_translation::t_terrain terrain = map.get_terrain(mouseover);
		if (terrain == t_translation::OFF_MAP_USER)
			break;

		const t_translation::t_list& underlying = map.underlying_union_terrain(terrain);

		if(map.is_village(mouseover)) {
			int owner = village_owner(mouseover, teams) + 1;
			if(owner == 0 || current_team.fogged(mouseover)) {
				str << map.get_terrain_info(terrain).income_description();
			} else if(owner == current_side) {
				str << map.get_terrain_info(terrain).income_description_own();
			} else if(current_team.is_enemy(owner)) {
				str << map.get_terrain_info(terrain).income_description_enemy();
			} else {
				str << map.get_terrain_info(terrain).income_description_ally();
			}
			str << " ";
		} else {
		        str << map.get_terrain_info(terrain).description();
		}

		if(underlying.size() != 1 || underlying.front() != terrain) {
			str << " (";

			for(t_translation::t_list::const_iterator i =
					underlying.begin(); i != underlying.end(); ++i) {

			str << map.get_terrain_info(*i).name();
				if(i+1 != underlying.end()) {
					str << ",";
				}
			}
			str << ")";
		}
		break;
	}
	case POSITION: {
		if(!map.on_board(mouseover)) {
			break;
		}

		const t_translation::t_terrain terrain = map[mouseover];

		if (terrain == t_translation::OFF_MAP_USER)
			break;

		str << mouseover;

		if (!u)
			break;
		if(displayed_unit_hex != mouseover && displayed_unit_hex != loc)
			break;
		if(current_team.shrouded(mouseover))
			break;

		int move_cost = u->movement_cost(terrain);
		int defense = 100 - u->defense_modifier(terrain);

		if(move_cost < unit_movement_type::UNREACHABLE) {
			str << " (" << defense << "%," << move_cost << ")";
		} else if (mouseover == displayed_unit_hex) {
			str << " (" << defense << "%,-)";
		} else {
			str << " (-)";
		}

		break;
	}

	case SIDE_PLAYING: {
		std::string flag_icon = teams[playing_side-1].flag_icon();
		std::string old_rgb = game_config::flag_rgb;
		std::string new_rgb = team::get_side_colour_index(playing_side);
		std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";

		if(flag_icon.empty()) {
			flag_icon = game_config::flag_icon_image;
		}

		image::locator flag_icon_img(flag_icon, mods);
		return report("",flag_icon_img,teams[playing_side-1].current_player());
	}

	case OBSERVERS: {
		if(observers.empty()) {
			return report();
		}

		str << _("Observers:") << "\n";

		for(std::set<std::string>::const_iterator i = observers.begin(); i != observers.end(); ++i) {
			str << *i << "\n";
		}

		return report("",game_config::observer_image,str.str());
	}
	case SELECTED_TERRAIN: {
		std::map<TYPE, std::string>::const_iterator it =
			report_contents.find(SELECTED_TERRAIN);
		if (it != report_contents.end()) {
			return report(it->second);
		}
		else {
			return report();
		}
	}
	case EDIT_LEFT_BUTTON_FUNCTION: {
		std::map<TYPE, std::string>::const_iterator it =
			report_contents.find(EDIT_LEFT_BUTTON_FUNCTION);
		if (it != report_contents.end()) {
			return report(it->second);
		}
		else {
			return report();
		}
	}
	case REPORT_COUNTDOWN: {
		int min;
		int sec;
		if (current_team.countdown_time() > 0){
			sec = current_team.countdown_time() / 1000;
			char const *end = naps;
			if (current_side != playing_side)
				str << span_color(font::GRAY_COLOUR);
			else if (sec < 60)
				str << "<span foreground=\"#c80000\">";
			else if (sec < 120)
				str << "<span foreground=\"#c8c800\">";
			else
				end = "";

			min = sec / 60;
			str << min << ":";
			sec = sec % 60;
			if (sec < 10) {
				str << "0";
			}
			str << sec << end;
			break;
		} // Intentional fall-through to REPORT_CLOCK
		  // if the time countdown isn't valid.
		  // If there is no turn time limit,
		  // then we display the clock instead.
		}
	case REPORT_CLOCK: {
		time_t t = std::time(NULL);
		struct tm *lt = std::localtime(&t);
		if (lt) {
			char temp[10];
			size_t s = std::strftime(temp, 10, preferences::clock_format().c_str(), lt);
			if(s>0) {
				return report(temp);
			} else {
				return report();
			}
		} else {
			return report();
		}
	}
	default:
		assert(false);
		break;
	}
	return report(str.str());
}