Author: pepeto Date: Sun Jul 6 10:48:40 2014 New Revision: 25396 URL: http://svn.gna.org/viewcvs/freeciv?rev=25396&view=rev Log: Add utility for iterating all requirements for reaching an advance, instead of building recursive functions.
See gna patch #4890 Modified: trunk/common/tech.c trunk/common/tech.h Modified: trunk/common/tech.c URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/tech.c?rev=25396&r1=25395&r2=25396&view=diff ============================================================================== --- trunk/common/tech.c (original) +++ trunk/common/tech.c Sun Jul 6 10:48:40 2014 @@ -21,7 +21,7 @@ /* utility */ #include "fcintl.h" -#include "game.h" +#include "iterator.h" #include "log.h" #include "mem.h" /* free */ #include "shared.h" /* ARRAY_SIZE */ @@ -29,14 +29,23 @@ #include "support.h" /* common */ +#include "game.h" #include "research.h" - #include "tech.h" + /* Define this for additional debug information about the tech status * (in player_research_update()). */ #undef DEBUG_TECH + +struct advance_req_iter { + struct iterator base; + bv_techs done; + const struct advance *array[A_LAST]; + const struct advance **current, **end; +}; +#define ADVANCE_REQ_ITER(it) ((struct advance_req_iter *) it) /* the advances array is now setup in: * server/ruleset.c (for the server) @@ -935,3 +944,80 @@ tech_free(i); } advance_index_iterate_end; } + + +/**************************************************************************** + Return the size of the advance requirements iterator. +****************************************************************************/ +size_t advance_req_iter_sizeof(void) +{ + return sizeof(struct advance_req_iter); +} + +/**************************************************************************** + Return the current advance. +****************************************************************************/ +static void *advance_req_iter_get(const struct iterator *it) +{ + return (void *) *ADVANCE_REQ_ITER(it)->current; +} + +/**************************************************************************** + Jump to next advance requirement. +****************************************************************************/ +static void advance_req_iter_next(struct iterator *it) +{ + struct advance_req_iter *iter = ADVANCE_REQ_ITER(it); + const struct advance *padvance = *iter->current, *preq; + enum tech_req req; + bool new = FALSE; + + for (req = AR_ONE; req < AR_SIZE; req++) { + preq = valid_advance(advance_requires(padvance, req)); + if (NULL != preq + && A_NONE != advance_number(preq) + && !BV_ISSET(iter->done, advance_number(preq))) { + BV_SET(iter->done, advance_number(preq)); + if (new) { + *iter->end++ = preq; + } else { + *iter->current = preq; + new = TRUE; + } + } + } + + if (!new) { + iter->current++; + } +} + +/**************************************************************************** + Return whether we finished to iterate or not. +****************************************************************************/ +static bool advance_req_iter_valid(const struct iterator *it) +{ + const struct advance_req_iter *iter = ADVANCE_REQ_ITER(it); + + return iter->current < iter->end; +} + +/**************************************************************************** + Initialize an advance requirements iterator. +****************************************************************************/ +struct iterator *advance_req_iter_init(struct advance_req_iter *it, + const struct advance *goal) +{ + struct iterator *base = ITERATOR(it); + + base->get = advance_req_iter_get; + base->next = advance_req_iter_next; + base->valid = advance_req_iter_valid; + + BV_CLR_ALL(it->done); + it->current = it->array; + *it->current = goal; + it->end = it->current + 1; + + return base; +} Modified: trunk/common/tech.h URL: http://svn.gna.org/viewcvs/freeciv/trunk/common/tech.h?rev=25396&r1=25395&r2=25396&view=diff ============================================================================== --- trunk/common/tech.h (original) +++ trunk/common/tech.h Sun Jul 6 10:48:40 2014 @@ -220,6 +220,19 @@ } \ } +/* Advance requirements iterator. */ +struct advance_req_iter; + +size_t advance_req_iter_sizeof(void); +struct iterator *advance_req_iter_init(struct advance_req_iter *it, + const struct advance *goal); + +#define advance_req_iterate(_goal, _padvance) \ + generic_iterate(struct advance_req_iter, const struct advance *, \ + _padvance, advance_req_iter_sizeof, advance_req_iter_init,\ + _goal) +#define advance_req_iterate_end generic_iterate_end + #ifdef __cplusplus } #endif /* __cplusplus */ _______________________________________________ Freeciv-commits mailing list Freeciv-commits@gna.org https://mail.gna.org/listinfo/freeciv-commits