From 09800b8387addbd76e6517821a4aeac3d78f8f70 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 13 Jun 2012 23:25:20 -0700 Subject: [PATCH] moving things into laws.c, where a lot of order processing happens now. --- src/gamecode/laws.c | 330 +++++++++++++++++++++++++++++++++++++++++++ src/gamecode/laws.h | 8 +- src/gamecode/spy.c | 2 +- src/kernel/build.c | 336 -------------------------------------------- src/kernel/build.h | 5 - 5 files changed, 338 insertions(+), 343 deletions(-) diff --git a/src/gamecode/laws.c b/src/gamecode/laws.c index 7f4c9278d..95af2bfa3 100755 --- a/src/gamecode/laws.c +++ b/src/gamecode/laws.c @@ -1063,6 +1063,112 @@ static void transfer_faction(faction * f, faction * f2) } } +/* test if the unit can slip through a siege undetected. + * returns 0 if siege is successful, or 1 if the building is either + * not besieged or the unit can slip through the siege due to better stealth. + */ +static int slipthru(const region * r, const unit * u, const building * b) +{ + unit *u2; + int n, o; + + /* b ist die burg, in die man hinein oder aus der man heraus will. */ + if (b == NULL || b->besieged < b->size * SIEGEFACTOR) { + return 1; + } + + /* u wird am hinein- oder herausschluepfen gehindert, wenn STEALTH <= + * OBSERVATION +2 der belagerer u2 ist */ + n = eff_skill(u, SK_STEALTH, r); + + for (u2 = r->units; u2; u2 = u2->next) { + if (usiege(u2) == b) { + + if (invisible(u, u2) >= u->number) + continue; + + o = eff_skill(u2, SK_PERCEPTION, r); + + if (o + 2 >= n) { + return 0; /* entdeckt! */ + } + } + } + return 1; +} + +int can_contact(const region * r, const unit * u, const unit * u2) { + + /* hier geht es nur um die belagerung von burgen */ + + if (u->building == u2->building) { + return 1; + } + + /* unit u is trying to contact u2 - unasked for contact. wenn u oder u2 + * nicht in einer burg ist, oder die burg nicht belagert ist, ist + * slipthru () == 1. ansonsten ist es nur 1, wenn man die belagerer */ + + if (slipthru(u->region, u, u->building) && slipthru(u->region, u2, u2->building)) { + return 1; + } + + return (alliedunit(u, u2->faction, HELP_GIVE)); +} + +void contact_cmd(unit * u, order * ord, int final) +{ + /* unit u kontaktiert unit u2. Dies setzt den contact einfach auf 1 - + * ein richtiger toggle ist (noch?) nicht noetig. die region als + * parameter ist nur deswegen wichtig, weil er an getunit () + * weitergegeben wird. dies wird fuer das auffinden von tempunits in + * getnewunit () verwendet! */ + unit *u2; + region *r = u->region; + + init_tokens(ord); + skip_token(); + u2 = getunitg(r, u->faction); + + if (u2 != NULL) { + if (!can_contact(r, u, u2)) { + if (final) { + cmistake(u, u->thisorder, 23, MSG_EVENT); + } + return; + } + usetcontact(u, u2); + } +} + +int leave_cmd(unit * u, struct order *ord) +{ + region *r = u->region; + + if (fval(u, UFL_ENTER)) { + /* if we just entered this round, then we don't leave again */ + return 0; + } + + if (fval(r->terrain, SEA_REGION) && u->ship) { + if (!fval(u->race, RCF_SWIM)) { + cmistake(u, ord, 11, MSG_MOVE); + return 0; + } + if (has_horses(u)) { + cmistake(u, ord, 231, MSG_MOVE); + return 0; + } + } + if (!slipthru(r, u, u->building)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "entrance_besieged", + "building", u->building)); + } else { + leave(u, true); + } + return 0; +} + static int restart_cmd(unit * u, struct order *ord) { init_tokens(ord); @@ -1159,6 +1265,230 @@ int quit_cmd(unit * u, struct order *ord) return 0; } +static boolean mayenter(region * r, unit * u, building * b) +{ + unit *u2; + if (fval(b, BLD_UNGUARDED)) + return true; + u2 = building_owner(b); + + if (u2 == NULL || ucontact(u2, u) + || alliedunit(u2, u->faction, HELP_GUARD)) + return true; + + return false; +} + +static int mayboard(const unit * u, ship * sh) +{ + unit *u2 = ship_owner(sh); + + return (!u2 || ucontact(u2, u) || alliedunit(u2, u->faction, HELP_GUARD)); +} + +static boolean CheckOverload(void) +{ + static int value = -1; + if (value < 0) { + value = get_param_int(global.parameters, "rules.check_overload", 0); + } + return value; +} + +int enter_ship(unit * u, struct order *ord, int id, int report) +{ + region *r = u->region; + ship *sh; + + /* Muß abgefangen werden, sonst könnten Schwimmer an + * Bord von Schiffen an Land gelangen. */ + if (!fval(u->race, RCF_CANSAIL) || (!fval(u->race, RCF_WALK) + && !fval(u->race, RCF_FLY))) { + cmistake(u, ord, 233, MSG_MOVE); + return 0; + } + + sh = findship(id); + if (sh == NULL || sh->region != r) { + if (report) + cmistake(u, ord, 20, MSG_MOVE); + return 0; + } + if (sh == u->ship) { + return 1; + } + if (!mayboard(u, sh)) { + if (report) + cmistake(u, ord, 34, MSG_MOVE); + return 0; + } + if (CheckOverload()) { + int sweight, scabins; + int mweight = shipcapacity(sh); + int mcabins = sh->type->cabins; + + if (mweight > 0) { + getshipweight(sh, &sweight, &scabins); + sweight += weight(u); + if (mcabins) { + int pweight = u->number * u->race->weight; + /* weight goes into number of cabins, not cargo */ + scabins += pweight; + sweight -= pweight; + } + + if (sweight > mweight || (mcabins && (scabins > mcabins))) { + if (report) + cmistake(u, ord, 34, MSG_MOVE); + return 0; + } + } + } + + if (leave(u, 0)) { + u_set_ship(u, sh); + fset(u, UFL_ENTER); + } + return 1; +} + +int enter_building(unit * u, order * ord, int id, int report) +{ + region *r = u->region; + building *b; + + /* Schwimmer können keine Gebäude betreten, außer diese sind + * auf dem Ozean */ + if (!fval(u->race, RCF_WALK) && !fval(u->race, RCF_FLY)) { + if (!fval(r->terrain, SEA_REGION)) { + if (report) { + cmistake(u, ord, 232, MSG_MOVE); + } + return 0; + } + } + + b = findbuilding(id); + if (b == NULL || b->region != r) { + if (report) { + cmistake(u, ord, 6, MSG_MOVE); + } + return 0; + } + if (!mayenter(r, u, b)) { + if (report) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_denied", + "building", b)); + } + return 0; + } + if (!slipthru(r, u, b)) { + if (report) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_besieged", + "building", b)); + } + return 0; + } + + if (leave(u, 0)) { + fset(u, UFL_ENTER); + u_set_building(u, b); + return 1; + } + return 0; +} + +static void do_misc(region * r, int is_final_attempt) +{ + unit **uptr, *uc; + + for (uc = r->units; uc; uc = uc->next) { + order *ord; + for (ord = uc->orders; ord; ord = ord->next) { + keyword_t kwd = get_keyword(ord); + if (kwd == K_CONTACT) { + contact_cmd(uc, ord, is_final_attempt); + } + } + } + + for (uptr = &r->units; *uptr;) { + unit *u = *uptr; + order **ordp = &u->orders; + + while (*ordp) { + order *ord = *ordp; + if (get_keyword(ord) == K_ENTER) { + param_t p; + int id; + unit *ulast = NULL; + const char * s; + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + p = findparam_ex(s, u->faction->locale); + id = getid(); + + switch (p) { + case P_BUILDING: + case P_GEBAEUDE: + if (u->building && u->building->no == id) + break; + if (enter_building(u, ord, id, is_final_attempt)) { + unit *ub; + for (ub = u; ub; ub = ub->next) { + if (ub->building == u->building) { + ulast = ub; + } + } + } + break; + + case P_SHIP: + if (u->ship && u->ship->no == id) + break; + if (enter_ship(u, ord, id, is_final_attempt)) { + unit *ub; + ulast = u; + for (ub = u; ub; ub = ub->next) { + if (ub->ship == u->ship) { + ulast = ub; + } + } + } + break; + + default: + if (is_final_attempt) { + cmistake(u, ord, 79, MSG_MOVE); + } + } + if (ulast != NULL) { + /* Wenn wir hier angekommen sind, war der Befehl + * erfolgreich und wir löschen ihn, damit er im + * zweiten Versuch nicht nochmal ausgeführt wird. */ + *ordp = ord->next; + ord->next = NULL; + free_order(ord); + + if (ulast != u) { + /* put u behind ulast so it's the last unit in the building */ + *uptr = u->next; + u->next = ulast->next; + ulast->next = u; + } + break; + } + } + if (*ordp == ord) + ordp = &ord->next; + } + if (*uptr == u) + uptr = &u->next; + } +} + void quit(void) { faction **fptr = &factions; diff --git a/src/gamecode/laws.h b/src/gamecode/laws.h index b3503f5d7..d0ba9965e 100755 --- a/src/gamecode/laws.h +++ b/src/gamecode/laws.h @@ -37,6 +37,7 @@ extern "C" { boolean renamed_building(const struct building * b); int rename_building(struct unit * u, struct order * ord, struct building * b, const char *name); void get_food(struct region * r); + extern int can_contact(const struct region *r, const struct unit *u, const struct unit *u2); /* eressea-specific. put somewhere else, please. */ void processorders(void); @@ -45,9 +46,13 @@ extern "C" { extern int dropouts[2]; extern int *age; + extern int enter_building(struct unit *u, struct order *ord, int id, int report); + extern int enter_ship(struct unit *u, struct order *ord, int id, int report); + extern void contact_cmd(struct unit *u, struct order *ord, int final); + extern void new_units(void); extern void quit(void); - extern void update_long_order(struct unit * u); + extern void update_long_order(struct unit *u); extern int password_cmd(struct unit *u, struct order *ord); extern int banner_cmd(struct unit *u, struct order *ord); extern int email_cmd(struct unit *u, struct order *ord); @@ -62,6 +67,7 @@ extern "C" { extern int quit_cmd(struct unit *u, struct order *ord); extern int name_cmd(struct unit *u, struct order *ord); extern int use_cmd(struct unit *u, struct order *ord); + extern int leave_cmd(struct unit *u, struct order *ord); #ifdef __cplusplus } diff --git a/src/gamecode/spy.c b/src/gamecode/spy.c index 76b0360b5..43eb475cb 100644 --- a/src/gamecode/spy.c +++ b/src/gamecode/spy.c @@ -19,9 +19,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include "spy.h" +#include "laws.h" /* kernel includes */ -#include #include #include #include diff --git a/src/kernel/build.c b/src/kernel/build.c index 6b9746e24..a37265d23 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -69,99 +69,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* Name, MaxGroesse, MinBauTalent, Kapazitaet, {Eisen, Holz, Stein, BauSilber, * Laen, Mallorn}, UnterSilber, UnterSpezialTyp, UnterSpezial */ -static boolean CheckOverload(void) -{ - static int value = -1; - if (value < 0) { - value = get_param_int(global.parameters, "rules.check_overload", 0); - } - return value; -} - -/* test if the unit can slip through a siege undetected. - * returns 0 if siege is successful, or 1 if the building is either - * not besieged or the unit can slip through the siege due to better stealth. - */ -static int slipthru(const region * r, const unit * u, const building * b) -{ - unit *u2; - int n, o; - - /* b ist die burg, in die man hinein oder aus der man heraus will. */ - if (b == NULL || b->besieged < b->size * SIEGEFACTOR) { - return 1; - } - - /* u wird am hinein- oder herausschluepfen gehindert, wenn STEALTH <= - * OBSERVATION +2 der belagerer u2 ist */ - n = eff_skill(u, SK_STEALTH, r); - - for (u2 = r->units; u2; u2 = u2->next) { - if (usiege(u2) == b) { - - if (invisible(u, u2) >= u->number) - continue; - - o = eff_skill(u2, SK_PERCEPTION, r); - - if (o + 2 >= n) { - return 0; /* entdeckt! */ - } - } - } - return 1; -} - -int can_contact(const region * r, const unit * u, const unit * u2) -{ - - /* hier geht es nur um die belagerung von burgen */ - - if (u->building == u2->building) { - return 1; - } - - /* unit u is trying to contact u2 - unasked for contact. wenn u oder u2 - * nicht in einer burg ist, oder die burg nicht belagert ist, ist - * slipthru () == 1. ansonsten ist es nur 1, wenn man die belagerer */ - - if (slipthru(u->region, u, u->building) && slipthru(u->region, u2, u2->building)) { - return 1; - } - - return (alliedunit(u, u2->faction, HELP_GIVE)); -} - -static void contact_cmd(unit * u, order * ord, int final) -{ - /* unit u kontaktiert unit u2. Dies setzt den contact einfach auf 1 - - * ein richtiger toggle ist (noch?) nicht noetig. die region als - * parameter ist nur deswegen wichtig, weil er an getunit () - * weitergegeben wird. dies wird fuer das auffinden von tempunits in - * getnewunit () verwendet! */ - unit *u2; - region *r = u->region; - - init_tokens(ord); - skip_token(); - u2 = getunitg(r, u->faction); - - if (u2 != NULL) { - if (!can_contact(r, u, u2)) { - if (final) - cmistake(u, u->thisorder, 23, MSG_EVENT); - return; - } - usetcontact(u, u2); - } -} - -/* ------------------------------------------------------------- */ - -/* ------------------------------------------------------------- */ - -/* ------------------------------------------------------------- */ - struct building *getbuilding(const struct region *r) { building *b = findbuilding(getid()); @@ -1152,246 +1059,3 @@ void continue_ship(region * r, unit * u, int want) build_ship(u, sh, want); } -/* ------------------------------------------------------------- */ - -static boolean mayenter(region * r, unit * u, building * b) -{ - unit *u2; - if (fval(b, BLD_UNGUARDED)) - return true; - u2 = building_owner(b); - - if (u2 == NULL || ucontact(u2, u) - || alliedunit(u2, u->faction, HELP_GUARD)) - return true; - - return false; -} - -static int mayboard(const unit * u, ship * sh) -{ - unit *u2 = ship_owner(sh); - - return (!u2 || ucontact(u2, u) || alliedunit(u2, u->faction, HELP_GUARD)); -} - -int leave_cmd(unit * u, struct order *ord) -{ - region *r = u->region; - - if (fval(u, UFL_ENTER)) { - /* if we just entered this round, then we don't leave again */ - return 0; - } - - if (fval(r->terrain, SEA_REGION) && u->ship) { - if (!fval(u->race, RCF_SWIM)) { - cmistake(u, ord, 11, MSG_MOVE); - return 0; - } - if (has_horses(u)) { - cmistake(u, ord, 231, MSG_MOVE); - return 0; - } - } - if (!slipthru(r, u, u->building)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "entrance_besieged", - "building", u->building)); - } else { - leave(u, true); - } - return 0; -} - -static boolean enter_ship(unit * u, struct order *ord, int id, boolean report) -{ - region *r = u->region; - ship *sh; - - /* Muß abgefangen werden, sonst könnten Schwimmer an - * Bord von Schiffen an Land gelangen. */ - if (!fval(u->race, RCF_CANSAIL) || (!fval(u->race, RCF_WALK) - && !fval(u->race, RCF_FLY))) { - cmistake(u, ord, 233, MSG_MOVE); - return false; - } - - sh = findship(id); - if (sh == NULL || sh->region != r) { - if (report) - cmistake(u, ord, 20, MSG_MOVE); - return false; - } - if (sh == u->ship) - return true; - if (!mayboard(u, sh)) { - if (report) - cmistake(u, ord, 34, MSG_MOVE); - return false; - } - if (CheckOverload()) { - int sweight, scabins; - int mweight = shipcapacity(sh); - int mcabins = sh->type->cabins; - - if (mweight > 0) { - getshipweight(sh, &sweight, &scabins); - sweight += weight(u); - if (mcabins) { - int pweight = u->number * u->race->weight; - /* weight goes into number of cabins, not cargo */ - scabins += pweight; - sweight -= pweight; - } - - if (sweight > mweight || (mcabins && (scabins > mcabins))) { - if (report) - cmistake(u, ord, 34, MSG_MOVE); - return false; - } - } - } - - if (leave(u, false)) { - u_set_ship(u, sh); - fset(u, UFL_ENTER); - } - return true; -} - -static boolean enter_building(unit * u, order * ord, int id, boolean report) -{ - region *r = u->region; - building *b; - - /* Schwimmer können keine Gebäude betreten, außer diese sind - * auf dem Ozean */ - if (!fval(u->race, RCF_WALK) && !fval(u->race, RCF_FLY)) { - if (!fval(r->terrain, SEA_REGION)) { - if (report) { - cmistake(u, ord, 232, MSG_MOVE); - } - return false; - } - } - - b = findbuilding(id); - if (b == NULL || b->region != r) { - if (report) { - cmistake(u, ord, 6, MSG_MOVE); - } - return false; - } - if (!mayenter(r, u, b)) { - if (report) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_denied", - "building", b)); - } - return false; - } - if (!slipthru(r, u, b)) { - if (report) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "entrance_besieged", - "building", b)); - } - return false; - } - - if (leave(u, false)) { - fset(u, UFL_ENTER); - u_set_building(u, b); - return true; - } - return false; -} - -void do_misc(region * r, int is_final_attempt) -{ - unit **uptr, *uc; - - for (uc = r->units; uc; uc = uc->next) { - order *ord; - for (ord = uc->orders; ord; ord = ord->next) { - keyword_t kwd = get_keyword(ord); - if (kwd == K_CONTACT) { - contact_cmd(uc, ord, is_final_attempt); - } - } - } - - for (uptr = &r->units; *uptr;) { - unit *u = *uptr; - order **ordp = &u->orders; - - while (*ordp) { - order *ord = *ordp; - if (get_keyword(ord) == K_ENTER) { - param_t p; - int id; - unit *ulast = NULL; - const char * s; - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - p = findparam_ex(s, u->faction->locale); - id = getid(); - - switch (p) { - case P_BUILDING: - case P_GEBAEUDE: - if (u->building && u->building->no == id) - break; - if (enter_building(u, ord, id, is_final_attempt)) { - unit *ub; - for (ub = u; ub; ub = ub->next) { - if (ub->building == u->building) { - ulast = ub; - } - } - } - break; - - case P_SHIP: - if (u->ship && u->ship->no == id) - break; - if (enter_ship(u, ord, id, is_final_attempt)) { - unit *ub; - ulast = u; - for (ub = u; ub; ub = ub->next) { - if (ub->ship == u->ship) { - ulast = ub; - } - } - } - break; - - default: - if (is_final_attempt) { - cmistake(u, ord, 79, MSG_MOVE); - } - } - if (ulast != NULL) { - /* Wenn wir hier angekommen sind, war der Befehl - * erfolgreich und wir löschen ihn, damit er im - * zweiten Versuch nicht nochmal ausgeführt wird. */ - *ordp = ord->next; - ord->next = NULL; - free_order(ord); - - if (ulast != u) { - /* put u behind ulast so it's the last unit in the building */ - *uptr = u->next; - u->next = ulast->next; - ulast->next = u; - } - break; - } - } - if (*ordp == ord) - ordp = &ord->next; - } - if (*uptr == u) - uptr = &u->next; - } -} diff --git a/src/kernel/build.h b/src/kernel/build.h index 5407034bf..20577da8e 100644 --- a/src/kernel/build.h +++ b/src/kernel/build.h @@ -64,9 +64,6 @@ extern "C" { extern int destroy_cmd(struct unit *u, struct order *ord); extern int leave_cmd(struct unit *u, struct order *ord); - extern int can_contact(const struct region *r, const struct unit *u, - const struct unit *u2); - void do_siege(struct region *r); void build_road(struct region *r, struct unit *u, int size, direction_t d); void create_ship(struct region *r, struct unit *u, @@ -76,8 +73,6 @@ extern "C" { struct building *getbuilding(const struct region *r); struct ship *getship(const struct region *r); - void do_misc(struct region *r, int is_final_attempt); - void reportevent(struct region *r, char *s); void shash(struct ship *sh);