/*      $NetBSD: pl_5.c,v 1.26 2019/02/03 03:19:25 mrg Exp $    */

/*
* Copyright (c) 1983, 1993
*      The Regents of the University of California.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pl_5.c      8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: pl_5.c,v 1.26 2019/02/03 03:19:25 mrg Exp $");
#endif
#endif /* not lint */

#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include "extern.h"
#include "player.h"
#include "display.h"

#define turnfirst(x) (*x == 'r' || *x == 'l')

static void parties(struct ship *, int *, int, int);

void
acceptmove(void)
{
       int ta;
       int ma;
       bool af;
       bool moved = false;
       int vma, dir;
       char promptstr[60];
       char buf[60], last = '\0';
       char *p;

       if (!mc->crew3 || snagged(ms) || !windspeed) {
               Msg("Unable to move");
               return;
       }

       ta = maxturns(ms, &af);
       ma = maxmove(ms, mf->dir, 0);
       snprintf(promptstr, sizeof(promptstr),
               "move (%d,%c%d): ", ma, af ? '\'' : ' ', ta);
       sgetstr(promptstr, buf, sizeof buf);
       dir = mf->dir;
       vma = ma;
       for (p = buf; *p; p++)
               switch (*p) {
               case 'l':
                       dir -= 2;
                       /* FALLTHROUGH */
               case 'r':
                       if (++dir == 0)
                               dir = 8;
                       else if (dir == 9)
                               dir = 1;
                       if (last == 't') {
                               Msg("Ship can't turn that fast.");
                               *p-- = '\0';
                       }
                       last = 't';
                       ma--;
                       ta--;
                       vma = min(ma, maxmove(ms, dir, 0));
                       if ((ta < 0 && moved) || (vma < 0 && moved))
                               *p-- = '\0';
                       break;
               case 'b':
                       ma--;
                       vma--;
                       last = 'b';
                       if ((ta < 0 && moved) || (vma < 0 && moved))
                               *p-- = '\0';
                       break;
               case '0':
               case 'd':
                       *p-- = '\0';
                       break;
               case '\n':
                       *p-- = '\0';
                       break;
               case '1': case '2': case '3': case '4':
               case '5': case '6': case '7':
                       if (last == '0') {
                               Msg("Can't move that fast.");
                               *p-- = '\0';
                       }
                       last = '0';
                       moved = true;
                       ma -= *p - '0';
                       vma -= *p - '0';
                       if ((ta < 0 && moved) || (vma < 0 && moved))
                               *p-- = '\0';
                       break;
               default:
                       if (!isspace((unsigned char)*p)) {
                               Msg("Input error.");
                               *p-- = '\0';
                       }
               }
       if ((ta < 0 && moved) || (vma < 0 && moved)
           || (af && turnfirst(buf) && moved)) {
               Msg("Movement error.");
               if (ta < 0 && moved) {
                       if (mf->FS == 1) {
                               send_fs(ms, 0);
                               Msg("No hands to set full sails.");
                       }
               } else if (ma >= 0)
                       buf[1] = '\0';
       }
       if (af && !moved) {
               if (mf->FS == 1) {
                       send_fs(ms, 0);
                       Msg("No hands to set full sails.");
               }
       }
       if (*buf)
               strlcpy(movebuf, buf, sizeof(movebuf));
       else
               strlcpy(movebuf, "d", sizeof(movebuf));
       send_move(ms, movebuf);
       Msg("Helm: %s.", movebuf);
}

void
acceptboard(void)
{
       struct ship *sp;
       int n;
       int crew[3];
       int men = 0;
       char c;

       crew[0] = mc->crew1;
       crew[1] = mc->crew2;
       crew[2] = mc->crew3;
       for (n = 0; n < NBP; n++) {
               if (mf->OBP[n].turnsent)
                           men += mf->OBP[n].mensent;
       }
       for (n = 0; n < NBP; n++) {
               if (mf->DBP[n].turnsent)
                           men += mf->DBP[n].mensent;
       }
       if (men) {
               crew[0] = men/100 ? 0 : crew[0] != 0;
               crew[1] = (men%100)/10 ? 0 : crew[1] != 0;
               crew[2] = men%10 ? 0 : crew[2] != 0;
       } else {
               crew[0] = crew[0] != 0;
               crew[1] = crew[1] != 0;
               crew[2] = crew[2] != 0;
       }
       foreachship(sp) {
               if (sp == ms || sp->file->dir == 0 || range(ms, sp) > 1)
                       continue;
               if (ms->nationality == capship(sp)->nationality)
                       continue;
               if (meleeing(ms, sp) && crew[2]) {
                       c = sgetch("How many more to board the $$? ",
                               sp, 1);
                       parties(sp, crew, 0, c);
               } else if ((fouled2(ms, sp) || grappled2(ms, sp)) && crew[2]) {
                       c = sgetch("Crew sections to board the $$ (3 max) ?",
                                  sp, 1);
                       parties(sp, crew, 0, c);
               }
       }
       if (crew[2]) {
               c = sgetch("How many sections to repel boarders? ",
                       (struct ship *)0, 1);
               parties(ms, crew, 1, c);
       }
}

static void
parties(struct ship *to, int *crew, int isdefense, int buf)
{
       int k, j, men;
       struct BP *ptr;
       int temp[3];

       for (k = 0; k < 3; k++)
               temp[k] = crew[k];
       if (isdigit(buf)) {
               ptr = isdefense ? to->file->DBP : to->file->OBP;
               for (j = 0; j < NBP && ptr[j].turnsent; j++)
                       ;
               if (j < NBP && !ptr[j].turnsent && buf > '0') {
                       men = 0;
                       for (k = 0; k < 3 && buf > '0'; k++) {
                               men += crew[k]
                                       * (k == 0 ? 100 : (k == 1 ? 10 : 1));
                               crew[k] = 0;
                               if (men)
                                       buf--;
                       }
                       if (buf > '0')
                               Msg("Sending all crew sections.");
                       if (isdefense) {
                               send_dbp(ms, j, turn, to->file->index, men);
                       } else {
                               send_obp(ms, j, turn, to->file->index, men);
                       }
                       if (isdefense) {
                               for (k=0; k < NBP; k++)
                                       display_set_dbp(k,
                                                        temp[k] && !crew[k]);
                               makemsg(ms, "repelling boarders");
                       } else {
                               for (k=0; k < NBP; k++)
                                       display_set_obp(k,
                                                        temp[k] && !crew[k]);
                               makesignal(ms, "boarding the $$", to);
                       }
               } else
                       Msg("Sending no crew sections.");
       }
}