The Battle for Wesnoth  1.19.0-dev
display_context.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
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 
24 const team& display_context::get_team(int side) const
25 {
26  return teams().at(side - 1);
27 }
28 
29 bool display_context::would_be_discovered(const map_location & loc, int side_num, bool see_all)
30 {
31  for(const map_location& u_loc : get_adjacent_tiles(loc)) {
32  unit_map::const_iterator u_it = units().find(u_loc);
33  if (!u_it.valid()) {
34  continue;
35  }
36  const unit & u = *u_it;
37  if (get_team(side_num).is_enemy(u.side()) && !u.incapacitated()) {
38  // Enemy spotted in adjacent tiles, check if we can see him.
39  // Watch out to call invisible with see_all=true to avoid infinite recursive calls!
40  if(see_all) {
41  return true;
42  } else if (!get_team(side_num).fogged(u_loc)
43  && !u.invisible(u_loc, true)) {
44  return true;
45  }
46  }
47  }
48  return false;
49 }
50 
51 const unit * display_context::get_visible_unit(const map_location & loc, const team &current_team, bool see_all) const
52 {
53  if (!map().on_board(loc)) return nullptr;
54  const unit_map::const_iterator u = units().find(loc);
55  if (!u.valid() || !u->is_visible_to_team(current_team, see_all)) {
56  return nullptr;
57  }
58  return &*u;
59 }
60 
61 unit_const_ptr display_context::get_visible_unit_shared_ptr(const map_location & loc, const team &current_team, bool see_all) const
62 {
63  if (!map().on_board(loc)) return nullptr;
64  const unit_map::const_iterator u = units().find(loc);
65  if (!u.valid() || !u->is_visible_to_team(current_team, see_all)) {
66  return unit_const_ptr();
67  }
68  return u.get_shared_ptr();
69 }
70 
72 {
73  if(!u.attacks_left() && u.movement_left() == 0)
74  return {false, false};
75 
76  // Units with goto commands that have already done their gotos this turn
77  // (i.e. don't have full movement left) should have red globes.
78  if(u.has_moved() && u.has_goto()) {
79  return {false, false};
80  }
81 
82  const team& current_team = get_team(u.side());
83 
84  can_move_result result = {false, false};
85  for(const map_location& adj : get_adjacent_tiles(u.get_location())) {
86  if (map().on_board(adj)) {
87  if(!result.attack_here) {
88  const unit_map::const_iterator i = units().find(adj);
89  if (i.valid() && !i->incapacitated() && current_team.is_enemy(i->side())) {
90  result.attack_here = true;
91  }
92  }
93 
94  if (!result.move && u.movement_cost(map()[adj]) <= u.movement_left()) {
95  result.move = true;
96  }
97  }
98  }
99 
100  // This should probably check if the unit can teleport too
101 
102  return result;
103 }
104 
106 {
107  if(u.user_end_turn())
108  return orb_status::moved;
109  if(u.movement_left() == u.total_movement() && u.attacks_left() == u.max_attacks())
110  return orb_status::unmoved;
111  auto can_move = unit_can_move(u);
112  if(!can_move)
113  return orb_status::moved;
114  if(can_move.move && u.attacks_left() == 0)
115  return orb_status::disengaged;
116  return orb_status::partial;
117 }
118 
120 {
121  const std::vector<team> & t = teams();
122  for(std::size_t i = 0; i != t.size(); ++i) {
123  if(t[i].owns_village(loc))
124  return i + 1;
125  }
126  return 0;
127 }
128 
129 /**
130  * Determine if we are an observer, by checking if every team is not locally controlled
131  */
133 {
134  for (const team &t : teams()) {
135  if (t.is_local())
136  return false;
137  }
138 
139  return true;
140 }
141 
142 // Static info getters previously declared at global scope in unit.?pp
143 
144 int display_context::side_units(int side) const
145 {
146  int res = 0;
147  for (const unit &u : units()) {
148  if (u.side() == side) ++res;
149  }
150  return res;
151 }
152 
154 {
155  int res = 0;
156  for (const unit &u : units()) {
157  if (u.side() == side) res += u.cost();
158  }
159  return res;
160 }
161 
162 int display_context::side_upkeep(int side) const
163 {
164  int res = 0;
165  for (const unit &u : units()) {
166  if (u.side() == side) res += u.upkeep();
167  }
168  return res;
169 }
170 
172  : side(tm.side())
173  , units(dc.side_units(side))
174  , upkeep(dc.side_upkeep(side))
175  , expenses(std::max<int>(0, upkeep - tm.support()))
176  , net_income(tm.total_income() - expenses)
177 {
178 }
double t
Definition: astarsearch.cpp:63
Abstract class for exposing game data that doesn't depend on the GUI, however which for historical re...
const team & get_team(int side) const
This getter takes a 1-based side number, not a 0-based team number.
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,...
virtual const gamemap & map() const =0
int side_units(int side_num) const
Returns the number of units of the side side_num.
virtual const std::vector< team > & teams() const =0
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.
virtual const unit_map & units() const =0
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
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:229
unit_iterator find(std::size_t id)
Definition: map.cpp:302
This class represents a single unit of a specific type.
Definition: unit.hpp:133
std::size_t i
Definition: function.cpp:968
bool invisible(const map_location &loc, bool see_all=true) const
Definition: unit.cpp:2572
bool user_end_turn() const
Check whether the user ended their turn.
Definition: unit.hpp:792
bool incapacitated() const
Check if the unit has been petrified.
Definition: unit.hpp:905
int side() const
The side this unit belongs to.
Definition: unit.hpp:343
int max_attacks() const
The maximum number of attacks this unit may perform per turn, usually 1.
Definition: unit.hpp:978
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
Definition: unit.hpp:994
bool has_goto() const
Gets whether this unit has a multi-turn destination set.
Definition: unit.hpp:1382
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1357
bool has_moved() const
Checks if this unit has moved.
Definition: unit.hpp:1312
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
Definition: unit.hpp:1440
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition: unit.hpp:1282
int total_movement() const
The maximum moves this unit has.
Definition: unit.hpp:1266
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.cpp:474
orb_status
Corresponds to the colored orbs displayed above units' hp-bar and xp-bar.
Definition: orb_status.hpp:23
@ 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:38
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