Author: pepeto Date: Thu Jun 26 22:44:19 2014 New Revision: 25280 URL: http://svn.gna.org/viewcvs/freeciv?rev=25280&view=rev Log: Use parameter-based hash table instead of unittype-based array for pf_reserve_map.
See gna patch #4820 Modified: trunk/common/aicore/path_finding.c Modified: trunk/common/aicore/path_finding.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/aicore/path_finding.c?rev=25280&r1=25279&r2=25280&view=diff ============================================================================== --- trunk/common/aicore/path_finding.c (original) +++ trunk/common/aicore/path_finding.c Thu Jun 26 22:44:19 2014 @@ -3094,11 +3094,73 @@ * units needs to reach the start tile. It stores a pf_map for every unit * type. */ +static genhash_val_t pf_map_hash_val(const struct pf_parameter *parameter); +static bool pf_map_hash_cmp(const struct pf_parameter *parameter1, + const struct pf_parameter *parameter2); + +#define SPECHASH_TAG pf_map +#define SPECHASH_IKEY_TYPE struct pf_parameter * +#define SPECHASH_IDATA_TYPE struct pf_map * +#define SPECHASH_IKEY_VAL pf_map_hash_val +#define SPECHASH_IKEY_COMP pf_map_hash_cmp +#define SPECHASH_IDATA_FREE pf_map_destroy +#include "spechash.h" + /* The reverse map structure. */ struct pf_reverse_map { struct pf_parameter param; /* Keep a parameter ready for usage. */ - struct pf_map **maps; /* A vector of pf_map for every unit_type. */ + struct pf_map_hash *hash; /* A hash where pf_map are stored. */ }; + +/* Here goes all unit type flags which affect the move rules handled by + * the reverse map. */ +static const enum unit_type_flag_id signifiant_flags[] = { + UTYF_IGTER +}; +static const size_t signifiant_flags_num = ARRAY_SIZE(signifiant_flags); + +/**************************************************************************** + Hash function for pf_parameter key. +****************************************************************************/ +static genhash_val_t pf_map_hash_val(const struct pf_parameter *parameter) +{ + genhash_val_t result = 0; + size_t b, i; + + for (i = 0, b = sizeof(result) * 8 - 1; i < signifiant_flags_num; + i++, b--) { + if (BV_ISSET(parameter->unit_flags, signifiant_flags[i])) { + result |= (1 << b); + } + } + + return (result + + uclass_number(parameter->uclass) + + (parameter->move_rate << 6)); +} + +/**************************************************************************** + Comparison function for pf_parameter hash key. +****************************************************************************/ +static bool pf_map_hash_cmp(const struct pf_parameter *parameter1, + const struct pf_parameter *parameter2) +{ + size_t i; + + if (parameter1->uclass != parameter2->uclass + || parameter1->move_rate != parameter2->move_rate) { + return FALSE; + } + + for (i = 0; i < signifiant_flags_num; i++) { + if (BV_ISSET(parameter1->unit_flags, signifiant_flags[i]) + != BV_ISSET(parameter2->unit_flags, signifiant_flags[i])) { + return FALSE; + } + } + + return TRUE; +} /**************************************************************************** This function estime the cost for unit moves to reach the start tile. @@ -3155,10 +3217,13 @@ param->start_tile = start_tile; param->owner = pplayer; param->omniscience = omniscient; + /* We don't deal with re-fuel points. */ + param->fuel = 1; + param->fuel_left_initially = 1; param->data = FC_INT_TO_PTR(max_turns); - /* Initialize the map vector. */ - pfrm->maps = fc_calloc(utype_count(), sizeof(*pfrm->maps)); + /* Initialize the map hash. */ + pfrm->hash = pf_map_hash_new(); return pfrm; } @@ -3179,17 +3244,9 @@ ****************************************************************************/ void pf_reverse_map_destroy(struct pf_reverse_map *pfrm) { - struct pf_map **ppfm; - size_t i; - fc_assert_ret(NULL != pfrm); - for (i = 0, ppfm = pfrm->maps; i < utype_count(); i++, ppfm++) { - if (NULL != *ppfm) { - pf_map_destroy(*ppfm); - } - } - free(pfrm->maps); + pf_map_hash_destroy(pfrm->hash); free(pfrm); } @@ -3200,32 +3257,28 @@ pf_reverse_map_utype_map(struct pf_reverse_map *pfrm, const struct unit_type *punittype) { - Unit_type_id index = utype_index(punittype); - struct pf_map *pfm = pfrm->maps[index]; - - if (NULL == pfm) { - struct pf_parameter *param = &pfrm->param; - int max_turns = FC_PTR_TO_INT(param->data); - - /* Not created yet. */ - param->uclass = utype_class(punittype); - param->unit_flags = punittype->flags; - param->move_rate = punittype->move_rate; - param->moves_left_initially = punittype->move_rate; - if (utype_fuel(punittype)) { - param->fuel = utype_fuel(punittype); - param->fuel_left_initially = utype_fuel(punittype); - } else { - param->fuel = 1; - param->fuel_left_initially = 1; - } - pfm = pf_map_new(param); - pfm->params.data = - FC_INT_TO_PTR(0 <= max_turns && FC_INFINITY > max_turns - ? max_turns * param->move_rate : FC_INFINITY); - pfrm->maps[index] = pfm; - } - + struct pf_map *pfm; + struct pf_parameter *param; + int max_turns; + + param = &pfrm->param; + param->uclass = utype_class(punittype); + param->unit_flags = punittype->flags; + param->move_rate = punittype->move_rate; + param->moves_left_initially = punittype->move_rate; + + if (pf_map_hash_lookup(pfrm->hash, param, &pfm)) { + fc_assert(NULL != pfm); + return pfm; + } + + /* Build map. */ + max_turns = FC_PTR_TO_INT(param->data); + pfm = pf_map_new(param); + pfm->params.data = + FC_INT_TO_PTR(0 <= max_turns && FC_INFINITY > max_turns + ? max_turns * param->move_rate : FC_INFINITY); + pf_map_hash_insert(pfrm->hash, &pfm->params, pfm); return pfm; } _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits