/*
* Empire - A multi-player, client/server Internet based war game.
- * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
- * Ken Stevens, Steve McClure
+ * Copyright (C) 1986-2020, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Ken Stevens, Steve McClure, Markus Armbruster
*
- * This program is free software; you can redistribute it and/or modify
+ * Empire is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ---
*
- * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- * related information and legal notices. It is expected that any future
- * projects/authors will amend these files as needed.
+ * See files README, COPYING and CREDITS in the root of the source
+ * tree for related information and legal notices. It is expected
+ * that future projects/authors will amend these files as needed.
*
* ---
*
* news.c: Show current Empire news
- *
+ *
* Known contributors to this file:
- *
+ * Markus Armbruster, 2006-2016
*/
-#include "misc.h"
-#include "player.h"
-#include "nat.h"
-#include "news.h"
-#include "file.h"
-#include "xy.h"
-#include "nsc.h"
-#include "deity.h"
+#include <config.h>
+
+#include "chance.h"
#include "commands.h"
+#include "news.h"
#include "optlist.h"
-static void preport(register struct nwsstr *np);
+static void preport(struct nwsstr *np);
+static int sectwon_cmp(const void *p, const void *q);
+
+struct sectwon {
+ natid ano, vno;
+ unsigned short num;
+};
int
news(void)
{
- extern s_char *page_headings[];
- struct natstr *natp;
- time_t now;
- int page;
- time_t then;
- time_t delta;
- struct nwsstr nws;
- struct nstr_item nstr;
- int page_has_news[N_MAX_PAGE+1];
- int there_is_news = 0;
- short sectors_taken[MAXNOC][MAXNOC];
- short sectors_delta;
- short max_delta = -1;
- short abs_delta;
- short k;
- int sectors_were_taken = 0;
- natid i,j;
- s_char num[128];
- s_char *verb;
-
- bzero((s_char *)page_has_news, sizeof(page_has_news));
- bzero((s_char *)sectors_taken, sizeof(sectors_taken));
- (void) head();
- (void) time(&now);
- natp = getnatp(player->cnum);
- then = natp->nat_newstim;
- if (!opt_HIDDEN) {
- if (player->argp[1] != 0 && isdigit(*player->argp[1])) {
- delta = days(atoi(player->argp[1]));
- then = now - delta;
- }
+ struct natstr *natp;
+ time_t now;
+ int heading, page;
+ time_t then;
+ time_t delta;
+ struct nwsstr nws;
+ struct nstr_item nstr;
+ int page_has_news[N_MAX_PAGE + 1];
+ unsigned short sectors_taken[MAXNOC][MAXNOC];
+ natid i, j;
+ int k, n, diff;
+ struct sectwon *sectwon;
+ char num[128];
+ char *verb;
+
+ if (!snxtitem(&nstr, EF_NEWS, "*", NULL))
+ return RET_SYN;
+ memset(sectors_taken, 0, sizeof(sectors_taken));
+ (void)time(&now);
+ natp = getnatp(player->cnum);
+ then = natp->nat_newstim;
+ if (player->argp[1]) {
+ /*
+ * We want to hide events before contact. Proper solution
+ * would be to timestamp the contact. Cheesy approximation:
+ * disable old news.
+ */
+ if (opt_HIDDEN && !player->god) {
+ pr("Sorry, argument doesn't work with HIDDEN enabled\n");
+ return RET_FAIL;
}
- natp->nat_newstim = now;
-/* if (then < now - days(3))
- then = now - days(3);
-*/
- snxtitem(&nstr, EF_NEWS, "*");
- pr("\nThe details of Empire news since %s", ctime(&then));
- while (nxtitem(&nstr, (s_char *)&nws)) {
- if (nws.nws_when < then)
- continue;
- if (opt_HIDDEN) {
- if (!player->god &&
- !(getcontact(getnatp(player->cnum), nws.nws_ano) &&
- getcontact(getnatp(player->cnum), nws.nws_vno)))
- continue;
- }
- ++page_has_news[rpt[(int)nws.nws_vrb].r_newspage];
- ++there_is_news;
+ delta = days(atoi(player->argp[1]));
+ then = now - delta;
+ }
+ natp->nat_newstim = now;
+ head();
+ pr("\nThe details of Empire news since %s", ctime(&then));
+
+ heading = 0;
+ memset(page_has_news, 0, sizeof(page_has_news));
+ page_has_news[0] = 1;
+
+ for (page = 0; page <= N_MAX_PAGE; page++) {
+ if (!page_has_news[page])
+ continue;
+ snxtitem_rewind(&nstr);
+ while (nxtitem(&nstr, &nws)) {
+ if (CANT_HAPPEN(nws.nws_vrb > N_MAX_VERB))
+ continue;
+ if (nws.nws_when < then)
+ continue;
+ if (CANT_HAPPEN(nws.nws_ntm <= 0))
+ nws.nws_ntm = 1;
+ if (opt_HIDDEN) {
+ if (!player->god &&
+ !(in_contact(player->cnum, nws.nws_ano) &&
+ in_contact(player->cnum, nws.nws_vno)))
+ continue;
+ }
+ page_has_news[rpt[nws.nws_vrb].r_newspage] = 1;
+ if (rpt[nws.nws_vrb].r_newspage != page)
+ continue;
+ if (heading != page) {
+ pr("\n\t === %s ===\n", page_headings[page].name);
+ heading = page;
+ }
+ if (nws.nws_vrb == N_WON_SECT ||
+ nws.nws_vrb == N_AWON_SECT ||
+ nws.nws_vrb == N_PWON_SECT)
+ sectors_taken[nws.nws_ano][nws.nws_vno] += nws.nws_ntm;
+ preport(&nws);
}
- for (page = 1; page <= N_MAX_PAGE; page++) {
- if (!page_has_news[page])
- continue;
- pr("\n\t === %s ===\n", page_headings[page]);
- snxtitem_rewind(&nstr);
- while (nxtitem(&nstr, (s_char *)&nws)) {
- if (rpt[(int)nws.nws_vrb].r_newspage != page)
- continue;
- if (nws.nws_when < then)
- continue;
- if (nws.nws_ntm == 0)
- nws.nws_ntm = 1;
- if (opt_HIDDEN) {
- if (!player->god &&
- !(getcontact(getnatp(player->cnum), nws.nws_ano) &&
- getcontact(getnatp(player->cnum), nws.nws_vno)))
- continue;
- }
- if (page == N_FRONT &&
- (nws.nws_vrb == N_WON_SECT ||
- nws.nws_vrb == N_AWON_SECT ||
- nws.nws_vrb == N_PWON_SECT)) {
- sectors_taken[nws.nws_ano][nws.nws_vno] += nws.nws_ntm;
- sectors_were_taken += nws.nws_ntm;
- }
- preport(&nws);
- }
+ }
+
+ if (!heading) {
+ pr("\nNo news at the moment...\n");
+ return RET_OK;
+ }
+
+ n = 0;
+ for (i = 0; i < MAXNOC; ++i) {
+ for (j = 0; j < i; ++j)
+ n += !!(sectors_taken[i][j] - sectors_taken[j][i]);
+ }
+ sectwon = malloc(sizeof(*sectwon) * n);
+
+ n = 0;
+ for (i = 0; i < MAXNOC; ++i) {
+ for (j = 0; j < i; ++j) {
+ diff = sectors_taken[i][j] - sectors_taken[j][i];
+ if (diff > 0) {
+ sectwon[n].ano = i;
+ sectwon[n].vno = j;
+ sectwon[n].num = diff;
+ n++;
+ } else if (diff < 0) {
+ sectwon[n].ano = j;
+ sectwon[n].vno = i;
+ sectwon[n].num = -diff;
+ n++;
+ }
}
- if (sectors_were_taken) {
- for (i = 0; i < MAXNOC; ++i) {
- for (j = 0; j < i; ++j) {
- sectors_delta = sectors_taken[i][j] -
- sectors_taken[j][i];
- if (max_delta < abs(sectors_delta))
- max_delta = abs(sectors_delta);
- }
- }
- pr("\n\t === The Bottom Line ==\n");
- for (k = max_delta; k > 0; --k) {
- for (i = 0; i < MAXNOC; ++i) {
- for (j = 0; j < i; ++j) {
- sectors_delta = sectors_taken[i][j] -
- sectors_taken[j][i];
- abs_delta = abs(sectors_delta);
- if (abs_delta != k)
- continue;
- if (abs_delta == 1)
- verb = "stole";
- else if (abs_delta < 4)
- verb = "took";
- else if (abs_delta < 8)
- verb = "captured";
- else
- verb = "seized";
- if (sectors_delta > 0) {
- numstr(num, abs_delta);
- pr("%s %s %s sector%s from %s\n", cname(i), verb, num, splur(sectors_delta), cname(j));
- } else if (sectors_delta < 0) {
- numstr(num, abs_delta);
- pr("%s %s %s sector%s from %s\n", cname(j), verb, num, splur(-sectors_delta), cname(i));
- }
- }
- }
- }
+ }
+
+ qsort(sectwon, n, sizeof(*sectwon), sectwon_cmp);
+
+ if (n) {
+ pr("\n\t === The Bottom Line ==\n");
+ for (k = 0; k < n; k++) {
+ if (sectwon[k].num == 1)
+ verb = "stole";
+ else if (sectwon[k].num < 4)
+ verb = "took";
+ else if (sectwon[k].num < 8)
+ verb = "captured";
+ else
+ verb = "seized";
+ numstr(num, sectwon[k].num);
+ pr("%s %s %s sector%s from %s\n",
+ cname(sectwon[k].ano), verb, num, splur(sectwon[k].num),
+ cname(sectwon[k].vno));
}
- if (!there_is_news)
- pr("\nNo news at the moment...\n");
- return 0;
+ }
+
+ free(sectwon);
+ return RET_OK;
}
static void
-preport(register struct nwsstr *np)
+preport(struct nwsstr *np)
{
- register s_char *cp;
- register int i;
- s_char buf[255];
- s_char num[128];
- s_char *ptr;
-
- cp = buf;
- sprintf(buf, "%-16.16s ", ctime(&np->nws_when));
- cp += strlen(cp);
- ptr = numstr(num, np->nws_ntm);
- /*
- * vary the order of the printing of "%d times "
- */
- if ((random() & 3) == 0 && np->nws_ntm > 1) {
- sprintf(cp, "%s times ", ptr);
- cp += strlen(cp);
- np->nws_ntm = 1;
- }
- strcpy(cp, cname(np->nws_ano));
+ char *cp;
+ int i;
+ char buf[255];
+ char num[128];
+ char *ptr;
+
+ cp = buf;
+ sprintf(buf, "%-16.16s ", ctime(&np->nws_when));
+ cp += strlen(cp);
+ ptr = numstr(num, np->nws_ntm);
+ /*
+ * vary the order of the printing of "%d times "
+ */
+ if (roll0(4) == 0 && np->nws_ntm > 1) {
+ sprintf(cp, "%s times ", ptr);
cp += strlen(cp);
- *cp++ = ' ';
- if (np->nws_vrb < 1 || np->nws_vrb > N_MAX_VERB)
- np->nws_vrb = 0;
- sprintf(cp, rpt[(int)np->nws_vrb].r_newstory[random() % NUM_RPTS],
- cname(np->nws_vno));
+ np->nws_ntm = 1;
+ }
+ strcpy(cp, cname(np->nws_ano));
+ cp += strlen(cp);
+ *cp++ = ' ';
+ sprintf(cp, rpt[(int)np->nws_vrb].r_newstory[roll0(NUM_RPTS)],
+ cname(np->nws_vno));
+ cp += strlen(cp);
+ if (np->nws_ntm != 1) {
+ sprintf(cp, " %s times", ptr);
cp += strlen(cp);
- if (np->nws_ntm != 1) {
- sprintf(cp, " %s times", ptr);
- cp += strlen(cp);
- }
- if (*buf >= 'a' && *buf <= 'z')
- *buf += 'A' - 'a';
- if (cp - buf > 80) {
- for (i=80; --i > 60; )
- if (buf[i] == ' ') break;
- buf[i] = '\0';
- pr("%s\n\t\t %s\n", buf, &buf[i+1]);
- } else {
- pr("%s\n", buf);
- }
- np->nws_ntm = 0;
- return;
+ }
+ if (cp - buf > 80) {
+ for (i = 80; --i > 60;)
+ if (buf[i] == ' ')
+ break;
+ buf[i] = '\0';
+ pr("%s\n\t\t %s\n", buf, &buf[i + 1]);
+ } else {
+ pr("%s\n", buf);
+ }
+ np->nws_ntm = 0;
+ return;
+}
+
+static int
+sectwon_cmp(const void *p, const void *q)
+{
+ const struct sectwon *a = p, *b = q;
+ int cmp;
+
+ cmp = b->num - a->num;
+ if (cmp)
+ return cmp;
+ cmp = b->ano - a->ano;
+ if (cmp)
+ return cmp;
+ return b->vno - a->vno;
}