rpc: take building influence into consideration in cc_get_production

This commit is contained in:
Crypto City 2021-07-16 22:23:12 +00:00
parent 5a66775599
commit c96b9dd18f
6 changed files with 57 additions and 5 deletions

View File

@ -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];

View File

@ -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);

View File

@ -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];
}
}

View File

@ -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)

View File

@ -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;

View File

@ -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'