|
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 c
Length: 7867 (0x1ebb) Types: TextFile Names: »cmd.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/War/cmd.c«
#ifdef SCCS static char *sccsid = "@(#)cmd.c 1.2 4/5/85"; static char *cpyrid = "@(#)Copyright (C) 1985 by D Bell"; #endif #include "war.h" int testblast(); /* routine to test is blasting is ok */ int testfight(); /* routine to test if fighting is ok */ /* * Read any command from us and set them for the object to work on. * This routine never blocks for input. Partially finished commands * will be delayed until they are complete. Such partial commands * can be edited. Command errors ring the terminal bell. */ docommands() { register char *cp; /* character pointer */ register int ch; /* current character */ register int objchar; /* character for object */ char buf[SCAN_SIZE+1]; /* input buffer */ if (setjmp(ttyjmp) == SCAN_EOF) { /* done with commands */ runcommands(); sendinfo('r', 0, 0, 0); return; } objchar = scanchar(); /* get object char */ if ((objchar == ' ') || (objchar == '\n') || (objchar == '\033')) scanabort(); if (ch == '\014') { dpyredraw(); scanabort(); } cp = buf; while (1) { /* get commands for object */ ch = scanchar(); if ((ch == ' ') || (ch == '\n')) break; if (ch == '\033') scanabort(); *cp++ = ch; } *cp = '\0'; if (setcmds(findobject(objchar), buf)) write(STDERR, "\7", 1); scanabort(); } /* * Routine call by scanchar to read the next input character from * the terminal. Longjmps away if a character is not ready yet. */ ttychar() { long n; /* char count */ unsigned char ch; /* char to return */ if (playing && (ioctl(STDIN, FIONREAD, &n) == 0) && (n <= 0)) { scaneof(); /* no char available now */ } do { errno = 0; n = read(STDIN, &ch, 1); /* read one char */ } while ((n < 0) && (errno == EINTR)); return((int)(ch &= 0x7f)); } /* * Execute one move's worth of commands for all of the user's objects. * Returns nonzero if something at all moved. */ runcommands() { register struct object *obj; /* current object */ register int trymore; /* nonzero if try again */ register int moved; /* something moved */ for (obj = objects; obj < endobjects; obj++) obj->o_flags &= ~F_MOVED; moved = 0; do { trymore = 0; for (obj = objects; obj < endobjects; obj++) { trymore |= runobject(obj); } moved |= trymore; } while (trymore); return(moved); } /* * Attempt to run one move's worth of commands for an object. * Returns nonzero if a command was actually executed. * In addition, the object is flagged as having made it's move. */ runobject(obj) register struct object *obj; /* object to execute */ { register struct cmd *cmd; /* current command to execute */ register struct cell *cell; /* current cell */ register struct cell *newcell; /* new cell */ register struct object *newobj; /* other object */ int trying; /* trying to do commands */ if ((obj->o_side != myside) || (obj->o_flags & F_MOVED)) return(0); cell = obj->o_cell; if (cell == NULL) return(0); trying = 0; for (cmd = obj->o_cmds; cmd->c_type; cmd++) { if (cmd->c_count <= 0) continue; newcell = NULL; switch (cmd->c_type) { case 'b': /* blast a wall */ if (tryblast(obj, cmd->c_subtype)) return(1); break; case 'f': /* fight the enemy */ if (tryfight(obj, cmd->c_subtype)) return(1); break; case 'h': /* move left */ newcell = cell->c_left; break; case 'j': /* move down */ newcell = cell->c_down; break; case 'k': /* move up */ newcell = cell->c_up; break; case 'l': /* move right */ newcell = cell->c_right; break; default: panic("running unknown command"); } if ((newcell == NULL) || (newcell == &edge)) continue; newobj = newcell->c_obj; if (newobj) { trying |= ((newobj->o_flags & F_WALL) == 0); continue; } placeobject(obj, newcell->c_row, newcell->c_col); sendinfo('p', newcell->c_row, newcell->c_col, obj->o_id); obj->o_flags |= F_MOVED; if (cmd->c_count < INFINITY) cmd->c_count--; return(1); } return(0); } /* * Attempt to blast a wall in a given direction. * Returns nonzero if we actually tried to do it. */ tryblast(obj, dir) register struct object *obj; /* object doing fighting */ { register struct cell *cc; /* current cell */ if ((obj->o_flags & F_MOVED) || ((obj->o_flags & F_BLAST) == 0)) return(0); cc = pickdir(obj->o_cell, dir, testblast); if (cc == NULL) return(0); obj->o_flags |= F_MOVED; obj = cc->c_obj; if ((obj->o_life >= 100) || ((obj->o_life > 0) && (random() % obj->o_life))) return(1); removeobject(cc->c_row, cc->c_col); sendinfo('b', cc->c_row, cc->c_col, 0); return(1); } /* See if a location is worth blasting */ testblast(cc) register struct cell *cc; /* cell to check */ { return((cc != &edge) && cc->c_obj && (cc->c_obj->o_flags & F_WALL)); } /* * Attempt to fight in a given certain direction. * Returns nonzero if we actually did fight. */ tryfight(obj, dir) register struct object *obj; /* object doing fighting */ { register struct cell *cc; /* current cell */ if ((obj->o_flags & F_MOVED) || ((obj->o_flags & F_FIGHT) == 0)) return(0); cc = pickdir(obj->o_cell, dir, testfight); if (cc == NULL) return(0); obj->o_flags |= F_MOVED; if (random() % 2) return(1); sendinfo('h', cc->c_row, cc->c_col, 0); hitobject(cc->c_row, cc->c_col); return(1); } /* See if a cell is worth fighting */ testfight(cc) struct cell *cc; /* cell to check */ { register struct object *obj; /* object to fight */ obj = cc->c_obj; if (obj == NULL) return(0); return(((obj->o_flags&(F_WALL|F_EDGE))== 0) && (obj->o_side != myside)); } /* * Specify the given list of commands to the specified object. * Returns nonzero if a bad command is given or if too many are specified. * If the string is valid, any previous commands are cancelled and * the new ones are in effect. */ setcmds(obj, str) register struct object *obj; /* current object */ register char *str; /* command string */ { register struct cmd *cmd; /* next command to store */ register int count; /* count for command */ register int gotcount; /* got a count */ struct cmd newcmds[CMDS]; /* new commands */ if ((obj == NULL) || (obj->o_side != myside)) return(1); cmd = newcmds; while (*str) { count = 0; /* read numeric argument */ gotcount = 0; while ((*str >= '0') && (*str <= '9')) { count = (count * 10) + *str++ - '0'; gotcount = 1; } if (count >= (INFINITY - 1)) count = (INFINITY - 1); if (gotcount == 0) count = INFINITY; if (count <= 0) return(1); switch (*str) { case 'b': /* blast in a direction */ case 'f': /* fight in a direction */ if (cmd >= &newcmds[CMDS-2]) return(1); cmd->c_type = *str++; switch (*str) { /* verify */ case 'h': case 'l': case 'j': case 'k': case 'a': case 'n': cmd->c_subtype = *str++; cmd->c_count = INFINITY; cmd++; continue; } return(1); case 'h': /* move left small amount */ case 'j': /* move down small amount */ case 'k': /* move up small amount */ case 'l': /* move right small amount */ if (cmd >= &newcmds[CMDS-2]) return(1); if (gotcount == 0) count = 1; cmd->c_type = *str++; cmd->c_subtype = '\0'; cmd->c_count = count; cmd++; continue; case 'H': /* move left large amount */ case 'J': /* move down large amount */ case 'K': /* move up large amount */ case 'L': /* move right large amount */ if (cmd >= &newcmds[CMDS-2]) return(1); cmd->c_type = *str++ - 'A' + 'a'; cmd->c_subtype = '\0'; cmd->c_count = count; cmd++; continue; default: /* illegal */ return(1); } } cmd->c_type = 'f'; /* add default fight command */ cmd->c_subtype = 'a'; cmd->c_count = INFINITY; cmd++; cmd->c_type = '\0'; /* end command table */ bcopy(newcmds, obj->o_cmds, sizeof(obj->o_cmds)); /* set cmds */ return(0); }