forked from townforge/townforge
rpc: take building influence into consideration in cc_get_production
This commit is contained in:
parent
5a66775599
commit
c96b9dd18f
@ -2886,6 +2886,47 @@ uint32_t get_num_players(const cryptonote::BlockchainDB &db)
|
||||
return db.get_num_cc_accounts() - 1 /* game */ - 1 /* foreclosure */ - db.get_num_cc_cities() /* treasuries */;
|
||||
}
|
||||
|
||||
uint32_t get_influence_bonus(const cryptonote::BlockchainDB &db, uint32_t city, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t role, uint32_t economic_power)
|
||||
{
|
||||
uint32_t cumulative_influence[NUM_ROLES];
|
||||
memset(cumulative_influence, 0, sizeof(cumulative_influence));
|
||||
|
||||
std::vector<cc::special_event_data_t> sed;
|
||||
db.get_cc_special_events(city, sed);
|
||||
const uint32_t special_event = sed.empty() || sed.back().duration > 0 ? cc::SPECIAL_EVENT_NONE : sed.back().special_event;
|
||||
|
||||
db.for_all_cc_flags([city, x0, y0, x1, y1, role, economic_power, special_event, &cumulative_influence](const cryptonote::cc_flag_data_t &fd){
|
||||
if (fd.city != city)
|
||||
return true;
|
||||
if (fd.active)
|
||||
return true;
|
||||
if (fd.x0 == x0 && fd.x1 == x1 && fd.y0 == y0 && fd.y1 == y1)
|
||||
return true;
|
||||
|
||||
const uint32_t influence_radius = cc::get_cc_influence(fd.x0, fd.y0, fd.x1, fd.y1, fd.role, fd.economic_power, fd.elevation_bonus, fd.potential, special_event);
|
||||
const uint32_t ix0 = std::max(fd.x0, influence_radius) - influence_radius;
|
||||
const uint32_t iy0 = std::max(fd.y0, influence_radius) - influence_radius;
|
||||
const uint32_t ix1 = std::min(fd.x1, std::numeric_limits<uint32_t>::max() - influence_radius) + influence_radius;
|
||||
const uint32_t iy1 = std::min(fd.y1, std::numeric_limits<uint32_t>::max() - influence_radius) + influence_radius;
|
||||
const uint32_t squares = intersection_squares(x0, y0, x1, y1, ix0, iy0, ix1, iy1);
|
||||
cumulative_influence[fd.role] += squares;
|
||||
return true;
|
||||
});
|
||||
|
||||
// normalize cumulative influence from squares to multiples
|
||||
const uint32_t flag_area = (x1 - x0 + 1) * (y1 - y0 + 1);
|
||||
for (int role = 1; role < NUM_ROLES; ++role)
|
||||
{
|
||||
if (cumulative_influence[role] > 0)
|
||||
cumulative_influence[role] = (cumulative_influence[role] + flag_area / 2) / flag_area;
|
||||
}
|
||||
|
||||
cryptonote::cc_command_game_update_t cg;
|
||||
cc::game_events_t events;
|
||||
const uint32_t influence_bonus = cc::calculate_influence_bonus(role, cumulative_influence, 0, 0, cg, events);
|
||||
return influence_bonus;
|
||||
}
|
||||
|
||||
void cc_derive_keys(const crypto::secret_key &base, crypto::secret_key &skey, crypto::public_key &pkey)
|
||||
{
|
||||
char data[33];
|
||||
|
@ -158,6 +158,7 @@ uint64_t get_gold_balance_including_reserves(uint64_t balance, const std::map<ui
|
||||
uint32_t get_item_balance_including_reserves(uint32_t item, const std::map<uint32_t, uint32_t> &item_balances, const std::map<uint32_t, std::pair<uint64_t, std::map<uint32_t, uint32_t>>> &reserve);
|
||||
uint32_t get_num_players(const cryptonote::BlockchainDB &db);
|
||||
bool has_specialization(const std::map<uint32_t, uint64_t> &specializations, uint32_t specialization, uint64_t *height = NULL);
|
||||
uint32_t get_influence_bonus(const cryptonote::BlockchainDB &db, uint32_t city, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t role, uint32_t economic_power);
|
||||
|
||||
bool encode_blocks(const uint8_t *src_types, uint32_t n_src_types, uint8_t *encoded_types, uint32_t *encoded_types_len);
|
||||
bool decode_blocks(const uint8_t *encoded_types, uint32_t encoded_types_len, uint8_t *dst_types, uint32_t *n_dst_types);
|
||||
|
@ -263,13 +263,15 @@ uint32_t calculate_influence_bonus(uint8_t role, const uint32_t cumulative_influ
|
||||
const uint32_t need = GET_NEED(rules.effect[r]);
|
||||
if (cumulative_influence[r] < need)
|
||||
{
|
||||
events.add(cg, owner, flag) << "Building type " << cc::get_role_name(role) << " deactivated due to unmet need for influence from " << need << " buildings of type " << cc::get_role_name(r);
|
||||
if (owner)
|
||||
events.add(cg, owner, flag) << "Building type " << cc::get_role_name(role) << " deactivated due to unmet need for influence from " << need << " buildings of type " << cc::get_role_name(r);
|
||||
return 0;
|
||||
}
|
||||
const int32_t penalty = (cumulative_influence[r] >= GET_PENALTY(rules.effect[r])) ? GET_PENALTY(rules.effect[r]) : 0;
|
||||
if (penalty > 0)
|
||||
{
|
||||
events.add(cg, owner, flag) << "Building type " << cc::get_role_name(role) << " got -" << penalty * influence_penalty[r] << "% penalty due to " << penalty << " buildings of type " << cc::get_role_name(r);
|
||||
if (owner)
|
||||
events.add(cg, owner, flag) << "Building type " << cc::get_role_name(role) << " got -" << penalty * influence_penalty[r] << "% penalty due to " << penalty << " buildings of type " << cc::get_role_name(r);
|
||||
score = score > penalty * influence_penalty[r] ? score - penalty * influence_penalty[r] : 0;
|
||||
}
|
||||
else
|
||||
@ -277,7 +279,8 @@ uint32_t calculate_influence_bonus(uint8_t role, const uint32_t cumulative_influ
|
||||
const uint32_t bonus = std::min(GET_BONUS(rules.effect[r]), cumulative_influence[r]);
|
||||
if (bonus > 0)
|
||||
{
|
||||
events.add(cg, owner, flag) << "Building type " << cc::get_role_name(role) << " got +" << bonus * influence_bonus[r] << "% bonus due to " << bonus << " buildings of type " << cc::get_role_name(r);
|
||||
if (owner)
|
||||
events.add(cg, owner, flag) << "Building type " << cc::get_role_name(role) << " got +" << bonus * influence_bonus[r] << "% bonus due to " << bonus << " buildings of type " << cc::get_role_name(r);
|
||||
score += bonus * influence_bonus[r];
|
||||
}
|
||||
}
|
||||
|
@ -5991,12 +5991,16 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t influence_bonus = 100;
|
||||
if (req.calculate_influence_bonus)
|
||||
influence_bonus = cc::get_influence_bonus(db, req.city, req.x0, req.y0, req.x1, req.y1, req.role, req.economic_power);
|
||||
|
||||
res.item_consumption.reserve(cost.size());
|
||||
for (const auto &e: cost)
|
||||
res.item_consumption.push_back({e.first, e.second});
|
||||
res.item_production.reserve(production.size());
|
||||
for (const auto &e: production)
|
||||
res.item_production.push_back({e.first, e.second});
|
||||
res.item_production.push_back({e.first, e.second * influence_bonus / 100});
|
||||
}
|
||||
|
||||
catch (const std::exception &e)
|
||||
|
@ -5261,6 +5261,7 @@ namespace cryptonote
|
||||
bool dense_rockbed;
|
||||
uint32_t logging_level;
|
||||
uint32_t quarrying_level;
|
||||
bool calculate_influence_bonus;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_OPT(city, 0u)
|
||||
@ -5275,6 +5276,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE_OPT(dense_rockbed, false)
|
||||
KV_SERIALIZE_OPT(logging_level, 0u)
|
||||
KV_SERIALIZE_OPT(quarrying_level, 0u)
|
||||
KV_SERIALIZE_OPT(calculate_influence_bonus, true)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<request_t> request;
|
||||
|
@ -1252,7 +1252,7 @@ class Daemon(object):
|
||||
}
|
||||
return self.rpc.send_json_rpc_request(cc_get_crop_yield)
|
||||
|
||||
def cc_get_production(self, city, x0, y0, x1, y1, role, economic_power, age = 0, dense_forest = False, dense_rockbed = False, logging_level = 0, quarrying_level = 0):
|
||||
def cc_get_production(self, city, x0, y0, x1, y1, role, economic_power, age = 0, dense_forest = False, dense_rockbed = False, logging_level = 0, quarrying_level = 0, calculate_influence_bonus = True):
|
||||
cc_get_production = {
|
||||
'method': 'cc_get_production',
|
||||
'params': {
|
||||
@ -1268,6 +1268,7 @@ class Daemon(object):
|
||||
'dense_rockbed': dense_rockbed,
|
||||
'logging_level': logging_level,
|
||||
'quarrying_level': quarrying_level,
|
||||
'calculate_influence_bonus': calculate_influence_bonus,
|
||||
},
|
||||
'jsonrpc': '2.0',
|
||||
'id': '0'
|
||||
|
Loading…
Reference in New Issue
Block a user