|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 31675 (0x7bbb) Types: TextFile Names: »play.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Spacewar/play.c«
/* * Spacewar - routine to execute user playing commands * * Copyright 1985 obo Systems, Inc. * Copyright 1985 Dan Rosenblatt */ #ifndef VMS #include <sys/types.h> #include <dbm.h> #else /* BSD SYSIII SYSV */ #include <types.h> #include "dbm.h" #endif /* VMS */ #include "spacewar.h" #include "universe.h" #include "login.h" #include "sys.h" #include "crft.h" #include "flds.h" #include "build.h" #include "aln.h" #include "obj.h" #include "torp.h" #include "ucmd.h" extern VOID fixdir(); extern double vdist(),vlen(); static int okdir(); static VOID fixaf(); static struct { char *pc_cmd; char pc_mincmdl; } pcmds[] = { /* 0 */ {"erase",1}, {"angle",2}, {"right",2}, {"left",3}, /* 4 */ {"up",2}, {"down",3}, {"vdist",1}, {"home",1}, /* 8 */ {"unhome",2}, {"faceforward",2},{"autopilot",2},{"shields",2}, /* 12 */{"stopthrust",2},{"thrust",2}, {"warp",2}, {"damage",3}, /* 16 */{"leave",3}, {"dock",3}, {"radio",2}, {"who",2}, /* 20 */{"report",3}, {"phasers",1}, {"torpedo",2}, {"fix",2}, /* 24 */{"-",1}, {"sensors",2}, {"lockon",2}, {"redraw",3} }; VOID play(plogin) register struct login *plogin; { int i,j; long l,m; register struct crft *pcrft; struct torp *ptorp; register struct universe *puniv; struct login *plgn; char buf[128]; double ftmp,tmpvec[3],tmpvec2[3]; struct ucmdkey getuckey; datum dbmkey,dbmdata; char ucargs[9][20+1],inuc=0; dsplcmnt tmpdspl; #ifdef DEBUG DBG("play(#%d/%s)\n",plogin-loginlst,plogin->ln_name); #endif /* if not yet placed into the universe, try doing so */ if (!plogin->ln_play.ip_ptr) { if (plinit(plogin)) { pcrft = plogin->ln_play.ip_ptr->uv_ptr.uv_crft; sprintf(plogin->ln_input,"Wlcm abrd the %s captain %s", plogin->ln_crft,plogin->ln_name); i = 0; /* force erase, not redraw */ goto erase; } #ifdef DEBUG VDBG("play return\n"); #endif return; } pcrft = plogin->ln_play.ip_ptr->uv_ptr.uv_crft; /* move last command indicator */ douc: output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_LSTCMD," "); if (++pcrft->cr_lcmd >= flds[FLD_LSTCMD].f_maxg) pcrft->cr_lcmd = 0; output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_LSTCMD,"#"); /* find command */ for (i=sizeof(pcmds)/sizeof(pcmds[0]);i-- > 0;) if (!strncmp(plogin->ln_input,pcmds[i].pc_cmd,pcmds[i].pc_mincmdl)) break; if (i < 0) { badinp: sprintf(buf,"??? %s",plogin->ln_input); badinp2: output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_COMMAND,buf); inuc = 0; goto done; } switch(i) { /*********/ /* erase */ /*********/ case 0: erase: /* erase screen, redraw background */ output(plogin,'E',0,0); redraw: background(pcrft); /* indicate all fields changed so they get re-displayed */ for (j=0;j < sizeof(pcrft->cr_chng);++j) pcrft->cr_chng[j] = ~0; pcrft->cr_scrn[0][0] = NULL; if (i == 0) { /* redraw instead of erase */ /* reset last report and command markers */ pcrft->cr_lrpt = 0; pcrft->cr_lcmd = 0; /* restore last command marker */ output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_LSTCMD,"#"); } break; /*********/ /* angle */ /*********/ case 1: if (sscanf(plogin->ln_input,"%*s %lf",&ftmp) != 1) goto badinp; /* must be 0<ang<=180 (or 360 if privileged) */ if (ftmp <= 0. || SUB(ftmp,360.) > 0. || (SUB(ftmp,180.) > 0 && !pcrft->cr_plvl)) goto badinp; pcrft->cr_vang = MUL(ftmp,DEGTORAD); biton(pcrft->cr_chng,BIT_VANGL); /* recompute viewing distance if not privileged */ if (!pcrft->cr_plvl) { pcrft->cr_vdst = INT(DIV(VANGVDST,SQUARE(pcrft->cr_vang))); biton(pcrft->cr_chng,BIT_VDIST); } break; /*********/ /* right */ /*********/ case 2: if (!okdir(plogin,pcrft,&ftmp)) goto badinp; pcrft->cr_dir[1] = SUB(pcrft->cr_dir[1],ftmp); biton(pcrft->cr_chng,BIT_DIR1); fixdir(pcrft); fixaf(pcrft); break; /********/ /* left */ /********/ case 3: if (!okdir(plogin,pcrft,&ftmp)) goto badinp; pcrft->cr_dir[1] = ADD(pcrft->cr_dir[1],ftmp); biton(pcrft->cr_chng,BIT_DIR1); fixdir(pcrft); fixaf(pcrft); break; /******/ /* up */ /******/ case 4: if (!okdir(plogin,pcrft,&ftmp)) goto badinp; pcrft->cr_dir[2] = SUB(pcrft->cr_dir[2],ftmp); biton(pcrft->cr_chng,BIT_DIR2); fixdir(pcrft); fixaf(pcrft); break; /********/ /* down */ /********/ case 5: if (!okdir(plogin,pcrft,&ftmp)) goto badinp; pcrft->cr_dir[2] = ADD(pcrft->cr_dir[2],ftmp); biton(pcrft->cr_chng,BIT_DIR2); fixdir(pcrft); fixaf(pcrft); break; /**********************/ /* vdist (privileged) */ /**********************/ case 6: if (!pcrft->cr_plvl) goto badinp; if (sscanf(plogin->ln_input,"%*s %ld",&pcrft->cr_vdst) != 1) goto badinp; biton(pcrft->cr_chng,BIT_VDIST); break; /********/ /* home */ /********/ case 7: if (sscanf(plogin->ln_input,"%*s %d",&i) != 1) goto badinp; if (i < 1 || i > MHOM) goto badinp; i -= 1; /* must be autopiloted on something */ if (!pcrft->cr_auto.ip_ptr) { sprintf(buf,"%.22s - not autopiloted",plogin->ln_input); goto badinp2; } pcrft->cr_hom[i].ip_ptr = pcrft->cr_auto.ip_ptr; /*pcrft->cr_hdst[i] = INT(vdist(pcrft->cr_pstn, pcrft->cr_auto.ip_ptr->uv_pstn));*/ tmpdspl = vdisp(pcrft->cr_univ.ip_ptr,pcrft->cr_auto.ip_ptr,'d'); pcrft->cr_hdst[i] = INT(tmpdspl.dst); biton(pcrft->cr_chng,BIT_HOMCHAN+i); break; /**********/ /* unhome */ /**********/ case 8: if (sscanf(plogin->ln_input,"%*s %d",&i) != 1) goto badinp; if (i < 1 || i > MHOM) goto badinp; i -= 1; /* must be homed in */ if (!pcrft->cr_hom[i].ip_ptr) { sprintf(buf,"%.25s - not homed in",plogin->ln_input); goto badinp2; } pcrft->cr_hom[i].ip_ptr = NULL; pcrft->cr_hdst[i] = NULL; biton(pcrft->cr_chng,BIT_HOMCHAN+i); break; /***************/ /* faceforward */ /***************/ case 9: if (vlen(pcrft->cr_vel) == 0.) { sprintf(buf,"%.27s - not moving",plogin->ln_input); goto badinp2; } pcrft->cr_ffwd = 1; pcrft->cr_auto.ip_ptr = NULL; rttosp(pcrft->cr_vel,pcrft->cr_dir); biton(pcrft->cr_chng,BIT_AUTOFFWD); biton(pcrft->cr_chng,BIT_DIR1); biton(pcrft->cr_chng,BIT_DIR2); fixdir(pcrft); break; /*************/ /* autopilot */ /*************/ case 10: if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */ i = 0; else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1) goto badinp; /* to a specific homing channel; privileges allow */ /* a negative # for absolute universe objects */ if (i) { if (i > MHOM || (i < 1 && !pcrft->cr_plvl)) goto badinp; if (i < 1) { if ((i=(-i-1)) >= MAXUNIVERSE || !univlst[i].uv_type) goto badinp; else pcrft->cr_auto.ip_ptr = univlst + i; } else { i -= 1; if (!pcrft->cr_hom[i].ip_ptr) { sprintf(buf,"%.25s - not homed in",plogin->ln_input); goto badinp2; } pcrft->cr_auto.ip_ptr = pcrft->cr_hom[i].ip_ptr; } /* if docked, shift to docked object (because docking */ /* loses autos, docks, and torps but not homing) */ puniv = pcrft->cr_auto.ip_ptr; if (puniv->uv_type == 'P' && puniv->uv_ptr.uv_crft->cr_dock.ip_ptr) pcrft->cr_auto.ip_ptr = puniv->uv_ptr.uv_crft->cr_dock.ip_ptr; /* but not to player's own craft */ if (pcrft->cr_auto.ip_ptr == plogin->ln_play.ip_ptr) pcrft->cr_auto.ip_ptr = NULL; /* to closest to center/closest object */ } else { doauto: /* use viewing distance and smaller of */ /* 5 degrees, half of viewing angle */ ftmp = MUL(10.,DEGTORAD); if (SUB(pcrft->cr_vang,ftmp) < 0.) ftmp = pcrft->cr_vang; ftmp = DIV(ftmp,2.); l = pcrft->cr_vdst; pcrft->cr_auto.ip_ptr = NULL; /* select based on closest to center/closest */ for (puniv = univlst+MAXUNIVERSE;puniv-- > univlst;) { if (!puniv->uv_type) continue; if (puniv == plogin->ln_play.ip_ptr) continue; /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/ tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v'); vecmul(/*tmpvec*/tmpdspl.vec,pcrft->cr_rmat,tmpvec); rttosp(tmpvec,tmpvec); m = INT(tmpvec[0]); if ((tmpvec[2] == ftmp && m <= l) || (SUB(tmpvec[2],ftmp) <= 0. && m <= pcrft->cr_vdst)) { pcrft->cr_auto.ip_ptr = puniv; ftmp = tmpvec[2]; l = m; } } } biton(pcrft->cr_chng,BIT_AUTOFFWD); if (!pcrft->cr_auto.ip_ptr) { sprintf(buf,"%.24s - nothing there",plogin->ln_input); goto badinp2; } else { pcrft->cr_ffwd = NULL; /*vdiff(pcrft->cr_auto.ip_ptr->uv_pstn,pcrft->cr_pstn, pcrft->cr_dir);*/ tmpdspl = vdisp(pcrft->cr_auto.ip_ptr,pcrft->cr_univ.ip_ptr,'v'); rttosp(/*pcrft->cr_dir*/tmpdspl.vec,pcrft->cr_dir); biton(pcrft->cr_chng,BIT_DIR1); biton(pcrft->cr_chng,BIT_DIR2); fixdir(pcrft); } break; /***********/ /* shields */ /***********/ case 11: if (!pcrft->cr_sys[SHIELDS].s_cap) { sprintf(buf,"%.27s - no shields",plogin->ln_input); goto badinp2; } if (sscanf(plogin->ln_input,"%*s %d",&i) != 1) goto badinp; /* 0<=arg<=100 */ if (i < 0 || i > 100) goto badinp; pcrft->cr_sys[SHIELDS].s_lvl = i; biton(pcrft->cr_chng,BIT_SLEVEL+SHIELDS*flds[FLD_SLEVEL].f_grpw); break; /**************/ /* stopthrust */ /**************/ case 12: if (!pcrft->cr_sys[ROCKETS].s_cap) { sprintf(buf,"%.27s - no rockets",plogin->ln_input); goto badinp2; } if (vlen(pcrft->cr_thr) == 0.) { sprintf(buf,"%.20s - no pending thrust",plogin->ln_input); goto badinp2; } vinit(pcrft->cr_thr); break; /**********/ /* thrust */ /**********/ case 13: if (!pcrft->cr_sys[ROCKETS].s_cap) { sprintf(buf,"%.27s - no rockets",plogin->ln_input); goto badinp2; } if (!pcrft->cr_sys[ROCKETS].s_lvl) { sprintf(buf,"%.30s - no fuel",plogin->ln_input); goto badinp2; } vinit(tmpvec); if ((i=sscanf(plogin->ln_input,"%*s %lf %lf %lf %lf%c",&ftmp, tmpvec+0,tmpvec+1,tmpvec+2,&j)) < 1 || i > 4) goto badinp; /* first number is thrust in direction pointed */ /* others are cartesian components */ pcrft->cr_dir[0] = ftmp; sptort(pcrft->cr_dir,tmpvec2); for (i=0;i<3;++i) pcrft->cr_thr[i] = ADD(pcrft->cr_thr[i],ADD(tmpvec[i],tmpvec2[i])); /* turn off docking */ if (puniv=pcrft->cr_dock.ip_ptr) { /* fix other player's screen if docked with another craft */ if (puniv->uv_type == 'P') puniv->uv_ptr.uv_crft->cr_scrn[7][15] = '?'; /* place craft away from docked object */ /* according to direction of thrust */ rttosp(pcrft->cr_thr,tmpvec); tmpvec[0] = ADD(MUL(FLOAT(puniv->uv_rad+1),2.),1.); sptort(tmpvec,tmpvec); for (i=0;i<3;++i) pcrft->cr_pstn[i] = ADD(pcrft->cr_pstn[i],tmpvec[i]); vchngd(pcrft->cr_univ.ip_ptr); pcrft->cr_dock.ip_ptr = NULL; pcrft->cr_scrn[7][15] = '?'; } break; /********/ /* warp */ /********/ case 14: if (!pcrft->cr_sys[WARP].s_cap) { sprintf(buf,"%.30s - no warp",plogin->ln_input); goto badinp2; } if (sscanf(plogin->ln_input,"%*s %lf",&ftmp) != 1 || ftmp == 0.) goto badinp; ftmp = MUL(ftmp,1000.); /* check energy required */ l = 500L + 15L * INT(SQRT((ftmp < 0.) ? NEG(ftmp) : ftmp)); if (l > pcrft->cr_sys[WARP].s_lvl) { sprintf(buf,"%.18s - need at least %ld",plogin->ln_input,l); goto badinp2; } /* reduce warp energy level */ pcrft->cr_sys[WARP].s_lvl -= l; biton(pcrft->cr_chng,BIT_SLEVEL+WARP*flds[FLD_SLEVEL].f_grpw); /* new position; % and %dmg affect accuracy */ pcrft->cr_dir[0] = ftmp; sptort(pcrft->cr_dir,tmpvec); ftmp = DIV(MUL(ftmp,FLOAT(100-pcrft->cr_sys[WARP].s_pct+ pcrft->cr_sys[WARP].s_dmg)),100.); for (i=0;i<3;++i) pcrft->cr_pstn[i] = ADD(pcrft->cr_pstn[i], ADD(tmpvec[i],MUL(ftmp,DIV(FLOAT(RANDOM(200)-100),100.)))); vchngd(pcrft->cr_univ.ip_ptr); biton(pcrft->cr_chng,BIT_PN1); biton(pcrft->cr_chng,BIT_PN2); biton(pcrft->cr_chng,BIT_PN3); /* turn off auto/dock for this and other crafts on this craft */ if (pcrft->cr_dock.ip_ptr) { pcrft->cr_dock.ip_ptr = NULL; pcrft->cr_scrn[7][15] = '?'; } if (pcrft->cr_auto.ip_ptr) { pcrft->cr_auto.ip_ptr = NULL; biton(pcrft->cr_chng,BIT_AUTOFFWD); } for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) { register struct crft *pcrft2; if (puniv->uv_type != 'P') continue; pcrft2 = puniv->uv_ptr.uv_crft; if (pcrft2->cr_dock.ip_ptr == plogin->ln_play.ip_ptr) { pcrft2->cr_dock.ip_ptr = NULL; pcrft2->cr_scrn[7][15] = '?'; pcrft->cr_scrn[7][15] = '?'; } if (pcrft2->cr_auto.ip_ptr == plogin->ln_play.ip_ptr) { pcrft2->cr_auto.ip_ptr = NULL; biton(pcrft2->cr_chng,BIT_AUTOFFWD); } } break; /***********************/ /* damage (privileged) */ /***********************/ case 15: if (!pcrft->cr_plvl) goto badinp; if (sscanf(plogin->ln_input,"%*s %d %d",&i,&j) != 2) goto badinp; /* must be a valid, existing system */ if (i < 0 || i >= MSYS || !pcrft->cr_sys[i].s_cap) goto badinp; /* 0<=%dmg<=100 */ if (j < 0 || j > 100) goto badinp; pcrft->cr_sys[i].s_dmg = j; if (i == HULL) plogin->ln_play.ip_ptr->uv_mass = j; biton(pcrft->cr_chng,BIT_SDMG+i*flds[FLD_SDMG].f_grpw); break; /*********/ /* leave */ /*********/ case 16: /* only if privileged or nothing bad */ /* nearby or docked with an object */ if (pcrft->cr_plvl || pcrft->cr_sens[1] == 0 || ((puniv=pcrft->cr_dock.ip_ptr) && puniv->uv_type == 'O')) { output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_COMMAND, plogin->ln_input); unplay(plogin); output(plogin,'E',0,0); output(plogin,'C',0,PROMPT); output(plogin,0,0,0); return; } sprintf(buf,"%.14s - not docked and BAD != 0",plogin->ln_input); goto badinp2; /********/ /* dock */ /********/ case 17: /* find the closest, dock'able object */ l = 10000L; pcrft->cr_dock.ip_ptr = NULL; for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) { double *pvel; switch(puniv->uv_type) { case 0: continue; case 'P': if (puniv == plogin->ln_play.ip_ptr) continue; if (puniv->uv_ptr.uv_crft->cr_dock.ip_ptr) continue; pvel = puniv->uv_ptr.uv_crft->cr_vel; break; case 'T': pvel = puniv->uv_ptr.uv_torp->tp_vel; break; case 'A': pvel = puniv->uv_ptr.uv_aln->al_vel; break; case 'O': if (puniv->uv_pctr == ' ' || puniv->uv_pctr == '*') continue; pvel = puniv->uv_ptr.uv_obj->oj_vel; break; } /*m = INT(vdist(pcrft->cr_pstn,puniv->uv_pstn));*/ tmpdspl = vdisp(pcrft->cr_univ.ip_ptr,puniv,'d'); m = INT(tmpdspl.dst); if (m < l && m <= 5*(puniv->uv_rad+1)) { pcrft->cr_dock.ip_ptr = puniv; l = m; vcopy(tmpvec,pvel); } } if (!pcrft->cr_dock.ip_ptr) { sprintf(buf,"%.25s - too far away",plogin->ln_input); goto badinp2; } puniv = pcrft->cr_dock.ip_ptr; /* must also be within range next movement iteration */ for (i=0;i<3;++i) tmpvec[i] = SUB(ADD(puniv->uv_pstn[i],tmpvec[i]), ADD(pcrft->cr_pstn[i],pcrft->cr_vel[i])); if (INT(vlen(tmpvec)) > 5*(puniv->uv_rad+1)) { sprintf(buf,"%.22s - moving too fast",plogin->ln_input); pcrft->cr_dock.ip_ptr = NULL; goto badinp2; } /* dock */ pcrft->cr_scrn[7][15] = '?'; vinit(pcrft->cr_thr); vcopy(pcrft->cr_pstn,puniv->uv_pstn); vchngd(pcrft->cr_univ.ip_ptr); biton(pcrft->cr_chng,BIT_PN1); biton(pcrft->cr_chng,BIT_PN2); biton(pcrft->cr_chng,BIT_PN3); output(plogin,0,0,0); /* fix autopilots, docks, torp aim, alien attack */ for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) { register struct crft *pcrft2; struct aln *paln; switch(puniv->uv_type) { case 0: continue; case 'P': pcrft2 = puniv->uv_ptr.uv_crft; if (pcrft2->cr_auto.ip_ptr == plogin->ln_play.ip_ptr) { /* shift autopilot to item docked with */ /* if its not an object and not itself */ if (pcrft->cr_dock.ip_ptr->uv_type != 'O' && pcrft->cr_dock.ip_ptr != puniv) pcrft2->cr_auto.ip_ptr = pcrft->cr_dock.ip_ptr; /* its an object or itself - lose autopilot */ else pcrft2->cr_auto.ip_ptr = NULL; biton(pcrft2->cr_chng,BIT_AUTOFFWD); pcrft2->cr_scrn[7][15] = '?'; } if (pcrft2->cr_dock.ip_ptr == plogin->ln_play.ip_ptr) { /* shift dock to item docked */ /* with if its an object */ if (pcrft->cr_dock.ip_ptr->uv_type == 'O') pcrft2->cr_dock.ip_ptr = pcrft->cr_dock.ip_ptr; else pcrft2->cr_dock.ip_ptr = NULL; pcrft2->cr_scrn[7][15] = '?'; } break; case 'T': ptorp = puniv->uv_ptr.uv_torp; if (ptorp->tp_aim.ip_ptr == plogin->ln_play.ip_ptr && pcrft->cr_dock.ip_ptr->uv_type == 'O' && ptorp->tp_fby.ip_ptr && ptorp->tp_fby.ip_ptr->uv_type == 'P') { pcrft2 = ptorp->tp_fby.ip_ptr->uv_ptr.uv_crft; output(pcrft2->cr_lgn,'B',0,0); setrpt(pcrft2); rpt(pcrft2,"Torpedo missed - target docked"); fnshrpt(pcrft2,1); remove(ptorp->tp_univ); } break; case 'A': paln = puniv->uv_ptr.uv_aln; if (paln->al_atck.ip_ptr == plogin->ln_play.ip_ptr && (pcrft->cr_dock.ip_ptr->uv_type == 'O' || pcrft->cr_dock.ip_ptr == puniv)) { paln->al_atck.ip_ptr = NULL; } break; } } break; /*********/ /* radio */ /*********/ case 18: if (sscanf(plogin->ln_input,"%*s %[^\n]",buf) != 1) goto badinp; output(pcrft->cr_lgn,0,0,0); /* similar to autopilot */ ftmp = MUL(10.,DEGTORAD); if (SUB(pcrft->cr_vang,ftmp) < 0.) ftmp = pcrft->cr_vang; ftmp = DIV(ftmp,2.); for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) { if (puniv->uv_type != 'P') continue; if (puniv->uv_ptr.uv_crft == pcrft) continue; /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/ tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v'); vecmul(/*tmpvec*/tmpdspl.vec,pcrft->cr_rmat,tmpvec); rttosp(tmpvec,tmpvec); if (SUB(tmpvec[2],ftmp) <= 0.) { char buf2[40+1]; plgn = puniv->uv_ptr.uv_crft->cr_lgn; output(plgn,'B',0,0); output(plgn,'H',FLD_RADIO,buf); /*vdiff(pcrft->cr_pstn,puniv->uv_pstn,tmpvec);*/ tmpdspl = vdisp(pcrft->cr_univ.ip_ptr,puniv,'v'); rttosp(/*tmpvec*/tmpdspl.vec,tmpvec); setrpt(puniv->uv_ptr.uv_crft); sprintf(buf2,"Radio @%ld %.1f %.1f",INT(tmpvec[0]), DIV(tmpvec[1],DEGTORAD),DIV(tmpvec[2],DEGTORAD)); rpt(puniv->uv_ptr.uv_crft,buf2); fnshrpt(puniv->uv_ptr.uv_crft,1); } } break; /*******/ /* who */ /*******/ case 19: if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */ i = 0; else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1 || i < 0) goto badinp; i *= flds[FLD_REPORT].f_maxg; /* skip display group count */ setrpt(pcrft); *buf = NULL; for (plgn=loginlst+MAXLOGIN;plgn-- > loginlst;) { if (!plgn->ln_play.ip_ptr) continue; if (i-- > 0) continue; if (strlen(buf) + strlen(plgn->ln_name) + strlen(plgn->ln_crft) + 5 > flds[FLD_REPORT].f_len) { rpt(pcrft,buf); *buf = NULL; } sprintf(buf+strlen(buf),"%s/%s(%c) ",plgn->ln_name, plgn->ln_crft,plgn->ln_play.ip_ptr->uv_pctr); } rpt(pcrft,buf); fnshrpt(pcrft,0); break; /**********/ /* report */ /**********/ case 20: if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */ i = 0; else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1 || i < 0) goto badinp; i *= flds[FLD_REPORT].f_maxg; /* skip display group count */ setrpt(pcrft); /* almost identical to view() */ for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) { if (!puniv->uv_type) continue; if (puniv->uv_ptr.uv_crft == pcrft) continue; /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/ tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v'); vecmul(/*tmpvec*/tmpdspl.vec,pcrft->cr_rmat,tmpvec); rttosp(tmpvec,tmpvec); ftmp = DIV(pcrft->cr_vang,2.); if (SUB(ftmp,tmpvec[2]) >= 0. && (l=INT(tmpvec[0])) <= pcrft->cr_vdst) { if (i-- > 0) continue; tmpvec[0] = DIV(tmpvec[2],ftmp); tmpvec[2] = DIV(PI,2.); sptort(tmpvec,tmpvec); /* common characteristics */ sprintf(buf,"%ld,%ld(%c)@%ld",-INT(MUL(tmpvec[1],7.)), INT(MUL(tmpvec[0],15.)),puniv->uv_pctr,l); /* individual characteristics */ switch(puniv->uv_type) { case 'O': sprintf(buf+strlen(buf)," r=%d m=%ld", puniv->uv_rad,puniv->uv_mass); break; case 'P': plgn = puniv->uv_ptr.uv_crft->cr_lgn; sprintf(buf+strlen(buf)," %s/%s h%ld s%d", plgn->ln_name,plgn->ln_crft,puniv->uv_mass, puniv->uv_ptr.uv_crft->cr_sys[SHIELDS].s_lvl); break; case 'T': sprintf(buf+strlen(buf)," h%ld",puniv->uv_mass); break; case 'A': sprintf(buf+strlen(buf)," h%ld s%d", puniv->uv_mass, puniv->uv_ptr.uv_aln->al_sys[SHIELDS].s_lvl); break; } /* indicate auto'd, dock'd, or home'd */ l = 0; if (pcrft->cr_auto.ip_ptr == puniv) { if (!l) strcat(buf," ("); l = 1; strcat(buf,"A"); } if (pcrft->cr_dock.ip_ptr == puniv) { if (!l) strcat(buf," ("); l = 1; strcat(buf,"D"); } for (j=0;j<MHOM;++j) if (pcrft->cr_hom[j].ip_ptr == puniv) { if (!l) strcat(buf," ("); l = 1; sprintf(buf+strlen(buf),"%d",j+1); } if (l) strcat(buf,")"); rpt(pcrft,buf); } } fnshrpt(pcrft,0); break; /***********/ /* phasers */ /***********/ case 21: if (!pcrft->cr_sys[PHASERS].s_cap) { sprintf(buf,"%.27s - no phasers",plogin->ln_input); goto badinp2; } if (sscanf(plogin->ln_input,"%*s %d",&i) != 1) goto badinp; /* 1<=arg<=1000 */ if (i < 1 || i > 1000) goto badinp; /* check if conditions allow phasers */ if (pcrft->cr_dock.ip_ptr) { sprintf(buf,"%.21s - not while docked",plogin->ln_input); goto badinp2; } puniv = pcrft->cr_auto.ip_ptr; if (!puniv || puniv->uv_type == 'O') { sprintf(buf,"%.19s - nothing to fire at",plogin->ln_input); goto badinp2; } if (inuc) { sprintf(buf,"%.24s - not in '-cmd'",plogin->ln_input); goto badinp2; } /* must have enough energy for phaser blast */ if (!pcrft->cr_sys[DILITH].s_cap || pcrft->cr_sys[DILITH].s_lvl < i) { sprintf(buf,"%.20s - not enough energy",plogin->ln_input); goto badinp2; } /* phasers must not be damaged too much */ if (pcrft->cr_sys[PHASERS].s_dmg >= 60) { sprintf(buf,"%.22s - too much damage",plogin->ln_input); goto badinp2; } /* use the requested energy */ pcrft->cr_sys[DILITH].s_lvl -= i; biton(pcrft->cr_chng,BIT_SLEVEL+DILITH*flds[FLD_SLEVEL].f_grpw); /* compute damage */ l = i; l *= pcrft->cr_sys[PHASERS].s_pct; l /= 100; l *= (100-pcrft->cr_sys[PHASERS].s_dmg); l /= 100; l *= pcrft->cr_sys[PHASERS].s_cap; l /= 100; /* finally, do it */ output(pcrft->cr_lgn,0,0,0); /* flush buffering */ damage(plogin->ln_play.ip_ptr,puniv,1.,FLOAT(l), "Phaser attack"); break; /***********/ /* torpedo */ /***********/ case 22: if (!pcrft->cr_sys[TORPS].s_cap || pcrft->cr_sys[TORPS].s_lvl < 1) { sprintf(buf,"%.25s - no torpedoes",plogin->ln_input); goto badinp2; } /* check if conditions allow torpedoes */ if (pcrft->cr_dock.ip_ptr) { sprintf(buf,"%.21s - not while docked",plogin->ln_input); goto badinp2; } puniv = pcrft->cr_auto.ip_ptr; if (!puniv || puniv->uv_type == 'O') { sprintf(buf,"%.19s - nothing to fire at",plogin->ln_input); goto badinp2; } if (inuc) { sprintf(buf,"%.24s - not in '-cmd'",plogin->ln_input); goto badinp2; } /* torpedo tubes must not be damaged too much */ if (pcrft->cr_sys[TORPS].s_dmg >= 60) { sprintf(buf,"%.22s - too much damage",plogin->ln_input); goto badinp2; } /* search for an open slot */ for (ptorp=torplst+MAXTORP;ptorp-- > torplst;) if (!ptorp->tp_aim.ip_ptr) break; if (ptorp < torplst) { sprintf(buf,"%.17s - sorry, universe full",plogin->ln_input); goto badinp2; } for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) if (!puniv->uv_type) break; if (puniv < univlst) { perror("play: ptorp but no puniv"); goto badinp; } /* reduce torpedo count */ pcrft->cr_sys[TORPS].s_lvl -= 1; biton(pcrft->cr_chng,BIT_SLEVEL+TORPS*flds[FLD_SLEVEL].f_grpw); /* put torpedo into the universe */ pcrft->cr_dir[0] = 1.0; sptort(pcrft->cr_dir,tmpvec); for (i=0;i<3;++i) { ptorp->tp_pstn[i] = ADD(pcrft->cr_pstn[i], ptorp->tp_thr[i]=MUL(tmpvec[i],50.)); ptorp->tp_vel[i] = ADD(pcrft->cr_vel[i],MUL(tmpvec[i],10.)); } ptorp->tp_aim.ip_ptr = pcrft->cr_auto.ip_ptr; ptorp->tp_fby.ip_ptr = plogin->ln_play.ip_ptr; ptorp->tp_dist = INT(vdist(ptorp->tp_pstn, ptorp->tp_aim.ip_ptr->uv_pstn)); ptorp->tp_dmg = 0; ptorp->tp_lhit.ip_ptr = NULL; puniv->uv_type = 'T'; puniv->uv_pctr = '+'; puniv->uv_pstn = ptorp->tp_pstn; puniv->uv_mass = ptorp->tp_dmg; puniv->uv_rad = 1; puniv->uv_ptr.uv_torp = ptorp; ptorp->tp_univ.ip_ptr = puniv; break; /*******/ /* fix */ /*******/ case 23: if (!pcrft->cr_sys[DMGCON].s_cap) { sprintf(buf,"%.20s - no damage control",plogin->ln_input); goto badinp2; } if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */ i = 0; else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1) goto badinp; /* 0<=arg<=MSYS */ if (i < 0 || i > MSYS) goto badinp; /* subsystem must be present */ if (i > 0 && !pcrft->cr_sys[i-1].s_cap) { sprintf(buf,"%.20s - no such subsystem",plogin->ln_input); goto badinp2; } pcrft->cr_sys[DMGCON].s_lvl = i; biton(pcrft->cr_chng,BIT_SLEVEL+DMGCON*flds[FLD_SLEVEL].f_grpw); break; /***************/ /* - (ucmd) */ /***************/ case 24: if (inuc) { sprintf(buf,"%.24s - nested '-cmd'",plogin->ln_input); goto badinp2; } for (i=0;i<9;ucargs[i++][0] = NULL) ; if ((i=sscanf(plogin->ln_input, "-%s %20s %20s %20s %20s %20s %20s %20s %20s %20s%c", buf,ucargs[0],ucargs[1],ucargs[2],ucargs[3],ucargs[4], ucargs[5],ucargs[6],ucargs[7],ucargs[8],&j)) < 1 || i > 10) goto badinp; buf[sizeof(getuckey.uc_name)-1] = NULL; /* set up data structure to get first line of ucmd */ binit((char *)&getuckey,sizeof(getuckey)); getuckey.uc_ucmdkey = UCMD; strcpy(getuckey.uc_plyr,plogin->ln_name); strcpy(getuckey.uc_name,buf); getuckey.uc_ucmd = 1; /* verify that ucmd exists */ dbmkey.dptr = (char *)&getuckey; dbmkey.dsize = sizeof(getuckey); dbmdata = fetch(dbmkey); if (!dbmdata.dptr) { sprintf(buf,"%.23s - no such '-cmd'",plogin->ln_input); goto badinp2; } inuc = 1; break; /***********/ /* sensors */ /***********/ case 25: if (sscanf(plogin->ln_input,"%*s%c",&i) != 1) /* null */ i = 0; else if (sscanf(plogin->ln_input,"%*s %d",&i) != 1 || i < 0) goto badinp; i *= flds[FLD_REPORT].f_maxg; /* skip display group count */ setrpt(pcrft); /* stolen from report and modified */ for (puniv=univlst+MAXUNIVERSE;puniv-- > univlst;) { if (!puniv->uv_type) continue; if (puniv->uv_ptr.uv_crft == pcrft) continue; /*vdiff(puniv->uv_pstn,pcrft->cr_pstn,tmpvec);*/ tmpdspl = vdisp(puniv,pcrft->cr_univ.ip_ptr,'v'); vcopy(tmpvec,tmpdspl.vec); vcopy(tmpvec2,tmpvec); rttosp(tmpvec,tmpvec); l = INT(tmpvec[0]); if (l <= 5000L) { if (i-- > 0) continue; /* is it on viewscreen? */ vecmul(tmpvec2,pcrft->cr_rmat,tmpvec2); rttosp(tmpvec2,tmpvec2); ftmp = DIV(pcrft->cr_vang,2.); *buf = NULL; if (SUB(ftmp,tmpvec2[2]) >= 0.) { tmpvec2[0] = DIV(tmpvec2[2],ftmp); tmpvec2[2] = DIV(PI,2.); sptort(tmpvec2,tmpvec2); sprintf(buf,"%ld,%ld",-INT(MUL(tmpvec2[1],7.)), INT(MUL(tmpvec2[0],15.))); } /* common characteristics */ sprintf(buf+strlen(buf),"(%c)@%ld %.1f %.1f", puniv->uv_pctr,l,DIV(tmpvec[1],DEGTORAD), DIV(tmpvec[2],DEGTORAD)); /* indicate auto'd, dock'd, or home'd */ l = 0; if (pcrft->cr_auto.ip_ptr == puniv) { if (!l) strcat(buf," ("); l = 1; strcat(buf,"A"); } if (pcrft->cr_dock.ip_ptr == puniv) { if (!l) strcat(buf," ("); l = 1; strcat(buf,"D"); } for (j=0;j<MHOM;++j) if (pcrft->cr_hom[j].ip_ptr == puniv) { if (!l) strcat(buf," ("); l = 1; sprintf(buf+strlen(buf),"%d",j+1); } if (l) strcat(buf,")"); rpt(pcrft,buf); } } fnshrpt(pcrft,0); break; /**********/ /* lockon */ /**********/ case 26: if (!pcrft->cr_lhit.ip_ptr) { sprintf(buf,"%.26s - no attacker",plogin->ln_input); goto badinp2; } /* undo FFWD/AUTO; point in direction of last hit position */ fixaf(pcrft); vdiff(pcrft->cr_lhpstn,pcrft->cr_pstn,pcrft->cr_dir); rttosp(pcrft->cr_dir,pcrft->cr_dir); biton(pcrft->cr_chng,BIT_DIR1); biton(pcrft->cr_chng,BIT_DIR2); fixdir(pcrft); /* try autopiloting (gross!) */ goto doauto; /**********/ /* redraw */ /**********/ case 27: goto redraw; default: perror("play: impossible cmd"); goto badinp; } /* display last command */ output(plogin,'H',(pcrft->cr_lcmd<<8)|FLD_COMMAND,plogin->ln_input); /* process ucmd */ done: if (inuc) { char *ip,*op; /* get ucmd text; setup for next one */ dbmdata = fetch(dbmkey); if (!dbmdata.dptr) goto done2; getuckey.uc_ucmd += 1; /* substitute arguments */ for (ip=dbmdata.dptr,op=plogin->ln_input; *ip && op < plogin->ln_input + sizeof(plogin->ln_input)-1;) { if (*ip == '$' && ip[1] >= '1' && ip[1] <= '9') { char *ap=ucargs[ip[1]-'1']; while (*ap && op < plogin->ln_input + sizeof(plogin->ln_input)-1) *op++ = *ap++; ip += 2; } else *op++ = *ip++; } *op = NULL; goto douc; } /* update screen, reposition cursor, and clear command line if present */ done2: nums(pcrft); view(pcrft); if (plogin->ln_input[0]) { output(plogin,'D',0,0); plogin->ln_input[0] = NULL; } output(plogin,0,0,0); #ifdef DEBUG VDBG("play return\n"); #endif return; } static int okdir(plogin,pcrft,pftmp) register struct login *plogin; register struct crft *pcrft; double *pftmp; { char c; /* no argument, use half viewing angle */ if (sscanf(plogin->ln_input,"%*s%c",&c) != 1) { *pftmp = DIV(pcrft->cr_vang,2.); return(1); } /* 0<arg<360 */ if (sscanf(plogin->ln_input,"%*s %lf",pftmp) != 1) return(0); if (SUB(*pftmp,360.) >= 0. || *pftmp <= 0.) return(0); *pftmp = MUL(*pftmp,DEGTORAD); return(1); } static VOID fixaf(pcrft) register struct crft *pcrft; { if (pcrft->cr_ffwd) { pcrft->cr_ffwd = NULL; biton(pcrft->cr_chng,BIT_AUTOFFWD); } else if (pcrft->cr_auto.ip_ptr) { pcrft->cr_auto.ip_ptr = NULL; biton(pcrft->cr_chng,BIT_AUTOFFWD); } }