Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 5/3/83; site cmu-cs-cad.ARPA Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!rochester!cmu-cs-pt!cmu-cs-cad!mlm From: mlm@cmu-cs-cad.ARPA (Michael Mauldin) Newsgroups: net.sources Subject: Rog-O-Matic XIV (part 02 of 10) Message-ID: <274@cmu-cs-cad.ARPA> Date: Fri, 1-Feb-85 13:33:28 EST Article-I.D.: cmu-cs-c.274 Posted: Fri Feb 1 13:33:28 1985 Date-Received: Sun, 3-Feb-85 09:48:06 EST Organization: Carnegie-Mellon University, CS/RI Lines: 1670 #!/bin/sh # # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # @ Here is part of your new automatic Rogue player, Rog-O-Matic XIV! @ # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # # [Note: this is a Beta-Test release of version XIV, and almost # certainly contains bugs. A new version will be made available # soon. If you experience any problems with this version, please # contact Michael Mauldin as soon as possible, so your input can be # included in the new release] # # Rog-O-Matic XIV is shipped via mail in pieces, files rgm14.01, rgm14.02, # ..., rgm14.nn. Each piece contains some number of smaller files. To # retrieve them, run each file through the shell 'sh', as follows: # # sh explore.c << '/' X/* X * explore.c: Rog-O-Matic XIV (CMU) Thu Jan 31 20:14:30 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This file contains all of the functions which are used to search out X * paths to explore, pick up something, or run away. X */ X X# include X# include "types.h" X# include "globals.h" X X# define SEARCHES(r,c) \ X (onrc(DEADEND,r,c) ? \ X ((version < RV53A || !isexplored (r,c)) ? \ X (timestosearch + k_door / 5) : \ X (timestosearch - k_door / 5 + 5)) : \ X timestosearch) X Xstatic int expDor, expavoidval; Xstatic int avdmonsters[24][80]; X Xint connect[9][4] = { X /* Room top bot left right*/ X /* 0 */ {-1, 3, -1, 1}, X /* 1 */ {-1, 4, 0, 2}, X /* 2 */ {-1, 5, 1, -1}, X /* 3 */ { 0, 6, -1, 4}, X /* 4 */ { 1, 7, 3, 5}, X /* 5 */ { 2, 8, 4, -1}, X /* 6 */ { 3, -1, -1, 7}, X /* 7 */ { 4, -1, 6, 8}, X /* 8 */ { 5, -1, 7, -1} X}; X X/* X * genericinit: Initialize a 'standard' movement search. MLM X */ X Xgenericinit () X{ expavoidval = avoid(); X return (1); X} X X/* Secret door search values and continuance tables: X * X * Number of unsearched walls adjacent. X * X * Vert Horiz Value Cont Explanation X * --------------------------------------------------- X * 0 0 0 0 Valueless X * 0 1 N-24-dep 16 Prefer (0,2) 1 move later X * 0 2 N-22-dep 15 Prefer (0,3) 1 move later X * 0 3 N-20-dep 14 Prefer (1,0) 10 moves later X * 1 0 N-9-dep 4 Prefer (1,1) 2 moves later X * 1 1 N-6-dep 2 Prefer (2,0) 1 move later X * 1 2 N-5-dep 2 Prefer (2,0) 1 move later X * 1 3 N-5-dep 2 Impossible X * 2 0 N-3-dep 1 Prefer (3,0) 1 move later X * 2 1 N-2-dep 0 X * 2 2 N-1-dep 0 X * 2 3 N-1-dep 0 Impossible X * 3 0 N 0 Best possible X * 3 1 N 0 Impossible X * 3 2 N 0 Impossible X * 3 3 N 0 Impossible X */ X X# define N 100 Xstatic int secretvalues[16]= { 0, N-24, N-22, N-20, X N-9, N-6, N-5, N-5, X N-3, N-2, N-1, N-1, X N, N, N, N }; X Xstatic int secretcont[16] = { 0, 16, 15, 14, X 4, 2, 2, 2, X 1, 0, 0, 0, X 0, 0, 0, 0 }; X X/* X * gotowards: Move toward a square. X */ X Xint gotorow = NONE, gotocol = NONE; X Xgotowards (row, col, running) Xint row, col, running; X{ int gotoinit(), gotovalue(); X X gotorow = row; gotocol = col; X return (makemove (running ? RUNAWAY:GOTOMOVE, gotoinit, gotovalue, REUSE)); X} X X/* X * gotoinit: Initialize a gotowards move. X */ X Xgotoinit () X{ expavoidval = avoid(); X return (1); X} X X/* X * gotovalue: Only the current target square has a value. X */ X Xgotovalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ X *avd = onrc (SAFE, r, c) ? 0 : X onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 175 : X onrc (TELTRAP, r, c) ? 50 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (WATERAP, r, c) ? 50 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X *avd += 200; X X *val = r == gotorow && c == gotocol ? 1 : 0; X /* *cont = 0; // default value when called // */ X return (1); X} X X/* X * sleepvalue: Squares with sleeping monsters have value. X * Use genericinit. MLM X */ X Xsleepvalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ X *avd = onrc (SAFE, r, c) ? 0 : X onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 175 : X onrc (TELTRAP, r, c) ? 50 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (WATERAP, r, c) ? 50 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X *avd += 200; X X if (onrc (SLEEPER, r, c)) X { *val = 1; X *avd = 0; X /* *cont = 0; // default value when called // */ X } X X return (1); X} X X/* X * wallkind: given a row and column, determine which kind of wall if any X * is there. Part of doorinit Guy Jacobson 5/82 X */ X Xint wallkind (r, c) Xint r, c; X{ X switch (screen[r][c]) X { case '|': if (onrc (ROOM, r, c+1)) return (LEFTW); X else return (RIGHTW); X case '-': if (onrc (ROOM, r+1, c)) return (TOPW); X else if (onrc (ROOM, r-1, c)) return (BOTW); X else return (CORNERW); X case '+': return (DOORW); X default: return (NOTW); X } X} X X/* X * setpsd: Initialize secret door search X * X * Guy Jacobson 5/82 X * Modified to allow searching even when there are cango bits. MLM. 10/82 X * Modified to reuse existing map while it is valid. LGCH. 10/82 X * Modified to understand maze room secret doors. MLM. 10/83 X */ X Xsetpsd (print) X{ register int i, j, k, whereto, numberpsd=0; X X if (!print && reusepsd > 0) return (reusepsd-1); X X /* find what rooms are missing */ X markmissingrooms (); X X /* Changed loop boundaries to ignore border around screen -- mlm 5/18/82 */ X for (i=2; i<22; i++) for (j=1; j<79; j++) X { unsetrc (PSD|DEADEND,i,j); X X /* If attempt > 3, allow ANYTHING to be a secret door! */ X if (attempt > 3 && ! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) && X nextto (CANGO, i, j)) X { if (!onrc (PSD, i, j)) numberpsd++; setrc(PSD,i,j); } X X /* Set Possible Secret Door for maze room secret doors */ X else if (attempt > 0 && ! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) && X mazedoor (i, j)) X { if (!onrc (PSD, i, j)) numberpsd++; setrc(PSD,i,j); } X X /* Set Possible Secret Door for corridor secret door */ X else if (version >= RV53A && X ! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) && X nextto (DOOR, i, j)) X { if (!onrc (PSD, i, j)) numberpsd++; setrc(PSD,i,j); } X X /* Set Possible Secret Door for dead end corridors */ X else if (! onrc (BEEN|DOOR|HALL|ROOM|WALL|STAIRS, i, j) && X (onrc (HALL, i-1, j) + onrc (HALL, i+1, j) + X onrc (HALL, i, j-1) + onrc (HALL, i, j+1) == HALL) && X !(onrc(HALL|DOOR, i-1, j-1) || onrc(HALL|DOOR, i+1, j+1) || X onrc(HALL|DOOR, i-1, j+1) || onrc(HALL | DOOR, i+1, j-1)) && X canbedoor (i, j)) X { if (!onrc (PSD, i, j)) numberpsd++; X setrc(DEADEND,i,j); setrc(PSD,i,j); X } X X /* Set PSD for walls which connect to empty space */ X X /* Modified to allow PSD for !ROOM (including the old CANGO des.) */ X /* since potions and scrolls of detection can cause the CANGO bit */ X /* to be set for a square on which we have never been. */ X /* mlm 10/8/82 */ X X /* If attempt > 2, then relax the constraint about empty space, */ X /* since we might have teleported into a disconnected part of the */ X /* level. This means after we have searched twice, we look for */ X /* ANY possible door, not just doors leading to empty space. */ X /* mlm 10/11/82 */ X X else X { if ((k = wallkind (i,j)) >= 0) X { /* A legit sort of wall */ X whereto = connect[whichroom (i,j)][k]; X if (whereto >= 0 && (attempt > 1 || room[whereto] == 0)) X { if (!onrc (PSD, i, j)) numberpsd++; X setrc (PSD,i,j); X } X } X } X } X X /* Now remove PSD bits from walls which already have doors */ X for (i=2; i<22; i++) for (j=1; j<79; j++) X { if (onrc (DOOR, i, j)) X { for (k = i-1; onrc (WALL, k, j); k--) X { if (onrc (PSD, k, j)) numberpsd--; unsetrc (PSD, k, j);} X for (k = i+1; onrc (WALL, k, j); k++) X { if (onrc (PSD, k, j)) numberpsd--; unsetrc (PSD, k, j);} X for (k = j-1; onrc (WALL, i, k); k--) X { if (onrc (PSD, i, k)) numberpsd--; unsetrc (PSD, i, k);} X for (k = j+1; onrc (WALL, i, k); k++) X { if (onrc (PSD, i, k)) numberpsd--; unsetrc (PSD, i, k);} X } X } X X if (print || debug (D_SCREEN)) X for (i=0; i<24; i++) for (j=0; j<80; j++) X if (onrc (PSD,i,j)) { at (i,j); addch ('P'); } X X reusepsd = numberpsd+1; X return (numberpsd); X} X X/* X * downvalue: find nearest stairs or trapdoor (use genericinit for init). X */ X Xdownvalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ X *avd = onrc (SAFE, r, c) ? 0 : X onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 175 : X onrc (TELTRAP, r, c) ? 50 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (WATERAP, r, c) ? 50 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X X if (onrc (STAIRS | TRAPDOR, r, c)) { *val = 1; *avd = 0; } X else { *val = 0; } X X return (1); X} X X/* X * expruninit: same as expinit but don't bias against doors. X */ X Xexpruninit () X{ dwait (D_CONTROL | D_SEARCH, "expruninit called."); X expinit(); X expDor = 0; X avoidmonsters (); X return (1); X} X X/* X * exprunvalue: When running, avoid monsters. X * X * Try to see a new square when running. X */ X Xexprunvalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ if (r == atrow && c == atcol) /* Current square useless MLM */ X *val = 0; X else if (onrc (MONSTER | TRAP, r, c)) /* Added TRAP useless MLM */ X *val = 0; X else if (!zigzagvalue (r, c, depth, val, avd, cont)) X return (0); X X if (*val > 0) { *val = *val * 1000 + depth; *cont = INFINITY; } X *avd += avdmonsters[r][c]; X return (1); X} X X/* X * expunpininit: same as exprunnit but try to unpin. X */ X Xexpunpininit () X{ dwait (D_CONTROL | D_SEARCH, "expunpininit called."); X expinit(); X expDor = 0; X pinavoid (); X return (1); X} X X/* X * expunpinvalue: When unpinning, avoid monsters. X * X * Try to see a new square when unpinning, but unpin anywhere if need be. X */ X Xexpunpinvalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ if (r == atrow && c == atcol) /* Current square useless MLM */ X *val = 0; X else if (onrc (MONSTER | TRAP, r, c)) /* Added TRAP useless MLM */ X *val = 0; X else if (!zigzagvalue (r, c, depth, val, avd, cont)) X return (0); X X if (*val > 0) { *val = *val * 1000 + depth; *cont = INFINITY; } X *avd += avdmonsters[r][c]; X return (1); X} X X/* X * runinit: R U N A W A Y S E A R C H X */ X Xruninit () X{ avoidmonsters(); X return (1); X} X X/* X * runvalue: X * X * Evaluate square for running away. Targets, in priority order are: X * X * STAIRS TRAPDOR TELTRAP X * RUNOK (cycle door) X * DOOR X * ANYWHERE X * X * Traps are avoided for a variable number of moves, except for target traps X * Gave GasTraps and BearTraps infinite avoidance. MLM 10/11/83 X */ X Xrunvalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ *avd = onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 0 : X onrc (TELTRAP, r, c) ? 0 : X onrc (GASTRAP, r, c) ? INFINITY : X onrc (BEARTRP, r, c) ? INFINITY : X onrc (DARTRAP, r, c) ? 100 : X onrc (WATERAP, r, c) ? 100 : X onrc (MONSTER, r, c) ? 150 : X 0; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X *avd += 200; X X if (onrc (MONSTER, r, c)) X { *val = 0; } X if (onrc (STAIRS+TRAPDOR+TELTRAP, r, c)) X { *val = 5000; *avd = 0; /* *cont = 0; */ } X else if (r == atrow && c == atcol) /* If we are running, our current */ X { *val = 0;} /* cant be that great -- MLM */ X else if (onrc (RUNOK, r, c)) X { *val = 4000; *cont = INFINITY;} X else if (onrc (DOOR | BEEN, r, c) == DOOR) X { *val = 2000+depth; *cont = INFINITY;} X else if (onrc (DOOR, r, c)) X { *val = 1000+depth; *cont = INFINITY;} X else if (onrc (HALL, r, c)) X { *val = depth; *cont = INFINITY;} X /* ---------------------------------------------------------------- X else if (onrc (CANGO | TRAP, r, c) == CANGO) X { *val = 1+depth; *cont = INFINITY;} X ---------------------------------------------------------------- */ X else X { *val = 0; } X X *avd += avdmonsters[r][c]; X} X X/* X * unpininit: U N P I N S E A R C H X * X * Same as runint, but we are willing to take one hit to get away. X */ X Xunpininit () X{ pinavoid(); X return (1); X} X X/* X * rundoorinit: Standard initialization routine. X */ X Xrundoorinit() X{ avoidmonsters(); X return (1); X} X X/* X * rundoorvalue: X * X * Evaluate square for running into doorway. X * X * Targets, in priority order are: X * X * RUNOK (cycle door) X * DOOR X * X * Traps are avoided for a variable number of moves, except for target traps X * Gave GasTraps and BearTraps infinite avoidance. MLM 10/11/83 X */ X Xrundoorvalue (r, c, depth, val, avd, cont) Xint r, c, depth; Xint *val, *avd, *cont; X{ *avd = onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 0 : X onrc (TELTRAP, r, c) ? 0 : X onrc (GASTRAP, r, c) ? INFINITY : X onrc (BEARTRP, r, c) ? INFINITY : X onrc (DARTRAP, r, c) ? 100 : X onrc (WATERAP, r, c) ? 100 : X onrc (MONSTER, r, c) ? 50 : 0; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X *avd += 200; X X if (onrc (RUNOK, r, c)) { *val = 2;} X else if (onrc (DOOR, r, c)) { *val = 1; *cont = INFINITY;} X else { *val = 0;} X X *avd += avdmonsters[r][c]; X} X X/* X * E X P L O R A T I O N S E A R C H X */ X Xexpinit () X{ /* avoidance values for doors */ X expDor = 0; X expavoidval = avoid(); X return (1); X} X Xroominit () X{ expinit (); X expDor = INFINITY; X return (1); X} X X/* X * expvalue: evaluation function for exploration. LGCH X * X * In order to prevent leaving orphan unseen squares, we have heuritics X * which cause rogomatic to use the three-step pattern to scan along the X * boundary of a room, and also have tests which detect any orphans (e.g. X * corners and when an object interrupts the search pattern) and cause them X * to be seen. X * X * Three-step pattern: X * X * @@ @@ X * @ @ @ X * bbbbbbbbb X */ X Xexpvalue (r, c, depth, val, avd, cont) Xint r, c, depth; Xint *val, *avd, *cont; X{ register int k, nr, nc, l; X int a, v = 0, nunseenb = 0, nseenb = 0, nearb = 0; X X a = onrc (SAFE|DOOR|STAIRS|HALL, r, c) ? 0 : X onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 300 : X onrc (TELTRAP, r, c) ? 100 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (TRAP, r, c) ? 100 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X { *avd = a+1000; *val=0; return (1); } X X if (onrc (BEEN+SEEN, r, c) == SEEN) /* If been or not seen, not a target */ X { for (k=0; k<8; k++) X { nr = r + deltr[k]; X nc = c + deltc[k]; X X /* For each unseen neighbour: add 10 to value. */ X if (nr >= 1 && nr <= 22 && nc >= 0 && nc <= 80 && X !onrc (SEEN, nr, nc)) X { v += 10; X X if (onrc (BOUNDARY, nr, nc)) X { /* Count unseen boundary neighbours. */ X nunseenb++; X X /* Count seen boundaries horiz/vert adjacent to unseen boundary */ X for (l=0; l<8; l+=2) X if (onrc (SEEN+BOUNDARY, nr+deltr[l], nc+deltc[l]) == X SEEN+BOUNDARY) X nseenb++; X X } X else X { /* Check for unseen boundary horiz/vert */ X /* adjacent to neighbour and not a neighbour. */ X l = k / 2 * 2; /* horizontal/vertical */ X if (onrc (BOUNDARY+SEEN, nr+deltr[l], nc+deltc[l]) == BOUNDARY) X nearb = 1; X else X { l = ((k+1) / 2 * 2) % 8; X if (onrc (BOUNDARY+SEEN, nr+deltr[l], nc+deltc[l]) == BOUNDARY) X nearb = 1; X } X } X } X } X X /* To zig-zag: add number of unseen boundary neighbours * 6 */ X v += nunseenb * 6; X X /* To do the three-step: add 29 if an unseen neighbour had an unseen X * boundary horiz/vert adjacent */ X if (nearb) X v += 29; X X /* To prevent orphans: if three unseen neighbours are boundary and one X * has a seen boundary horiz/vert adjacent, add 200 */ X if (nunseenb >= 3 && nseenb >= 1) X v += 200; X X /* To clean up any orphans: if two seen boundaries are adjacent to any X * unseen boundary neighbours, add 400. */ X if (nseenb >= 2) X v += 400; X } X X if (onrc (DOOR, r, c)) X a += expDor; X /* else if (onrc (BEEN+BOUNDARY, r, c) == BOUNDARY) X a++; // Avoid running along the untrodden boundary. // */ X X *avd = a; X *val = v; X if (v < 50) X *cont = 4; /* Look for something better */ X if (debug (D_SCREEN) && v > 0) X { mvaddch (r, c, 'o'); dwait (D_SCREEN, "Value %d", v); } X X return (1); X} X X/* X * zigzagvalue: evaluation function for exploration. LGCH X * X * This is a copy of expvalue with the three-step code and the code to X * detect orphans removed. It is used when running away and unpinning X * to find a useful exploration move. The boundary moves must zig-zag X * rather than three-step so that the door can be entered when it is seen X * without taking a hit from the monster chasing us. X * X * Gave GasTraps and BearTraps infinite avoidance. MLM 10/11/83 X */ X Xzigzagvalue (r, c, depth, val, avd, cont) Xint r, c, depth; Xint *val, *avd, *cont; X{ register int k, nr, nc, l; X int a, v = 0, nunseenb = 0, nseenb = 0, nearb = 0; X X a = onrc (SAFE|DOOR|STAIRS|HALL, r, c) ? 0 : X onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 300 : X onrc (TELTRAP, r, c) ? 100 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (TRAP, r, c) ? 100 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X { *avd = a+1000; *val=0; return (1); } X X if (onrc (BEEN+SEEN, r, c) == SEEN) /* If been or not seen, not a target */ X { for (k=0; k<8; k++) X { nr = r + deltr[k]; X nc = c + deltc[k]; X X /* For each unseen neighbour: add 10 to value. */ X if (nr >= 1 && nr <= 22 && nc >= 0 && nc <= 80 && X !onrc (SEEN, nr, nc)) X { v += 10; X X if (onrc (BOUNDARY, nr, nc)) X { /* Count unseen boundary neighbours. */ X nunseenb++; X } X if (debug (D_SCREEN)) mvaddch (nr, nc, 'o'); X } X } X X /* To zig-zag: add number of unseen boundary neighbours * 6 */ X v += nunseenb * 6; X } X X if (onrc (DOOR, r, c)) X a += expDor; X /* else if (onrc (BEEN+BOUNDARY, r, c) == BOUNDARY) X a++; // Avoid running along the untrodden boundary. // */ X X *avd = a; X *val = v; X *cont = 0; /* Look for orphans */ X X return (1); X} X X/* X * S E C R E T D O O R S E A R C H X */ X Xsecretinit () X{ expinit (); X if (setpsd ()) X return (1); X return (0); X} X Xsecretvalue (r, c, depth, val, avd, cont) Xint r, c, depth; Xint *val, *avd, *cont; X{ register int v, a, k; X X *val=0; X v = 0; /* establish value of square */ X a = onrc (SAFE, r, c) ? 0 : X onrc (ARROW, r, c) ? 50 : X onrc (TRAPDOR, r, c) ? 175 : X onrc (TELTRAP, r, c) ? 50 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (WATERAP, r, c) ? 50 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X a += 200; X X for (k=0; k<8; k++) /* examine adjacent squares */ X { register int nr = r + deltr[k]; X register int nc = c + deltc[k]; X if (nr >= 1 && nr <= 22 && X nc >= 0 && nc <= 80 && X onrc (PSD, nr, nc) && timessearched[nr][nc] < SEARCHES(nr,nc)) X { /* If adjacent square is on the screen */ X /* and if it has PSD set but has not been searched completely */ X /* count useful neighbours */ X if (screen[nr][nc] == '|') v += 4; X else v ++; X if (debug (D_SCREEN | D_INFORM)) mvaddch (nr, nc, 'S'); X } X } X X if (v>0) X { if (version >= RV53A && X onrc (DOOR|BEEN, r, c) == DOOR|BEEN && X (onrc (CANGO|WALL, r+1, c) == 0 || onrc (CANGO|WALL, r-1, c) == 0 || X onrc (CANGO|WALL, r, c+1) == 0 || onrc (CANGO|WALL, r, c-1) == 0)) X { *val = v+100; *cont = 5; } X else X { v = min (15, v); X *val = secretvalues[v]; *cont = secretcont[v]; X if (onrc (DOOR, r, c)) a += expDor; X } X } X *avd = a; X X return (1); X} X X/* X * E S T A B L I S H A V O I D A N C E M A P to avoid monsters. X */ X X# define AVOID(r,c,ch) \ X { avdmonsters[r][c] = INFINITY; \ X if (debug (D_SCREEN)) { at((r),(c)); addch(ch); at(row,col); }} X Xavoidmonsters () X{ register int i, r, c, wearingstealth; X X /* Clear old avoid monster values */ X for (i = 24*80; i--; ) avdmonsters[0][i] = 0; X X /* Set stealth status */ X wearingstealth = (wearing ("stealth") != NONE); X X /* Avoid each monster in turn */ X for (i=0; i= RV53A && on (DOOR) && !blinded && X (seerc (' ',atrow+1,atcol) || seerc (' ',atrow-1,atcol) || X seerc (' ',atrow,atcol+1) || seerc (' ',atrow,atcol-1)) && X SEARCHES (atrow, atcol) < timestosearch+20) X { int count = timessearched[atrow][atcol]+1; X saynow ("Searching dead end door (%d,%d) for the %d%s time...", X atrow, atcol, count, ordinal (count)); X command (T_DOORSRCH, "s"); return (1); X } X X /* Verify that we are actually at a dead end */ X if (onrc (CANGO,atrow-1,atcol) + onrc (CANGO,atrow,atcol-1) + X onrc (CANGO,atrow+1,atcol) + onrc (CANGO,atrow,atcol+1) != CANGO) X return (0); X X /* If Level 1 or edge of screen: dead end cannot be room, mark and return */ X if (Level == 1 && attempt == 0 || X version < RV53A && (atrow<=1 || atrow>=22 || atcol<=0 || atcol>=79)) X { markexplored (atrow, atcol); return (0); } X X /* Have we mapped this level? */ X if (Level == didreadmap) return (0); X X /* Found a dead end, should we search it? */ X if (nexttowall (atrow, atcol) || X canbedoor (atrow, atcol) && X (version >= RV53A || !isexplored (atrow, atcol))) X { setrc (DEADEND, atrow, atcol); X X if ((SEARCHES (atrow, atcol) - timessearched[atrow][atcol]) > 0) X { int count = timessearched[atrow][atcol]+1; X saynow ("Searching dead end (%d,%d) for the %d%s time...", X atrow, atcol, count, ordinal (count)); X command (T_DOORSRCH, "s"); X return (1); X } X else X { markexplored (atrow, atcol); X return (0); X } X } X X return (0); X} X X/* X * F I N D R O O M : Try to find another room. X */ X Xfindroom () X{ int expinit(), expvalue(); /* LGCH */ X X if (new_findroom) X { if (!on (ROOM) && secret ()) return (1); X if (makemove (EXPLORE, expinit, expvalue, REUSE)) return (1); X } X X new_findroom = 0; X dwait (D_SEARCH, "findroom failed."); X return (0); X} X X/* X * E X P L O R E R O O M : Explore the current room. X */ X Xexploreroom () X{ int roominit(), expvalue(); /* LGCH */ X X if (!on (ROOM) || isexplored (atrow, atcol)) return (0); X if (makemove (EXPLOREROOM, roominit, expvalue, REUSE)) return (1); X markexplored (atrow, atcol); X X dwait (D_SEARCH, "exploreroom failed."); X return (0); X} X X/* X * D O O R E X P L O R E : look for secret doors X */ X Xdoorexplore() X{ static searchcount = 0; X int secretinit(), secretvalue(); X X /* If no new squares or read map, dont bother */ X if (! new_search || Level == didreadmap) X { searchcount = 0; return (0); } X X if (makemove (SECRETDOOR, secretinit, secretvalue, REUSE)) /* move */ X { searchcount = 0; return (1); } X X if (searchcount > 20) X { new_search = 0; return (0); } X X if (ontarget) /* Moved to a possible secret door, search it */ X { searchcount++; X saynow ("Searching square (%d,%d) for the %d%s time...", X atrow, atcol, searchcount, ordinal (searchcount)); X command (T_DOORSRCH, "s"); X return (1); X } X X new_search = searchcount = 0; X return (0); X} X X/* X * S A F E S Q U A R E S E A R C H Use genericinit. X */ X Xsafevalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ register int k, v; X X *avd = onrc (SAFE, r, c) ? 0 : X onrc (TRAPDOR | BEARTRP | GASTRAP, r, c) ? INFINITY : X onrc (ARROW, r, c) ? 50 : X onrc (TELTRAP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (WATERAP, r, c) ? 50 : X onrc (MONSTER, r, c) ? 150 : X expavoidval; X *val = 0; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X *avd += 500; X X if (onrc(CANGO, r, c)) X { v = 0; X for (k=0; k<8; k++) X if (onrc(CANGO, r+deltr[k], c+deltc[k]) && X onrc(CANGO, r+deltr[k], c) && X onrc(CANGO, r, c+deltc[k])) v++; X if (v < 3) X *val = 1; /* *cont = 0; // default // */ X } X return (1); X} X X/* findsafe: find a spot with 2 or fewer moves, for when blinded */ X Xfindsafe() X{ X return (makemove (FINDSAFE, genericinit, safevalue, REEVAL)); X} X X/* How scared are we of hitting a trap? */ X Xavoid () X{ if (cheat && !foundarrowtrap && !usingarrow) return (0); X else if (Level < 5) return (0); /* Don't bother */ X else return (2); /* Avoid a little */ X} X X/* X * archery: Initialize a archery move. We find a good place to X * shoot from and stand there. Then mark the monster as awake, and X * battlestations will handle firing at him. X */ X Xstatic int archrow = NONE, archcol = NONE, archturns = NONE, archval[24][80]; X Xarchmonster (m, turns) Xregister int m; /* Monster to attack */ Xregister int turns; /* Minimum number of arrows to make it worthwhile */ X{ int archeryinit(), archeryvalue(); X register int mr, mc; X X dwait (D_CONTROL | D_BATTLE, "archmonster: m=%d, turns=%d", m, turns); X X if (! new_arch) return (0); X X /* Useless without arrows */ X if (havemult (missile, "", turns) < 0) X { dwait (D_BATTLE, "archmonster, fewer than %d missiles", turns); X return (0); } X X /* For now, only work for sleeping monsters */ X if (mlist[m].q != ASLEEP) X { dwait (D_BATTLE, "archmonster, monster not asleep"); return (0); } X X /* Save globals */ X archrow = mlist[m].mrow; archcol = mlist[m].mcol; archturns = turns; X X /* Can we get to a suitable square */ X if (makemove (ARCHERYMOVE, archeryinit, archeryvalue, REUSE)) X { dwait (D_BATTLE, "archmonster, made a move"); return (1); } X X /* If no move made and not on target, no path to monster */ X if (!ontarget) { new_arch = 0; return (0); } X X /* On target: wake him up and set darkdir/turns if necessary */ X mr = mlist[m].mrow; mc = mlist[m].mcol; targetmonster = mlist[m].chr; X mlist[m].q = AWAKE; dwait (D_BATTLE, "archmonster, waking him up"); X X /* Set dark room archery variables, add goal of standing on square */ X if (darkroom ()) X { darkdir = direc (mr-atrow, mc-atcol); X darkturns = max (abs (mr-atrow), abs (mc-atcol)); X agoalr = mr; agoalc = mc; /* Go here to pick up what (s)he drops */ X } X X /* Tell the user about it */ X saynow ("Arching at %s", monname (mlist[m].chr)); X X return (1); X} X X/* X * archeryinit: Initialize a archery move. Must avoid monsters to avoid X * waking our potential victim up. X */ X Xarcheryinit () X{ register int dir, r, c, dr, dc, dist; X X /* Clear the archery value array */ X for (r = 24*80; r--; ) archval[0][r] = 0; X X /* Scan around monster to see how far away we can shoot from */ X for (dir = 0; dir < 8; dir++) X { dr = deltr[dir]; dc = deltc[dir]; X for (dist = 1, r = archrow+dr, c = archcol+dc; X onrc (CANGO | HALL | MONSTER, r, c) == CANGO; X r += dr, c += dc, dist++) X if (dist > archturns && !onrc (TRAP, r, c)) X { archval[r][c] = dist - 1; /* number of arrows we get to shoot */ X if (debug (D_SCREEN)) { at (r, c); addch ('='); at (row, col); } X } X } X X expavoidval = avoid(); X avoidmonsters (); X return (1); X} X X/* X * archeryvalue: Get the value of the square from the archery array. X * Value is non-zero only if we can fire arrows at beast and value is X * number of shots we can fire. X */ X Xarcheryvalue (r, c, depth, val, avd, cont) Xint r, c, depth, *val, *avd, *cont; X{ X *avd = (onrc (SAFE, r, c) ? 0 : X onrc (TRAPDOR, r, c) ? INFINITY : X onrc (HALL, r, c) ? INFINITY : X onrc (ARROW, r, c) ? 50 : X onrc (TELTRAP, r, c) ? 50 : X onrc (GASTRAP, r, c) ? 50 : X onrc (BEARTRP, r, c) ? 50 : X onrc (DARTRAP, r, c) ? 200 : X onrc (WATERAP, r, c) ? 50 : X onrc (MONSTER, r, c) ? 150 : X expavoidval) + avdmonsters[r][c]; X X if (onrc (SCAREM, r, c) && version < RV53A && objcount != maxobj) X *avd += 500; X X *val = archval[r][c]; X *cont = INFINITY; X X return (1); X} X X/* X * M O V E T O R E S T : Find a safe square to rest up on. X */ X Xstatic restinlight = 0; /* True only in lit rooms */ Xstatic restinroom = 0; /* True only in a room */ Xstatic restr = NONE, restc = NONE; /* Square to rest on */ X X/* Set new resting goal */ Xunrest () X{ restr = restc = NONE; X} X X/* Move to a good square to rest up on */ Xmovetorest () X{ int restinit(), restvalue(); /* LGCH */ X X if (markcycles (NOPRINT)) X unrest (); X X /* If we are where we want to rest, do so */ X if (restr >= 0 && atrow == restr && atcol == restc) X { dwait (D_SEARCH, "movetorest: already on square"); return (0); } X X /* Try to move to a better square (remember position) */ X if (makemove (RESTMOVE, restinit, restvalue, REUSE)) X { dwait (D_SEARCH, "movetorest wins."); X restr = targetrow; restc = targetcol; X return (1); X } X X /* Cant move anywhere better, stay here */ X dwait (D_SEARCH, "movetorest fails."); X restr = atrow; restc = atcol; X X return (0); X} X Xrestinit () X{ expavoidval = avoid(); X restinlight = (on (ROOM) && !darkroom ()); X restinroom = on (ROOM); X return (1); X} X Xrestvalue (r, c, depth, val, avd, cont) Xregister int r, c; Xint depth, *val, *avd, *cont; X{ register int dr, dc, ar, ac; X int count, dir, rm; X X /* Find room number for diagonal selection */ X if ((rm = whichroom (r, c)) < 0) rm = 4; X X /* Default is no value, no avoidance */ X *avd = *val = 0; X X /* Set base value of square */ X if (onrc (TRAP|MONSTER,r, c)) { *avd = INFINITY; return (0); } X else if (restinroom && onrc (DOOR,r, c)) { *avd = INFINITY; return (0); } X else if (onrc (SCAREM, r, c)) X { if (objcount == maxobj || version >= RV53A) { *val = 500; return (1); } X else { *avd = INFINITY; return (0); } X } X else if (onrc (STAIRS, r, c)) { *val = 400; return (1); } X else if (onrc (ROOM, r, c)) { *val = 1; *cont = 99;} X else if (!onrc (SAFE|BEEN|STUFF, r, c)) { *avd = 5; } X X /* Give bonus for being next to a trap door or a teleport trap */ X if (onrc (TRAPDOR|TELTRAP, r-1, c-1) || onrc (TRAPDOR|TELTRAP, r+1, c-1) || X onrc (TRAPDOR|TELTRAP, r-1, c+1) || onrc (TRAPDOR|TELTRAP, r+1, c+1)) X { *val += 80; *cont = 99;} X X if (onrc (TRAPDOR|TELTRAP, r-1, c) || onrc (TRAPDOR|TELTRAP, r+1, c) || X onrc (TRAPDOR|TELTRAP, r, c-1) || onrc (TRAPDOR|TELTRAP, r, c+1)) X { *val += 30; *cont = 99;} X X /* In lit rooms (with ammo) stay away from doors, this gives us time */ X /* to shoot arrows at monsters coming in at us MLM 06/21/83 */ X if (restinlight && ammo) X { for (dir = 0; dir < 8; dir += 2) X { dr = deltr[dir]; dc = deltc[dir]; X for (count = 0, ar = r+dr, ac = c+dc; X onrc (CANGO | HALL | MONSTER, ar, ac) == CANGO; X ar += dr, ac += dc, count++) X { /* Bonus of 'count' if this square covers a door */ X if (onrc(DOOR,ar+deltr[(dir+2)%8],ac+deltc[(dir+2)%8])) *val += count; X if (onrc(DOOR,ar+deltr[(dir+6)%8],ac+deltc[(dir+6)%8])) *val += count; X if (onrc(DOOR,ar,ac)) *val += count; X } X } X } X X /* In dark rooms, stand diagonally away from doors (1 extra turn) */ X else if (onrc (ROOM, r, c)) X { if (onrc (DOOR,r-1,c-1) && (rm!=0 && rm!=1 && rm!=3)) {*val+=80;*cont=99;} X if (onrc (DOOR,r+1,c-1) && (rm!=3 && rm!=6 && rm!=7)) {*val+=80;*cont=99;} X if (onrc (DOOR,r-1,c+1) && (rm!=1 && rm!=2 && rm!=5)) {*val+=80;*cont=99;} X if (onrc (DOOR,r+1,c+1) && (rm!=5 && rm!=7 && rm!=8)) {*val+=80;*cont=99;} X X /* Bonus for door also orthogonally away */ X if(onrc(DOOR,r,c-1)||onrc(DOOR,r-1,c)||onrc(DOOR,r,c+1)||onrc(DOOR,r+1,c)) X { *val+=30; *cont=99; } X } X X return (1); X} / echo 'x - utility.c' sed 's/^X//' > utility.c << '/' X/* X * utility.c: Rog-O-Matic XIV (CMU) Thu Jan 31 18:18:22 1985 - mlm X * Copyright (C) 1985 by A. Appel, G. Jacobson, L. Hamey, and M. Mauldin X * X * This file contains all of the miscellaneous system functions which X * determine the baud rate, time of day, etc. X */ X X# include X# include X# include X# include X# include X X# include "install.h" X X# ifdef BSD41 X# include X# else X# include X# endif X X# define TRUE 1 X# define FALSE 0 X X/* X * baudrate: Determine the baud rate of the terminal X */ X Xbaudrate () X{ static short baud_convert[] = X { 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600 }; X static struct sgttyb sg; X static short baud_rate; X X gtty (fileno (stdin), &sg); X baud_rate = sg.sg_ospeed == 0 ? 1200 X : sg.sg_ospeed < sizeof baud_convert / sizeof baud_convert[0] X ? baud_convert[sg.sg_ospeed] : 9600; X X return (baud_rate); X} X X/* X * stlmatch -- match leftmost part of string X * X * Usage: i = stlmatch (big,small) X * int i; X * char *small, *big; X * X * Returns 1 iff initial characters of big match small exactly; X * else 0. X * X * HISTORY X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University X * Ripped out of CMU lib for Rog-O-Matic portability X * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University X * Rewritten for VAX from Ken Greer's routine. X * X * Originally from klg (Ken Greer) on IUS/SUS UNIX X */ X Xint stlmatch (big, small) Xchar *small, *big; X{ register char *s, *b; X s = small; X b = big; X do X { if (*s == '\0') X return (1); X } X while (*s++ == *b++); X return (0); X} X X/* X * getname: get userid of player. X */ X Xchar *getname () X{ static char name[100]; X int i; X X getpw (getuid (), name); X i = 0; X while (name[i] != ':' && name[i] != ',') X i++; X name[i] = '\0'; X X return (name); X} X X/* X * putenv -- put value into environment X * X * Usage: i = putenv (name,value) X * int i; X * char *name, *value; X * X * Putenv associates "value" with the environment parameter "name". X * If "value" is 0, then "name" will be deleted from the environment. X * Putenv returns 0 normally, -1 on error (not enough core for malloc). X * X * Putenv may need to add a new name into the environment, or to X * associate a value longer than the current value with a particular X * name. So, to make life simpler, putenv() copies your entire X * environment into the heap (i.e. malloc()) from the stack X * (i.e. where it resides when your process is initiated) the first X * time you call it. X * X * HISTORY X * 25-Nov-82 Michael Mauldin (mlm) at Carnegie-Mellon University X * Ripped out of CMU lib for Rog-O-Matic portability X * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University X * Created for VAX. Too bad Bell Labs didn't provide this. It's X * unfortunate that you have to copy the whole environment onto the X * heap, but the bookkeeping-and-not-so-much-copying approach turns X * out to be much hairier. So, I decided to do the simple thing, X * copying the entire environment onto the heap the first time you X * call putenv(), then doing realloc() uniformly later on. X * Note that "putenv(name,getenv(name))" is a no-op; that's the reason X * for the use of a 0 pointer to tell putenv() to delete an entry. X * X */ X X#define EXTRASIZE 5 /* increment to add to env. size */ X Xchar *index (), *malloc (), *realloc (); Xint strlen (); X Xstatic int envsize = -1; /* current size of environment */ Xextern char **environ; /* the global which is your env. */ X Xstatic int findenv (); /* look for a name in the env. */ Xstatic int newenv (); /* copy env. from stack to heap */ Xstatic int moreenv (); /* incr. size of env. */ X Xint putenv (name, value) Xchar *name, *value; X{ register int i, j; X register char *p; X X if (envsize < 0) X { /* first time putenv called */ X if (newenv () < 0) /* copy env. to heap */ X return (-1); X } X X i = findenv (name); /* look for name in environment */ X X if (value) X { /* put value into environment */ X if (i < 0) X { /* name must be added */ X for (i = 0; environ[i]; i++); X if (i >= (envsize - 1)) X { /* need new slot */ X if (moreenv () < 0) X return (-1); X } X p = malloc (strlen (name) + strlen (value) + 2); X if (p == 0) /* not enough core */ X return (-1); X environ[i + 1] = 0; /* new end of env. */ X } X else X { /* name already in env. */ X p = realloc (environ[i], X strlen (name) + strlen (value) + 2); X if (p == 0) X return (-1); X } X sprintf (p, "%s=%s", name, value);/* copy into env. */ X environ[i] = p; X } X else X { /* delete name from environment */ X if (i >= 0) X { /* name is currently in env. */ X free (environ[i]); X for (j = i; environ[j]; j++); X environ[i] = environ[j - 1]; X environ[j - 1] = 0; X } X } X X return (0); X} X Xstatic int findenv (name) Xchar *name; X{ register char *namechar, *envchar; X register int i, found; X X found = 0; X for (i = 0; environ[i] && !found; i++) X { envchar = environ[i]; X namechar = name; X while (*namechar && (*namechar == *envchar)) X { namechar++; X envchar++; X } X found = (*namechar == '\0' && *envchar == '='); X } X return (found ? i - 1 : -1); X} X Xstatic int newenv () X{ register char **env, *elem; X register int i, esize; X X for (i = 0; environ[i]; i++); X esize = i + EXTRASIZE + 1; X env = (char **) malloc (esize * sizeof (elem)); X if (env == 0) X return (-1); X X for (i = 0; environ[i]; i++) X { elem = malloc (strlen (environ[i]) + 1); X if (elem == 0) X return (-1); X env[i] = elem; X strcpy (elem, environ[i]); X } X X env[i] = 0; X environ = env; X envsize = esize; X return (0); X} X Xstatic int moreenv () X{ register int esize; X register char **env; X X esize = envsize + EXTRASIZE; X env = (char **) realloc (environ, esize * sizeof (*env)); X if (env == 0) X return (-1); X environ = env; X envsize = esize; X return (0); X} X X/* X * wopen: Open a file for world access. X */ X XFILE *wopen(fname, mode) Xchar *fname, *mode; X{ int oldmask; X FILE *newlog; X X oldmask = umask (0111); X newlog = fopen (fname, mode); X umask (oldmask); X X return (newlog); X} X X/* X * fexists: return a boolean if the named file exists X */ X Xfexists (fn) Xchar *fn; X{ struct stat pbuf; X X return (stat (fn, &pbuf) == 0); X} X X/* X * filelength: Do a stat and return the length of a file. X */ X Xint filelength (f) X{ struct stat sbuf; X X if (stat (f, &sbuf) == 0) X return (sbuf.st_size); X else X return (-1); X} X X/* X * critical: Disable interrupts X */ X Xstatic int (*hstat)(), (*istat)(), (*qstat)(); X Xcritical () X{ X hstat = signal (SIGHUP, SIG_IGN); X istat = signal (SIGINT, SIG_IGN); X qstat = signal (SIGQUIT, SIG_IGN); X} X X/* X * uncritical: Enable interrupts X */ X Xuncritical () X{ X signal (SIGHUP, hstat); X signal (SIGINT, istat); X signal (SIGQUIT, qstat); X} X X/* X * reset_int: Set all interrupts to default X */ X Xreset_int () X{ X signal (SIGHUP, SIG_DFL); X signal (SIGINT, SIG_DFL); X signal (SIGQUIT, SIG_DFL); X} X X/* X * int_exit: Set up a function to call if we get an interrupt X */ X Xint_exit (exitproc) Xint (*exitproc)(); X{ X if (signal (SIGINT, SIG_IGN) != SIG_IGN) signal (SIGINT, exitproc); X if (signal (SIGPIPE, SIG_IGN) != SIG_IGN) signal (SIGPIPE, exitproc); X if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) signal (SIGQUIT, exitproc); X} X X/* X * lock_file: lock a file for a maximum number of seconds. X * Based on the method used in Rogue 5.2. X */ X X# define NOWRITE 0 X Xlock_file (lokfil, maxtime) Xchar *lokfil; Xint maxtime; X{ int try; X struct stat statbuf; X time_t time (); X X start: X if (creat (lokfil, NOWRITE) > 0) X return TRUE; X X for (try = 0; try < 60; try++) X { sleep (1); X if (creat (lokfil, NOWRITE) > 0) X return TRUE; X } X X if (stat (lokfil, &statbuf) < 0) X { creat (lokfil, NOWRITE); X return TRUE; X } X X if (time (NULL) - statbuf.st_mtime > maxtime) X { if (unlink (lokfil) < 0) X return FALSE; X goto start; X } X else X return FALSE; X} X X/* X * unlock_file: Unlock a lock file. X */ X Xunlock_file (lokfil) Xchar *lokfil; X{ unlink (lokfil); X} X X/* X * quit: Defined for compatibility with Berkeley 4.2 system X */ X Xquit (code, fmt, a1, a2, a3, a4) Xint code, a1, a2, a3, a4; Xchar *fmt; X{ X fprintf (stderr, fmt, a1, a2, a3, a4); X exit (code); X} / echo 'Part 02 of Rog-O-Matic XIV complete.' exit