root/games/warp/us.c
/* Header: us.c,v 7.0.1.3 87/01/13 17:13:21 lwall Exp */

/* Log: us.c,v
 * Revision 7.0.1.3  87/01/13  17:13:21  lwall
 * Partially fixed ^S behavior.  It now just ignores ^S.
 *
 * Revision 7.0.1.2  86/12/12  17:06:09  lwall
 * Baseline for net release.
 *
 * Revision 7.0.1.1  86/10/16  10:53:50  lwall
 * Added Damage.  Fixed random bugs.
 *
 * Revision 7.0  86/10/08  15:14:21  lwall
 * Split into separate files.  Added amoebas and pirates.
 *
 */

#include "EXTERN.h"
#include "warp.h"
#include "bang.h"
#include "object.h"
#include "play.h"
#include "sig.h"
#include "term.h"
#include "util.h"
#include "weapon.h"
#include "INTERN.h"
#include "us.h"

void
us_init(void)
{
    ;
}

void
do_direction(int dy, int dx)
{
    int decr;
    OBJECT *obj;

    if (status < 2) {
        if (cloaking) {
            char ch;

            cloaked = false;
            ch = (ent->energy >= 500?'E':'e');
            if (ch != ent->image) {
                setimage(ent, ch);
            }
        }
        decr = 5+abs(evely)+abs(evelx)+tractor*tractor;
        if (ent->energy >= decr) {
            ent->energy -= decr;
            if (tractor) {
                if (!damage || !damflag[NOTRACTORS]) {
                    if (!rand_mod(50)) {
                        damage++;
                        damflag[NOTRACTORS] = rand_mod(smarts+10)+2;
                    }
                    if (tract(ent,dy,dx,tractor)) {
                        evely += tractor*dy;
                        evelx += tractor*dx;
                    }
                }
            }
            else if (!damage ||
              (!entmode && !damflag[NOIMPULSE]) ||
              (entmode && !damflag[NOWARP]) ) {
                if (!rand_mod(30+500/(abs(evely)+abs(evelx)+1))) {
                    damage++;
                    damflag[entmode?NOWARP:NOIMPULSE] = rand_mod(smarts+10)+2;
                }
                evely += dy;
                evelx += dx;
            }
            if (inumthols &&
              (obj=occupant[(ent->posy+evely+YSIZE00)%YSIZE]
                           [(ent->posx+evelx+XSIZE00)%XSIZE] ) &&
              obj->type == Web)
                evely = evelx = 0;
        }
    }
    else if (status == 2) {
        decr = 500+abs(bvely)*5+abs(bvelx)*5+tractor*tractor*100;
        if (base->energy >= decr) {
            base->energy -= decr;
            if (tractor) {
                if (tract(base,dy,dx,tractor)) {
                    bvely += tractor*dy;
                    bvelx += tractor*dx;
                }
            }
            else {
                bvely += dy;
                bvelx += dx;
            }
            if (inumthols &&
              (obj=occupant[(base->posy+bvely+YSIZE00)%YSIZE]
                           [(base->posx+bvelx+XSIZE00)%XSIZE] ) &&
              obj->type == Web)
                bvely = bvelx = 0;
        }
    }
    tractor = 0;
}

void
ctrl_direction(int dy, int dx)
{
    if (status < 2) {
        if (cloaking) {
            char ch;

            cloaked = false;
            ch = (ent->energy >= 500?'E':'e');
            if (ch != ent->image) {
                setimage(ent, ch);
            }
        }
        if (!damage || !damflag[NOPHASERS]) {
            if (!rand_mod(200)) {
                damage++;
                damflag[NOPHASERS] = rand_mod(smarts+10)+2;
            }
            fire_phaser(ent, dy, dx);
        }
    }
    else if (status == 2)
        fire_phaser(base, dy, dx);
}

void
shift_direction(int dy, int dx)
{
    if (status < 2) {
        if (cloaking) {
            char ch;

            cloaked = false;
            ch = (ent->energy >= 500?'E':'e');
            if (ch != ent->image) {
                setimage(ent, ch);
            }
        }
        if (!damage || !damflag[NOTORPS]) {
            if (!rand_mod(300)) {
                damage++;
                damflag[NOTORPS] = rand_mod(smarts+10)+2;
            }
            fire_torp(ent, dy, dx);
        }
    }
    else if (status == 2)
        fire_torp(base, dy, dx);
}

void
get_commands(bool *done)
{
    static char ch[80];
    int i;
    int count;
    bool ctrla = false;
    char numdestructs = 0, numzaps = 0;

top:
    while ((count = read_nd(ch,(sizeof ch)))) {
        for (i=0; i<count; i++) {
            if (ch[i] == 'Q') {
                bombed_out = true;
                *done = true;
                keepgoing = false;
                return;
            }
            if (ch[i] == 'q' || ch[i] == BREAKCH || ch[i] == INTRCH) {
                int x;
                static char quest[] = "Do you wish to escape from reality? ";

                if (timer >= whenok) {
                    mvaddstr(12,22,quest);
                    do {
                        getcmd(&ch[i]);
                    } while (ch[i] != 'y' && ch[i] != 'n');
                    if (ch[i] == 'y') {
                        bombed_out = true;
                        *done = true;
                        return;
                    }
                    else {
                        for (x=11; x<=28; x++) {
                            mvaddch(12,x*2,
                                occupant[11][x]
                                   ? occupant[11][x]->image
                                   : numamoebas
                                      ? amb[11][x]
                                      : ' ');
                            addspace();
                        }
                        roundsleep(2);
                        whenok = timer + 10;
                        goto top;
                    }
                }
                else {
                    write(1,"\07",1);
                    goto top;
                }
            }
        }
        for (i=0; i<count; i++) {
            if (ctrla) {
                switch (ch[i]) {
                case '1': case 'b':
                    ctrl_direction(1, -1);
                    break;
                case '2': case 'j':
                    ctrl_direction(1, 0);
                    break;
                case '3': case 'n':
                    ctrl_direction(1, 1);
                    break;
                case '4': case 'h':
                    ctrl_direction(0, -1);
                    break;
                case '6': case 'l':
                    ctrl_direction(0, 1);
                    break;
                case '7': case 'y':
                    ctrl_direction(-1, -1);
                    break;
                case '8': case 'k':
                    ctrl_direction(-1, 0);
                    break;
                case '9': case 'u':
                    ctrl_direction(-1, 1);
                    break;
                case 'r':
                    rewrite();
                    roundsleep(3);
                    ctrla = false;
                    goto top;
                case 'w':
                    clear();
                    while (!input_pending())
                        sleep(1);
                    rewrite();
                    roundsleep(3);
                    ctrla = false;
                    goto top;
#ifdef SIGTSTP
                case 'z':
                    clear();
                    mytstp();
                    sleep(4);
                    ctrla = false;
                    goto top;
#endif
                default:
                    break;
                }
                ctrla = false;
            }
            else {
                switch (ch[i]) {
                case 'Z':
                    clear();
                    mytstp();
                    sleep(4);
                    goto top;
                case 'i':
                    if (ent && (!damage || !damflag[NOIMPULSE])) {
                        entmode = 0;
                        status = 0;
                    }
                    break;
                case 'w':
                    if (ent && (!damage || !damflag[NOWARP])) {
                        entmode = 1;
                        status = 1;
                    }
                    break;
                case 'p':
                    if (base) {
                        status = 2;
                    }
                    break;
                case 'o':
                    if (status < 2) {
                        if (base)
                            status = 2;
                    }
                    else if (status == 2) {
                        if (ent)
                            status = entmode;
                    }
                    break;
                case 'v':
                    if (ent) {
                        status = entmode;
                    }
                    cloaking=false;
                    cloaked=false;
                    break;
                case 'c':
                    if (ent) {
                        status = entmode;
                        if (ent->energy >= 250)
                            cloaking = true;
                    }
                    break;
                case 'z':
                    if (ent && (!damage || !damflag[NOZAPPER])) {
                        ++numzaps;
                        if (!rand_mod(100/numzaps)) {
                            damage++;
                            damflag[NOZAPPER] = rand_mod(smarts+10)+2;
                        }
                        if (nxtbang && bangm[nxtbang-1] < 0)
                            --nxtbang;  /* consolidate zaps */
                        make_blast(evely*2+ent->posy,evelx*2+ent->posx,
                            -5000000L, 3*numzaps);
                        ent->energy /= 2;
                    }
                    break;
                case 'D':
                    if (status < 2 && (!damage || !damflag[NODESTRUCT])) {
                        if (ent && !rand_mod(10)) {
                            damage++;
                            damflag[NODESTRUCT] = rand_mod(smarts+10)+2;
                        }
                        if (++numdestructs <= 2)
                            make_blast(evely*2+ent->posy,evelx*2+ent->posx,
                                15000L, 3);
                        ent->energy /= 4;
                    }
                    else if (status == 2) {
                        if (numdestructs)
                            base->energy = base->energy / 2;
                        if (++numdestructs <= 2)
                            make_blast(base->posy, base->posx, 15000L, 5);
                    }
                    break;
                case 'd':
                    if ((!damage || !damflag[NODESTRUCT]) && (base||ent)) {
                        OBJECT *obj;
                        int x, y;

                        if (ent && !rand_mod(200)) {
                            damage++;
                            damflag[NODESTRUCT] = rand_mod(smarts+10)+2;
                        }
                        for (obj = root.prev;
                          obj != &root;
                          obj = obj->prev) {
                            if (obj->image == '+') {
                                blast[y=(obj->posy+obj->vely+YSIZE00)%YSIZE]
                                     [x=(obj->posx+obj->velx+XSIZE00)%XSIZE]
                                     += 1;
                                yblasted[y] |= 1;
                                xblasted[x] |= 1;
                                blasted = true;
                                obj->mass = (massacre?3000:4000);
                            }
                        }
                    }
                    break;
                case 's':
                    if ((!damage || !damflag[NODESTRUCT]) && (base||ent)) {
                        OBJECT *obj;
                        if (ent && !rand_mod(200)) {
                            damage++;
                            damflag[NODESTRUCT] = rand_mod(smarts+10)+2;
                        }
                        for (obj = root.prev;
                          obj->type == Torp || obj->type == Web ||
                          obj->type == Star;
                          obj = obj->prev) {
                            if (obj->image == '+')
                                obj->vely = obj->velx = 0;
                        }
                    }
                    break;
                case '\001':
                    ctrla = true;
                    break;
                case '\002':
                case '\003':
                case '\004':
                case '\005':
                case '\006':
                case '\007':
                case '\010':
                case '\011':
                case '\012':
                case '\013':
                case '\014':
                case '\015':
                case '\016':
                case '\017':
                case '\020':
                case '\021':
                case '\022':
                case '\023':
                case '\024':
                case '\025':
                case '\026':
                case '\027':
                case '\030':
                case '\031':
                case '\032':
                    ch[i] += 96;
                    i--;
                    ctrla = true;
                    break;
                case '\033':
                    tractor = 0;
                    break;
                case 'a':
                    tractor++;
                    break;
                case 'r':
                    tractor--;
                    break;
                case '1': case 'b':
                    do_direction(1,-1);
                    break;
                case '2': case 'j':
                    do_direction(1,0);
                    break;
                case '3': case 'n':
                    do_direction(1,1);
                    break;
                case '4': case 'h':
                    do_direction(0,-1);
                    break;
                case '6': case 'l':
                    do_direction(0,1);
                    break;
                case '7': case 'y':
                    do_direction(-1,-1);
                    break;
                case '8': case 'k':
                    do_direction(-1,0);
                    break;
                case '9': case 'u':
                    do_direction(-1,1);
                    break;
                case '0': case 'S':
                    if (status < 2) {
                        evely = 0;
                        evelx = 0;
                    }
                    break;
                case '-':
                    if (status < 2 && ent->energy >= 10) {
                        evely *= -1;
                        evelx *= -1;
                        ent->energy -= 10;
                    }
                    break;
                case '%': case '\177': case '_':
                    shift_direction(0, -1);
                    shift_direction(0, 1);
                    shift_direction(-1, 0);
                    shift_direction(1, 0);
                    shift_direction(-1, -1);
                    shift_direction(-1, 1);
                    shift_direction(1, -1);
                    shift_direction(1, 1);
                    break;
                case '!': case 'B':
                    shift_direction(1, -1);
                    break;
                case '@': case 'J':
                    shift_direction(1, 0);
                    break;
                case '#': case 'N':
                    shift_direction(1, 1);
                    break;
                case '$': case 'H':
                    shift_direction(0, -1);
                    break;
                case '^': case 'L':
                    shift_direction(0, 1);
                    break;
                case '&': case 'Y':
                    shift_direction(-1, -1);
                    break;
                case '*': case 'K':
                    shift_direction(-1, 0);
                    break;
                case '(': case 'U':
                    shift_direction(-1, 1);
                    break;
                case '?':
                    helper();
                    roundsleep(3);
                    goto top;
                default:
                    break;
                }
            }
        }
    }
}