Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 5/3/83; site cad.cs.cmu.edu.ARPA Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!harvard!seismo!rochester!pt.cs.cmu.edu!cad.cs.cmu.edu!mlm From: mlm@cad.cs.cmu.edu.ARPA (Michael Mauldin) Newsgroups: net.sources.games Subject: Rob-O-Matic: Plays the Robots Game Message-ID: <378@cad.cs.cmu.edu.ARPA> Date: Mon, 14-Oct-85 13:06:39 EDT Article-I.D.: cad.378 Posted: Mon Oct 14 13:06:39 1985 Date-Received: Thu, 17-Oct-85 00:47:54 EDT Organization: Carnegie-Mellon University, CS/RI Lines: 843 #!/bin/sh # # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # @ Here is your new automatic Robots player, Rob-O-Matic! @ # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ # # To unpack this program, run this message through 'unshar', or # remove the mail headers and pipe the body through the "sh" command. # Then "make" should build the program for you. # # A tradition of fine game playing programs, # from the People who brought you Rog-O-Matic. # # Michael L. Mauldin (Fuzzy) Department of Computer Science # Mauldin@CAD.CS.CMU.EDU Carnegie-Mellon University # (412) 578-3065 Pittsburgh, PA 15213 # echo 'Start of Rob-O-Matic Distribution:' echo 'x - robomatic.6' sed 's/^X//' > robomatic.6 << '/' X.TH ROBOMATIC 6 10/14/85 X.UC 4 X.SH NAME Xrobomatic \- Automatically Playing a Game of Logic X.SH SYNOPSIS X.I robomatic X[ X.I -d X] X.SH DESCRIPTION X.PP X.I Rob-O-Matic XPlays the "Robots" game written by XAllan Black of Strathclyde University, Glasgow. X.SH OPTIONS X.TP X.B -d XTurns on debugging. X.SH FILES X.PP XLooks for the Robots executable in the current directory, then in two Xplaces specified at compile-time (one of which is /usr/games). X.SH SEE ALSO X.PP Xrobots(6) X.SH BUGS X.PP XDoesn't play an optimum game. X.SH HISTORY X.TP X14-Oct-85 Michael Mauldin (mlm) at Carnegie-Mellon University XCreated. / echo 'x - robomatic.c' sed 's/^X//' > robomatic.c << '/' X/* robomatic.c: Rob-O-Matic I (CMU) Mon Oct 14 11:51:01 EDT 1985 - mlm */ X/***************************************************************** X * X * Rob-O-Matic: Play the robots game X * Copyright (C) 1985 by Mauldin X * The right is granted to any person, university, or company X * to copy, modify, or distribute (for free) this file, providing X * that this notice is not removed. X * X * HISTORY X * 11-Oct-85 Michael Mauldin (mlm) at Carnegie-Mellon University X * Created. X * X *****************************************************************/ X X# include X X# define NEWROBOT "/usr/mlm/bin/robots" X# define ROBOT "/usr/games/robots" X X# define READ 0 X# define WRITE 1 X# define abs(A) ((A)>0?(A):-(A)) X# define max(A,B) ((A)>(B)?(A):(B)) X# define sgn(A) ((A)==0?0:((A)>0?1:-1)) X X/* Define the Rob-O-Matic pseudo-terminal */ X X# define ROBOTTERM "rb|rterm:am:bs:ce=^E:cl=^L:cm=^F%+ %+ :co#80:li#24:pt:ta=^I:up=^A:do=^B:nd=^C:db:xn:" X# define ctrl(C) ((C)&037) X# define BL ctrl('G') X# define BS ctrl('H') X# define CE ctrl('E') X# define CL ctrl('L') X# define CM ctrl('F') X# define CR ctrl('M') X# define DO ctrl('B') X# define LF ctrl('J') X# define ND ctrl('C') X# define TA ctrl('I') X# define UP ctrl('A') X Xint child; Xint frobot, trobot; Xint debug=0; XFILE *trace=NULL; X/**************************************************************** X * Main routine X ****************************************************************/ X Xmain (argc, argv) Xint argc; Xchar *argv[]; X X{ int ptc[2], ctp[2]; X char *rfile=NULL; X X /* Get the options from the command line */ X while (--argc > 0 && (*++argv)[0] == '-') X { while (*++(*argv)) X { switch (**argv) X { case 'd': debug++; break; X default: printf ("Usage: robomatic [-d]\n"); exit (1); X } X } X } X X /* Open tracing file (if needed) */ X if (debug) X { if ((trace = fopen ("trace.log", "w")) == NULL) X { perror ("trace.log"); X exit (1); X } X } X X /* Find an executable of the robots game */ X if (access ("robots", 1) == 0) rfile = "robots"; X else if (access (NEWROBOT, 1) == 0) rfile = NEWROBOT; X else if (access (ROBOT, 1) == 0) rfile = ROBOT; X else X { perror ("robots"); X exit (1); X } X X /* Get two pipes to attach to the Robots process */ X if ((pipe (ptc) < 0) || (pipe (ctp) < 0)) X { fprintf (stderr, "Cannot get pipes!\n"); X exit (1); X } X X trobot = ptc[WRITE]; X frobot = ctp[READ]; X X /* Now fork a child process, update the TERMCAP, and exec the Robots */ X if ((child = fork ()) == 0) X { close (0); X dup (ptc[READ]); X close (1); X dup (ctp[WRITE]); X X putenv ("TERMCAP", ROBOTTERM); X execl (rfile, rfile, 0); X _exit (1); X } X X /* Call Robomatic as the Parent Process */ X else X { robomatic (); } X} X X/**************************************************************** X * Robomatic: Play Robots. Read the scrren, choose a move, and send it X ****************************************************************/ X X# define ROWS 24 X# define COLS 80 X Xchar screen[ROWS][COLS]; Xint playing=1; Xint row=0, col=0, atrow= -1, atcol= -1; X Xrobomatic () X{ int cmd; X X /* Initialize the Curses package */ X initscr (); crmode (); noecho (); clear (); refresh (); X X /* Clearn the screen array */ X blankscreen (); X X /* Read the first screen of output */ X send (';'); /* Cause robots to send a bell when ready to read cmd */ X getrobot (); /* Read screen updates until a bell */ X X /* Main loop, send a command and then read the screen */ X while (playing) X { X /* If the user types anything, execute his commands */ X while (charsavail (stdin)) X { switch (getchar ()) X { case 'd': debug++; X break; X case 'r': clear (); refresh (); drawscreen (); refresh (); X break; X default: break; X } X } X X /* Choose a command and send it */ X cmd = strategy (); X if (cmd == 0) { debug++; dwait ("command is zero"); } X dwait ("Sending command '%c'.", cmd); X send (cmd); X X /* Send the semicolon and read screen updates until a bell */ X send (';'); X getrobot (); X } X X /* Clear the scoreboard on some Robots */ X send ('\n'); X X /* Now wait for the user to type a character before finishing */ X refresh (); X getchar (); X X /* Print termination messages */ X move (ROWS-1, 0); clrtoeol (); refresh (); X endwin (); nocrmode (); noraw (); echo (); X X deadrobot (); X X exit (0); X} X X/**************************************************************** X * blankscreen: Fill the screen array with blanks X ****************************************************************/ X Xblankscreen () X{ register int i, j; X X for (i=0; i abs (dc)) X { sr = hr+sgn (dr); sc = hc; } X else X { sr = hr; sc = hc+sgn (dc); } X X /* If we are closer to the shadow square than the robot is, win */ X if (distance (sr, sc, tr, tc) > distance (hr, hc, atrow, atcol)) X { *pr = sr; *pc = sc; return (1); } X X /* Lose */ X return (0); X} X X/**************************************************************** X * findcollide: Find a robot to collide with a given robot. The target X * square will be the nearest safe square to the collision point. X ****************************************************************/ X Xfindcollide (tr, tc, pr, pc) Xint tr, tc, *pr, *pc; X{ int r=0, c=0, d, cr1, cc1, cr2, cc2; X X /* Search from target robot for another on the same row or column */ X for (d=1; d= ROWS || *pc < 1 || *pc > COLS) return (0); X X dwait ("predicting safe spot near collision (%d,%d)", *pr, *pc); X return (1); X } X X /* Check for two on same column */ X if (c == tc && c != atcol) X { /* Check collision left */ X cr1 = cr2 = (tr + r) / 2; X cc1 = tc - (d+1)/2 - 1; X cc2 = tc + (d+1)/2 + 1; X if (distance (atrow, atcol, cr1, cc1) < distance (atrow, atcol, cr2, cc2)) X { *pr = cr1; *pc = cc1; } X else X { *pr = cr2; *pc = cc2; } X X if (*pr < 1 || *pr >= ROWS || *pc < 1 || *pc > COLS) return (0); X X dwait ("predicting safe spot near collision (%d,%d)", *pr, *pc); X return (1); X } X X /* Fail */ X return (0); X} X X/**************************************************************** X * makemove: Return the direction to move toward a given square. This X * routine checks to make sure the move is a safe one. Returns 0 if no X * move is safe, and the character if one is found. X ****************************************************************/ X Xmakemove (r, c) X{ int dr, dc; X X dr = sgn (r-atrow); dc = sgn (c-atcol); X X if (dr && dc) X { if (safe (atrow+dr, atcol+dc)) return (keydir[3*dr + dc + 4]); X if (safe (atrow, atcol+dc)) return (keydir[ 0 + dc + 4]); X if (safe (atrow+dr, atcol )) return (keydir[3*dr + 0 + 4]); X } X else if (dr == 0) X { if (safe (atrow, atcol+dc)) return (keydir[ 0 + dc + 4]); X if (safe (atrow+1, atcol+dc)) return (keydir[ 3 + dc + 4]); X if (safe (atrow-1, atcol )) return (keydir[-3 + 0 + 4]); X } X else if (dc == 0) X { if (safe (atrow+dr, atcol )) return (keydir[3*dr + 0 + 4]); X if (safe (atrow, atcol+1)) return (keydir[3*dr + 1 + 4]); X if (safe (atrow+dr, atcol-1)) return (keydir[3*dr - 1 + 4]); X } X X dwait ("makemove: cannot move to (%d,%d) safely.", r, c); X return (0); X} X X/***************************************************************** X * charsavail: How many characters are there at the terminal? If any X * characters are found, 'noterm' is reset, since there is obviously X * a terminal around if the user is typing at us. X *****************************************************************/ X Xcharsavail () X{ long n; X int retc; X X if (retc = ioctl (READ, FIONREAD, &n)) X { fprintf (stderr, "Ioctl returns %d, n=%ld.\n", retc, n); X n=0; X } X X return ((int) n); X} X X/**************************************************************** X * dwait: Debugging message X ****************************************************************/ X Xdwait (f, a1, a2, a3, a4) Xchar *f; Xint a1, a2, a3, a4; X{ char buf[BUFSIZ]; X register int c; X X if (debug) X { mvprintw (0, 0, "[%d,%d] ", atrow, atcol); X printw (f, a1, a2, a3, a4); X addch (' '); X move (row, col); X refresh (); X switch (getchar ()) X { case 'd': debug=0; break; X case 'r': clear (); refresh (); drawscreen (); refresh (); break; X default: break; X } X for (c=0; c= (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} / echo 'x - Makefile' sed 's/^X//' > Makefile << '/' Xrobomatic: robomatic.c X cc -O -o robomatic robomatic.c -lcurses -ltermcap / echo 'Rob-O-Matic Distribution complete.' exit