vector2d: try to protect the access against bad index, to be improved...
+ details rewriting
This commit is contained in:
@@ -727,8 +727,8 @@ location find_clear_spot(location from_where,short mode) {
|
||||
if(!loc_off_act_area(loc) && !is_blocked(loc)
|
||||
&& can_see_light(from_where,loc,combat_obscurity) == 0
|
||||
&& (!is_combat() || univ.target_there(loc,TARG_PC) == nullptr)
|
||||
&& (!(is_town()) || (loc != univ.party.town_loc))
|
||||
&& (!(univ.town.fields[loc.x][loc.y] & blocking_fields))) {
|
||||
&& (!is_town() || loc != univ.party.town_loc)
|
||||
&& (!is_town() || !(univ.town.fields[loc.x][loc.y] & blocking_fields))) {
|
||||
if((mode == 0) || ((mode == 1) && (adjacent(from_where,loc))))
|
||||
return loc;
|
||||
else store_loc = loc;
|
||||
|
@@ -196,8 +196,8 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
|
||||
if(mode == eSpecCtx::OUT_MOVE) {
|
||||
out_where = global_to_local(where_check);
|
||||
|
||||
for(short i = 0; i < univ.out->special_locs.size(); i++)
|
||||
if(out_where == univ.out->special_locs[i]) {
|
||||
for(short i = 0; i < univ.out->special_locs.size(); i++) {
|
||||
if(out_where != univ.out->special_locs[i]) continue;
|
||||
spec_num = univ.out->special_locs[i].spec;
|
||||
// call special
|
||||
run_special(mode, eSpecCtxType::OUTDOOR, spec_num, out_where, &s1, &s2);
|
||||
@@ -240,8 +240,8 @@ bool check_special_terrain(location where_check,eSpecCtx mode,cPlayer& which_pc,
|
||||
}
|
||||
if((mode == eSpecCtx::TOWN_MOVE || (mode == eSpecCtx::COMBAT_MOVE && which_combat_type == 1))
|
||||
&& can_enter && univ.town.is_special(where_check.x,where_check.y)) {
|
||||
for(short i = 0; i < univ.town->special_locs.size(); i++)
|
||||
if(where_check == univ.town->special_locs[i]) {
|
||||
for(short i = 0; i < univ.town->special_locs.size(); i++) {
|
||||
if(where_check != univ.town->special_locs[i]) continue;
|
||||
spec_num = univ.town->special_locs[i].spec;
|
||||
bool runSpecial = false;
|
||||
if(!is_blocked(where_check)) runSpecial = true;
|
||||
|
@@ -837,15 +837,18 @@ void create_out_combat_terrain(short ter_type,short num_walls,bool is_road) {
|
||||
univ.town.fields[i][j] = 0;
|
||||
if((j <= 8) || (j >= 35) || (i <= 8) || (i >= 35))
|
||||
univ.town->terrain(i,j) = 90;
|
||||
else univ.town->terrain(i,j) = ter_base[arena];
|
||||
}
|
||||
for(short i = 0; i < 48; i++)
|
||||
for(short j = 0; j < 48; j++)
|
||||
for(short k = 0; k < 5; k++)
|
||||
if((univ.town->terrain(i,j) != 90) && (get_ran(1,1,1000) < terrain_odds[arena][k * 2 + 1]))
|
||||
else
|
||||
univ.town->terrain(i,j) = ter_base[arena];
|
||||
if (univ.town->terrain(i,j) == 90)
|
||||
continue;
|
||||
for(short k = 0; k < 5; k++) {
|
||||
if(get_ran(1,1,1000) < terrain_odds[arena][k * 2 + 1]) {
|
||||
univ.town->terrain(i,j) = terrain_odds[arena][k * 2];
|
||||
|
||||
univ.town->terrain(0,0) = ter_base[arena];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
univ.town->terrain(0,0) = ter_base[arena]; // to force an exit position?
|
||||
|
||||
bool is_bridge = (arena == 3 || arena == 4);
|
||||
|
||||
|
@@ -48,6 +48,16 @@ void cScenario::destroy_terrain() {
|
||||
}
|
||||
}
|
||||
|
||||
cOutdoors *cScenario::get_bad_outdoor()
|
||||
{
|
||||
static std::shared_ptr<cOutdoors> badOutdoor;
|
||||
if (!badOutdoor)
|
||||
badOutdoor=std::make_shared<cOutdoors>(*this);
|
||||
badOutdoor->reattach(*this);
|
||||
badOutdoor->name="Bad Outdoor";
|
||||
return badOutdoor.get();
|
||||
}
|
||||
|
||||
cScenario::cScenario() {
|
||||
std::string temp_str;
|
||||
|
||||
@@ -68,6 +78,7 @@ cScenario::cScenario() {
|
||||
bg_fight = 4;
|
||||
bg_town = 13;
|
||||
bg_dungeon = 9;
|
||||
outdoors.set_get_default_function([this](){return get_bad_outdoor();});
|
||||
// ASAN used but unset
|
||||
is_legacy = false;
|
||||
for(short i = 0; i < town_mods.size(); i++) {
|
||||
@@ -143,6 +154,7 @@ cScenario::cScenario(const cScenario& other)
|
||||
for(size_t i = 0; i < outdoors.width(); i++)
|
||||
for(size_t j = 0; j < outdoors.height(); j++)
|
||||
outdoors[i][j] = new cOutdoors(*other.outdoors[i][j]);
|
||||
outdoors.set_get_default_function([this](){return get_bad_outdoor();});
|
||||
}
|
||||
|
||||
cScenario::cScenario(cScenario&& other) {
|
||||
|
@@ -132,6 +132,9 @@ public:
|
||||
void reset_version();
|
||||
explicit cScenario();
|
||||
~cScenario();
|
||||
|
||||
cOutdoors *get_bad_outdoor();
|
||||
|
||||
// Copy-and-swap
|
||||
void swap(cScenario& other);
|
||||
cScenario(const cScenario& other);
|
||||
|
@@ -85,7 +85,7 @@ void cTown::import_legacy(T const & old, int){
|
||||
// Try to fix specials that could be triggered while in a boat
|
||||
// (Boats never triggered specials in the old BoE, so we probably don't want them to trigger.)
|
||||
int found_spec = -1;
|
||||
for(int k = 0; k < 50; k++) {
|
||||
for(int k = 0; k < special_locs.size(); k++) {
|
||||
if(i == special_locs[k].x && j == special_locs[k].y) {
|
||||
found_spec = k;
|
||||
break;
|
||||
|
@@ -26,7 +26,6 @@ void set_string(std::string string,std::string string2);
|
||||
bool is_special(short i,short j);
|
||||
void take_special(short i,short j);
|
||||
void make_special(short i,short j);
|
||||
void sort_specials();
|
||||
bool is_field_type(short i,short j,eFieldType field_type);
|
||||
void make_field_type(short i,short j,eFieldType field_type);
|
||||
void take_field_type(short i,short j,eFieldType field_type);
|
||||
|
@@ -12,6 +12,7 @@
|
||||
// Tried using boost::multi_array, but it kept causing weird issues, so I decided to make my own.
|
||||
// TODO: Fill out missing members (should have equivalents for most of the stuff in std::vector)
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
template<typename Type, typename Alloc = std::allocator<Type>> class vector2d {
|
||||
@@ -21,6 +22,7 @@ template<typename Type, typename Alloc = std::allocator<Type>> class vector2d {
|
||||
friend class const_col_ref;
|
||||
std::vector<Type, Alloc> data;
|
||||
size_t w, h;
|
||||
std::function<Type()> get_default_value_function=nullptr;
|
||||
public:
|
||||
using value_type = Type;
|
||||
class row_ref {
|
||||
@@ -30,10 +32,14 @@ public:
|
||||
row_ref(vector2d<Type, Alloc>& ref, size_t row) : ref(ref), y(row) {}
|
||||
public:
|
||||
Type& operator[](size_t x) {
|
||||
if (x<ref.w)
|
||||
return ref.data[ref.w * y + x];
|
||||
return ref.get_bad_value();
|
||||
}
|
||||
const Type& operator[](size_t x) const {
|
||||
if (x<ref.w)
|
||||
return ref.data[ref.w * y + x];
|
||||
return ref.get_bad_value();
|
||||
}
|
||||
row_ref operator=(row_ref&& other) {
|
||||
row_ref& me = *this;
|
||||
@@ -60,10 +66,14 @@ public:
|
||||
col_ref(vector2d<Type, Alloc>& ref, size_t col) : ref(ref), x(col) {}
|
||||
public:
|
||||
Type& operator[](size_t y) {
|
||||
if (y<ref.h)
|
||||
return ref.data[ref.w * y + x];
|
||||
return ref.get_bad_value();
|
||||
}
|
||||
const Type& operator[](size_t y) const {
|
||||
if (y<ref.h)
|
||||
return ref.data[ref.w * y + x];
|
||||
return ref.get_bad_value();
|
||||
}
|
||||
col_ref operator=(col_ref&& other) {
|
||||
col_ref& me = *this;
|
||||
@@ -90,7 +100,9 @@ public:
|
||||
const_row_ref(const vector2d<Type, Alloc>& ref, size_t row) : ref(ref), y(row) {}
|
||||
public:
|
||||
const Type& operator[](size_t x) const {
|
||||
if (x<ref.w)
|
||||
return ref.data[ref.w * y + x];
|
||||
return ref.get_bad_value();
|
||||
}
|
||||
};
|
||||
class const_col_ref {
|
||||
@@ -100,32 +112,50 @@ public:
|
||||
const_col_ref(const vector2d<Type, Alloc>& ref, size_t col) : ref(ref), x(col) {}
|
||||
public:
|
||||
const Type& operator[](size_t y) const {
|
||||
if (y<ref.h)
|
||||
return ref.data[ref.w * y + x];
|
||||
return ref.get_bad_value();
|
||||
}
|
||||
};
|
||||
col_ref operator[](size_t x) {
|
||||
if (x<w)
|
||||
return col_ref(*this, x);
|
||||
return get_bad_vector()[0];
|
||||
}
|
||||
const_col_ref operator[](size_t x) const {
|
||||
if (x<w)
|
||||
return const_col_ref(*this, x);
|
||||
return get_bad_const_vector()[0];
|
||||
}
|
||||
col_ref col(size_t x) {
|
||||
if (x<w)
|
||||
return col_ref(*this, x);
|
||||
return get_bad_vector()[0];
|
||||
}
|
||||
const_col_ref col(size_t x) const {
|
||||
if (x<w)
|
||||
return const_col_ref(*this, x);
|
||||
return get_bad_const_vector()[0];
|
||||
}
|
||||
row_ref row(size_t x) {
|
||||
return row_ref(*this, x);
|
||||
row_ref row(size_t y) {
|
||||
if (y<h)
|
||||
return row_ref(*this, y);
|
||||
return get_bad_vector().row(0);
|
||||
}
|
||||
const_row_ref row(size_t x) const {
|
||||
return const_row_ref(*this, x);
|
||||
const_row_ref row(size_t y) const {
|
||||
if (y<h)
|
||||
return const_row_ref(*this, y);
|
||||
return get_bad_const_vector().row(0);
|
||||
}
|
||||
Type& operator()(size_t x, size_t y) {
|
||||
if (x<w && y<h)
|
||||
return (*this)[x][y];
|
||||
return get_bad_value();
|
||||
}
|
||||
const Type& operator()(size_t x, size_t y) const {
|
||||
if (x<w && y<h)
|
||||
return (*this)[x][y];
|
||||
return get_bad_value();
|
||||
}
|
||||
size_t width() const {
|
||||
return w;
|
||||
@@ -173,6 +203,32 @@ public:
|
||||
vector2d(size_t w, size_t h) : w(w), h(h) {
|
||||
resize(w,h);
|
||||
}
|
||||
|
||||
Type &get_bad_value() {
|
||||
static Type badValue;
|
||||
badValue=get_default_value_function ? get_default_value_function() : Type(-1);
|
||||
return badValue;
|
||||
}
|
||||
const Type &get_bad_value() const {
|
||||
static Type badValue;
|
||||
badValue = get_default_value_function ? get_default_value_function() : Type(-1);
|
||||
return badValue;
|
||||
}
|
||||
vector2d &get_bad_vector() {
|
||||
static vector2d bad_vector(1,1);
|
||||
bad_vector.data[0]=get_bad_value();
|
||||
bad_vector.set_get_default_function(get_default_value_function);
|
||||
return bad_vector;
|
||||
}
|
||||
vector2d const &get_bad_const_vector() const {
|
||||
static vector2d bad_vector(1,1);
|
||||
bad_vector.data[0]=get_bad_value();
|
||||
bad_vector.set_get_default_function(get_default_value_function);
|
||||
return bad_vector;
|
||||
}
|
||||
void set_get_default_function(std::function<Type()> const &func) {
|
||||
get_default_value_function=func;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user