From ebe365fd6ed1aba669a1d7cd63ffe131dcb5c0d3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 18 Aug 2015 18:57:04 +0200 Subject: [PATCH] move travelthru logic to a separate module. todo: split off the report writing from the collection of units. --- src/CMakeLists.txt | 1 + src/creport.c | 1 + src/kernel/region.c | 12 ---- src/kernel/region.h | 1 - src/move.c | 24 +------ src/move.h | 1 - src/report.c | 102 ++-------------------------- src/report.h | 7 +- src/reports.c | 1 + src/reports.test.c | 1 + src/travelthru.c | 159 ++++++++++++++++++++++++++++++++++++++++++++ src/travelthru.h | 20 ++++++ 12 files changed, 197 insertions(+), 133 deletions(-) create mode 100644 src/travelthru.c create mode 100644 src/travelthru.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2cd21396..b04631e6a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,6 +108,7 @@ set (ERESSEA_SRC spy.c study.c summary.c + travelthru.c monsters.c wormhole.c ${SPELLS_SRC} diff --git a/src/creport.c b/src/creport.c index 6f8be4f2c..6794c33d6 100644 --- a/src/creport.c +++ b/src/creport.c @@ -11,6 +11,7 @@ without prior permission by the authors of Eressea. #include #include "buildno.h" #include "creport.h" +#include "travelthru.h" /* tweakable features */ #define RENDER_CRMESSAGES diff --git a/src/kernel/region.c b/src/kernel/region.c index ddaab10d1..999b8dc33 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -525,18 +525,6 @@ attrib_type at_woodcount = { ATF_UNIQUE }; -/*********************/ -/* at_travelunit */ -/*********************/ -attrib_type at_travelunit = { - "travelunit", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ -}; - void rsetroad(region * r, direction_t d, int val) { connection *b; diff --git a/src/kernel/region.h b/src/kernel/region.h index 5c2c3a17c..c29732b78 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -169,7 +169,6 @@ extern "C" { extern struct attrib_type at_horseluck; extern struct attrib_type at_woodcount; extern struct attrib_type at_deathcount; - extern struct attrib_type at_travelunit; void initrhash(void); void rhash(struct region *r); diff --git a/src/move.c b/src/move.c index 131d87e74..de1cb05bd 100644 --- a/src/move.c +++ b/src/move.c @@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "laws.h" #include "reports.h" #include "alchemy.h" +#include "travelthru.h" #include "vortex.h" #include "monster.h" #include "lighthouse.h" @@ -501,29 +502,6 @@ static ship *do_maelstrom(region * r, unit * u) return u->ship; } -/** sets a marker in the region telling that the unit has travelled through it - * this is used for two distinctly different purposes: - * - to report that a unit has travelled through. the report function - * makes sure to only report the ships of travellers, not the travellers - * themselves - * - to report the region to the traveller - */ -void travelthru(const unit * u, region * r) -{ - attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); - - fset(r, RF_TRAVELUNIT); - - ru->data.v = (void *)u; - - /* the first and last region of the faction gets reset, because travelthrough - * could be in regions that are located before the [first, last] interval, - * and recalculation is needed */ -#ifdef SMART_INTERVALS - update_interval(u->faction, r); -#endif -} - static direction_t koor_reldirection(int ax, int ay, int bx, int by, const struct plane *pl) { diff --git a/src/move.h b/src/move.h index 7674c43d7..013885564 100644 --- a/src/move.h +++ b/src/move.h @@ -64,7 +64,6 @@ extern "C" { int enoughsailors(const struct ship *sh, int sumskill); bool canswim(struct unit *u); bool canfly(struct unit *u); - void travelthru(const struct unit *u, struct region *r); struct ship *move_ship(struct ship *sh, struct region *from, struct region *to, struct region_list *route); int walkingcapacity(const struct unit *u); diff --git a/src/report.c b/src/report.c index ce71d78fa..d02d9a7fc 100644 --- a/src/report.c +++ b/src/report.c @@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "reports.h" #include "laws.h" +#include "travelthru.h" #include "monster.h" /* modules includes */ @@ -163,7 +164,7 @@ static void centre(stream *out, const char *s, bool breaking) } } -static void +void paragraph(stream *out, const char *str, ptrdiff_t indent, int hanging_indent, char marker) { @@ -1345,100 +1346,6 @@ static void statistics(stream *out, const region * r, const faction * f) } -static int count_travelthru(const region *r, const faction *f, attrib *alist) { - int maxtravel = 0; - attrib *a; - for (a = alist; a && a->type == &at_travelunit; a = a->next) { - unit *u = (unit *)a->data.v; - - if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { - if (cansee_durchgezogen(f, r, u, 0)) { - ++maxtravel; - } - } - } - return maxtravel; -} - -void write_travelthru(stream *out, const region * r, const faction * f) -{ - attrib *abegin, *a; - int counter = 0, maxtravel = 0; - char buf[8192]; - char *bufp = buf; - int bytes; - size_t size = sizeof(buf) - 1; - - assert(r); - assert(f); - if (!fval(r, RF_TRAVELUNIT)) { - return; - } - CHECK_ERRNO(); - abegin = a_find(r->attribs, &at_travelunit); - - /* How many are we listing? For grammar. */ - maxtravel = count_travelthru(r, f, abegin); - if (maxtravel == 0) { - return; - } - - /* Auflisten. */ - newline(out); - for (a = abegin; a && a->type == &at_travelunit; a = a->next) { - unit *u = (unit *)a->data.v; - - if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { - if (cansee_durchgezogen(f, r, u, 0)) { - ++counter; - if (u->ship != NULL) { - bytes = (int)strlcpy(bufp, shipname(u->ship), size); - } - else { - bytes = (int)strlcpy(bufp, unitname(u), size); - } - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - - if (counter + 1 < maxtravel) { - bytes = (int)strlcpy(bufp, ", ", size); - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - } - else if (counter + 1 == maxtravel) { - bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size); - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) { - INFO_STATIC_BUFFER(); - break; - } - } - } - } - } - if (size > 0) { - CHECK_ERRNO(); - if (maxtravel == 1) { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one")); - } - else { - bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_many")); - } - CHECK_ERRNO(); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER_EX("write_travelthru"); - CHECK_ERRNO(); - } - *bufp = 0; - paragraph(out, buf, 0, 0, 0); -} - static int buildingmaintenance(const building * b, const resource_type * rtype) { const building_type *bt = b->type; @@ -2340,20 +2247,25 @@ const char *charset) } } guards(out, r, f); + newline(out); write_travelthru(out, r, f); } else { if (sr->mode == see_far) { describe(out, sr, f); + newline(out); guards(out, r, f); + newline(out); write_travelthru(out, r, f); } else if (sr->mode == see_lighthouse) { describe(out, sr, f); + newline(out); write_travelthru(out, r, f); } else { describe(out, sr, f); + newline(out); write_travelthru(out, r, f); } } diff --git a/src/report.h b/src/report.h index 4a2299969..69f64702c 100644 --- a/src/report.h +++ b/src/report.h @@ -1,3 +1,4 @@ +#pragma once /* +-------------------+ Christian Schlittchen | | Enno Rehling @@ -11,6 +12,9 @@ */ #ifndef H_GC_REPORT #define H_GC_REPORT + +#include + #ifdef __cplusplus extern "C" { #endif @@ -21,7 +25,8 @@ extern "C" { void register_nr(void); void report_cleanup(void); void write_spaces(struct stream *out, size_t num); - void write_travelthru(struct stream *out, const struct region * r, const struct faction * f); + + void paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_indent, char marker); #ifdef __cplusplus } #endif diff --git a/src/reports.c b/src/reports.c index c381ac831..7cd67d010 100644 --- a/src/reports.c +++ b/src/reports.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "reports.h" #include "laws.h" +#include "travelthru.h" #include "lighthouse.h" /* kernel includes */ diff --git a/src/reports.test.c b/src/reports.test.c index 780d69b4d..c9679827e 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -4,6 +4,7 @@ #include "report.h" #include "creport.h" #include "move.h" +#include "travelthru.h" #include #include diff --git a/src/travelthru.c b/src/travelthru.c new file mode 100644 index 000000000..bbb4674b9 --- /dev/null +++ b/src/travelthru.c @@ -0,0 +1,159 @@ +/* +Copyright (c) 1998-2015, Enno Rehling +Katja Zedel + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +**/ + +#include +#include + +#include "travelthru.h" +#include "laws.h" +#include "report.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/*********************/ +/* at_travelunit */ +/*********************/ +attrib_type at_travelunit = { + "travelunit", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + NO_READ +}; + +static int count_travelthru(const struct region *r, const struct faction *f, attrib *alist) { + int maxtravel = 0; + attrib *a; + for (a = alist; a && a->type == &at_travelunit; a = a->next) { + unit *u = (unit *)a->data.v; + + if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { + if (cansee_durchgezogen(f, r, u, 0)) { + ++maxtravel; + } + } + } + return maxtravel; +} + +void write_travelthru(stream *out, const region * r, const faction * f) +{ + attrib *abegin, *a; + int counter = 0, maxtravel = 0; + char buf[8192]; + char *bufp = buf; + int bytes; + size_t size = sizeof(buf) - 1; + + assert(r); + assert(f); + if (!fval(r, RF_TRAVELUNIT)) { + return; + } + abegin = a_find(r->attribs, &at_travelunit); + + /* How many are we listing? For grammar. */ + maxtravel = count_travelthru(r, f, abegin); + if (maxtravel == 0) { + return; + } + + /* Auflisten. */ + for (a = abegin; a && a->type == &at_travelunit; a = a->next) { + unit *u = (unit *)a->data.v; + + if (r != u->region && (!u->ship || ship_owner(u->ship) == u)) { + if (cansee_durchgezogen(f, r, u, 0)) { + ++counter; + if (u->ship != NULL) { + bytes = (int)strlcpy(bufp, shipname(u->ship), size); + } + else { + bytes = (int)strlcpy(bufp, unitname(u), size); + } + if (wrptr(&bufp, &size, bytes) != 0) { + INFO_STATIC_BUFFER(); + break; + } + + if (counter + 1 < maxtravel) { + bytes = (int)strlcpy(bufp, ", ", size); + if (wrptr(&bufp, &size, bytes) != 0) { + INFO_STATIC_BUFFER(); + break; + } + } + else if (counter + 1 == maxtravel) { + bytes = (int)strlcpy(bufp, LOC(f->locale, "list_and"), size); + if (wrptr(&bufp, &size, bytes) != 0) { + INFO_STATIC_BUFFER(); + break; + } + } + } + } + } + if (size > 0) { + if (maxtravel == 1) { + bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_one")); + } + else { + bytes = _snprintf(bufp, size, " %s", LOC(f->locale, "has_moved_many")); + } + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER_EX("write_travelthru"); + } + *bufp = 0; + paragraph(out, buf, 0, 0, 0); +} + +/** sets a marker in the region telling that the unit has travelled through it +* this is used for two distinctly different purposes: +* - to report that a unit has travelled through. the report function +* makes sure to only report the ships of travellers, not the travellers +* themselves +* - to report the region to the traveller +*/ +void travelthru(const unit * u, region * r) +{ + attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); + + fset(r, RF_TRAVELUNIT); + + ru->data.v = (void *)u; + + /* the first and last region of the faction gets reset, because travelthrough + * could be in regions that are located before the [first, last] interval, + * and recalculation is needed */ +#ifdef SMART_INTERVALS + update_interval(u->faction, r); +#endif +} + diff --git a/src/travelthru.h b/src/travelthru.h new file mode 100644 index 000000000..29ecf4261 --- /dev/null +++ b/src/travelthru.h @@ -0,0 +1,20 @@ +#pragma once + +#ifndef H_TRAVELTHRU +#define H_TRAVELTHRU +#ifdef __cplusplus +extern "C" { +#endif + + extern struct attrib_type at_travelunit; + + struct stream; + struct region; + struct faction; + void write_travelthru(struct stream *out, const struct region * r, const struct faction * f); + void travelthru(const struct unit * u, struct region * r); + +#ifdef __cplusplus +} +#endif +#endif