The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
display_context.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2014 - 2025
3 by Chris Beck <render787@gmail.com>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#include "display_context.hpp"
17
18#include "map/map.hpp"
19#include "map/location.hpp"
20#include "team.hpp"
21#include "units/unit.hpp"
22#include "units/map.hpp"
23
24const team& display_context::get_team(int side) const
25{
26 return teams().at(side - 1);
27}
28
29bool display_context::has_team(int side) const
30{
31 return side > 0 && side <= static_cast<int>(teams().size());
32}
33
34bool display_context::would_be_discovered(const map_location& loc, int side_num, bool see_all)
35{
38 if(!u_it.valid()) {
39 continue;
40 }
41
42 const unit& u = *u_it;
43 if(get_team(side_num).is_enemy(u.side()) && !u.incapacitated()) {
44 // Enemy spotted in adjacent tiles, check if we can see him.
45 // Watch out to call invisible with see_all=true to avoid infinite recursive calls!
46 if(see_all) {
47 return true;
48 } else if(!get_team(side_num).fogged(u_loc) && !u.invisible(u_loc, true)) {
49 return true;
50 }
51 }
52 }
53 return false;
54}
55
56const unit* display_context::get_visible_unit(const map_location& loc, const team& current_team, bool see_all) const
57{
58 if(!map().on_board(loc)) return nullptr;
60 if(!u.valid() || !u->is_visible_to_team(current_team, see_all)) {
61 return nullptr;
62 }
63 return &*u;
64}
65
67{
68 if(!map().on_board(loc)) return nullptr;
70 if(!u.valid() || !u->is_visible_to_team(current_team, see_all)) {
71 return unit_const_ptr();
72 }
73 return u.get_shared_ptr();
74}
75
77{
78 if(!u.attacks_left() && u.movement_left() == 0) {
79 return {false, false};
80 }
81
82 // Units with goto commands that have already done their gotos this turn
83 // (i.e. don't have full movement left) should have red globes.
84 if(u.has_moved() && u.has_goto()) {
85 return {false, false};
86 }
87
88 const team& current_team = get_team(u.side());
89
90 can_move_result result = {false, false};
91 if(u.attacks_left() > 0 && !u.attacks().empty()) {
92 const auto& attacks = u.attacks();
93
94 std::set<int> attackable_distances;
95 for(const auto& attack : attacks) {
96 for(int i = attack.min_range(); i <= attack.max_range(); ++i) {
97 attackable_distances.insert(i);
98 }
99 }
100
102 int max_distance = *std::prev(attackable_distances.end());
103
104 for(int dx = -max_distance; dx <= max_distance; ++dx) {
105 for(int dy = -max_distance; dy <= max_distance && !result.attack_here; ++dy) {
106 // Adjust for hex grid
107 int adjusted_dy = dy + floor(dx / 2.0);
108
110 int distance = distance_between(u.get_location(), locs);
111
113 continue;
114 }
115
116 if(map().on_board(locs)) {
117 const unit_map::const_iterator i = units().find(locs);
118 if(i.valid() && !i->incapacitated() && current_team.is_enemy(i->side()) && i->is_visible_to_team(get_team(u.side()), false)) {
119 result.attack_here = true;
120 }
121 }
122 }
123 }
124 }
125 }
126
128 if(map().on_board(adj)) {
129 if(!result.move && u.movement_cost(map()[adj]) <= u.movement_left()) {
130 result.move = true;
131 }
132 }
133 }
134 // This should probably check if the unit can teleport too
135
136 return result;
137}
138
140{
141 if(u.user_end_turn())
142 return orb_status::moved;
143 if(u.movement_left() == u.total_movement() && u.attacks_left() == u.max_attacks())
144 return orb_status::unmoved;
145 auto can_move = unit_can_move(u);
146 if(!can_move)
147 return orb_status::moved;
148 if(can_move.move && u.attacks_left() == 0)
150 return orb_status::partial;
151}
152
154{
155 for(const team& t : teams()) {
156 if(t.owns_village(loc)) {
157 return t.side();
158 }
159 }
160 return 0;
161}
162
163/**
164 * Determine if we are an observer, by checking if every team is not locally controlled
165 */
167{
168 for(const team& t : teams()) {
169 if(t.is_local()) {
170 return false;
171 }
172 }
173
174 return true;
175}
176
177// Static info getters previously declared at global scope in unit.?pp
178
180{
181 int res = 0;
182 for(const unit& u : units()) {
183 if(u.side() == side) ++res;
184 }
185 return res;
186}
187
189{
190 int res = 0;
191 for(const unit& u : units()) {
192 if(u.side() == side) res += u.cost();
193 }
194 return res;
195}
196
198{
199 int res = 0;
200 for(const unit& u : units()) {
201 if(u.side() == side) res += u.upkeep();
202 }
203 return res;
204}
205
207 : side(tm.side())
208 , units(dc.side_units(side))
209 , upkeep(dc.side_upkeep(side))
210 , expenses(std::max<int>(0, upkeep - tm.support()))
211 , net_income(tm.total_income() - expenses)
212{
213}
static bool is_enemy(std::size_t side, std::size_t other_side)
map_location loc
Definition move.cpp:172
double t
Abstract class for exposing game data that doesn't depend on the GUI, however which for historical re...
virtual const gamemap & map() const =0
const team & get_team(int side) const
This getter takes a 1-based side number, not a 0-based team number.
virtual const std::vector< team > & teams() const =0
orb_status unit_orb_status(const unit &u) const
Returns an enumurated summary of whether this unit can move and/or attack.
int village_owner(const map_location &loc) const
Given the location of a village, will return the 1-based number of the team that currently owns it,...
const unit * get_visible_unit(const map_location &loc, const team &current_team, bool see_all=false) const
bool is_observer() const
Check if we are an observer in this game.
can_move_result unit_can_move(const unit &u) const
Work out what u can do - this does not check which player's turn is currently active,...
bool has_team(int side) const
virtual const unit_map & units() const =0
int side_units(int side_num) const
Returns the number of units of the side side_num.
unit_const_ptr get_visible_unit_shared_ptr(const map_location &loc, const team &current_team, bool see_all=false) const
int side_units_cost(int side_num) const
Returns the total cost of units of side side_num.
bool would_be_discovered(const map_location &loc, int side_num, bool see_all=true)
Given a location and a side number, indicates whether an invisible unit of that side at that location...
int side_upkeep(int side_num) const
bool empty() const
Tell if the map is of 0 size.
Definition map.hpp:68
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition map.cpp:347
This class stores all the data for a single 'side' (in game nomenclature).
Definition team.hpp:74
bool is_enemy(int n) const
Definition team.hpp:270
unit_iterator find(std::size_t id)
Definition map.cpp:302
This class represents a single unit of a specific type.
Definition unit.hpp:39
bool invisible(const map_location &loc, bool see_all=true) const
Definition unit.cpp:2640
bool user_end_turn() const
Check whether the user ended their turn.
Definition unit.hpp:707
bool incapacitated() const
Check if the unit has been petrified.
Definition unit.hpp:826
int cost() const
How much gold is required to recruit this unit.
Definition unit.hpp:555
int side() const
The side this unit belongs to.
Definition unit.hpp:249
attack_itors attacks()
Gets an iterator over this unit's attacks.
Definition unit.hpp:848
int max_attacks() const
The maximum number of attacks this unit may perform per turn, usually 1.
Definition unit.hpp:884
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
Definition unit.hpp:900
const map_location & get_location() const
The current map location this unit is at.
Definition unit.hpp:1327
bool has_goto() const
Gets whether this unit has a multi-turn destination set.
Definition unit.hpp:1352
bool has_moved() const
Checks if this unit has moved.
Definition unit.hpp:1282
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
Definition unit.hpp:1410
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition unit.hpp:1252
int total_movement() const
The maximum moves this unit has.
Definition unit.hpp:1236
int upkeep() const
Gets the amount of gold this unit costs a side per turn.
Definition unit.cpp:1751
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition location.cpp:584
void get_adjacent_tiles(const map_location &a, utils::span< map_location, 6 > res)
Function which, given a location, will place all adjacent locations in res.
Definition location.cpp:513
STL namespace.
orb_status
Corresponds to the colored orbs displayed above units' hp-bar and xp-bar.
@ partial
There are still moves and/or attacks possible, but the unit doesn't fit in the "unmoved" status.
@ moved
All moves and possible attacks have been done.
@ unmoved
The unit still has full movement and all attacks available.
@ disengaged
The unit can move but can't attack, and wouldn't be able to attack even if it was moved to a hex adja...
std::shared_ptr< const unit > unit_const_ptr
Definition ptr.hpp:27
bool attack_here
The unit can make an attack from the hex that it's currently on, this requires attack points and a no...
bool move
The unit can move to another hex, taking account of enemies' locations, ZoC and terrain costs vs curr...
Encapsulates the map of the game.
Definition location.hpp:46
team_data(const display_context &dc, const team &tm)
bool valid() const
Definition map.hpp:273
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
Definition map.hpp:217
#define i