]> git.pond.sub.org Git - empserver/blobdiff - src/lib/commands/news.c
Update copyright notice
[empserver] / src / lib / commands / news.c
index c7ba54bb6fdc0dace5a1dd1e98498907bfc35c0b..d6b6ba5a1843f96e00d1d8bd96b944555eb1341b 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2017, 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 <config.h>
 
-#include "misc.h"
-#include "player.h"
-#include "nat.h"
-#include "news.h"
-#include "file.h"
-#include "xy.h"
-#include "nsc.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)
 {
     struct natstr *natp;
     time_t now;
-    int page;
+    int heading, 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;
+    unsigned short sectors_taken[MAXNOC][MAXNOC];
     natid i, j;
-    s_char num[128];
-    s_char *verb;
+    int k, n, diff;
+    struct sectwon *sectwon;
+    char num[128];
+    char *verb;
 
-    if (!snxtitem(&nstr, EF_NEWS, "*"))
-       return RET_SYN;
-    memset(page_has_news, 0, sizeof(page_has_news));
+    if (!snxtitem(&nstr, EF_NEWS, "*", NULL))
+       return RET_SYN;
     memset(sectors_taken, 0, sizeof(sectors_taken));
-    (void)head();
     (void)time(&now);
     natp = getnatp(player->cnum);
     then = natp->nat_newstim;
-    /*
-     * Don't disclose events before contact.  Proper solution would be
-     * to timestamp the contact.  Cheesy approximatation: disable old
-     * news.
-     */
-    if (!opt_HIDDEN) {
-       if (player->argp[1] != 0 && isdigit(*player->argp[1])) {
-           delta = days(atoi(player->argp[1]));
-           then = now - delta;
+    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;
        }
+       delta = days(atoi(player->argp[1]));
+       then = now - delta;
     }
     natp->nat_newstim = now;
-/*     if (then < now - days(3))
-               then = now - days(3);
-*/
+    head();
     pr("\nThe details of Empire news since %s", ctime(&then));
-    while (nxtitem(&nstr, &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;
-    }
-    for (page = 1; page <= N_MAX_PAGE; page++) {
+
+    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;
-       pr("\n\t ===  %s  ===\n", page_headings[page]);
        snxtitem_rewind(&nstr);
        while (nxtitem(&nstr, &nws)) {
-           if (rpt[(int)nws.nws_vrb].r_newspage != page)
+           if (CANT_HAPPEN(nws.nws_vrb > N_MAX_VERB))
                continue;
            if (nws.nws_when < then)
                continue;
-           if (nws.nws_ntm == 0)
+           if (CANT_HAPPEN(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)))
+                   !(in_contact(player->cnum, nws.nws_ano) &&
+                     in_contact(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;
+           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);
        }
     }
-    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);
+
+    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++;
            }
        }
+    }
+
+    qsort(sectwon, n, sizeof(*sectwon), sectwon_cmp);
+
+    if (n) {
        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));
-                   }
-               }
-           }
+       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;
+    char *cp;
+    int i;
+    char buf[255];
+    char num[128];
+    char *ptr;
 
     cp = buf;
     sprintf(buf, "%-16.16s  ", ctime(&np->nws_when));
@@ -190,7 +192,7 @@ preport(register struct nwsstr *np)
     /*
      * vary the order of the printing of "%d times "
      */
-    if ((random() & 3) == 0 && np->nws_ntm > 1) {
+    if (roll0(4) == 0 && np->nws_ntm > 1) {
        sprintf(cp, "%s times ", ptr);
        cp += strlen(cp);
        np->nws_ntm = 1;
@@ -198,17 +200,13 @@ preport(register struct nwsstr *np)
     strcpy(cp, cname(np->nws_ano));
     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],
+    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 (*buf >= 'a' && *buf <= 'z')
-       *buf += 'A' - 'a';
     if (cp - buf > 80) {
        for (i = 80; --i > 60;)
            if (buf[i] == ' ')
@@ -221,3 +219,18 @@ preport(register struct nwsstr *np)
     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;
+}