Article View: comp.sources.apple2
Article #80v001SRC065: Robots for HyperC
From: Jonathan A. Chandross
Date: Sun, 08 Nov 1992 23:12
Date: Sun, 08 Nov 1992 23:12
806 lines
22956 bytes
22956 bytes
Submitted-by: Andy Tefft (teffta@tsengr.dnet.ge.com)
Posting-number: Volume 1, Source:65
Archive-name: games/c/robots
Architecture: ANY_2
Version-number: 2.5
The object of this game is to stay alive while robots chase you. If
a robot catches you, you die. You are given two weapons in your fight:
a teleportation device and a blaster. When two robots crash into each
other they create a junk heap; junk heaps are deadly to other robots.
You are allowed to move junk heaps around. When all the robots are
junk heaps, you advance to the next level.
Enjoy.
=Read.Me
-
-Robots
-
-The object of this game is to stay alive while robots chase you. If
-a robot catches you, you die. You are given two weapons in your fight:
-a teleportation device and a blaster. When two robots crash into each
-other they create a junk heap; junk heaps are deadly to other robots.
-You are allowed to move junk heaps around. When all the robots are
-junk heaps, you advance to the next level.
-
-This version of robots is based on the robots game that is usually
-distributed with Unix. It is not a port, however, but written mostly
-on my Apple //c under Hyperc. This is version 2.5. It should be
-slightly faster than previous versions in the higher levels (results
-vary), and fixes the unlimited blast bug. Revision history is in robots.c.
-
-Files:
- Read.Me This file
- ccrobots script to compile and link source files
- ladd.c ladd() function (see robots.doc)
- lnkrobots script to just link object files
- robots.c HyperC source
- robots.doc Documentation
- robots.files list of files for linker to link
- uitostr.c uitostr() function (see robots.doc)
-
-
-Andrew Tefft
-TEFFTA@tsengr.dnet.ge.com
-July 1992
-Version 2.5
-
=Manifest
-Read.Me
-ccrobots
-ladd.c
-lnkrobots
-robots.c
-robots.doc
-robots.files
-uitostr.c
=ccrobots
-/csys/bin/ppf -i |/ram/|/csys/hdrs/ -o $1.p $1.c
-/csys/bin/hyperc -o $1.s $1.p
-rm $1.p
-/csys/bin/asmcp -o $1.o $1.s
-rm $1.s
-lnk -l |/ram/|/csys/libs/ -o robots -as &s.o robots.o ladd.o &mylib &libc
-
=ladd.c
-/* for some reason ladd is unresolved so... */
-
-/* this version of ladd just adds the lsb of src to the array dest. */
-
-ladd(dest,src)
-unsigned int dest[2],src[2];
-{
-int t;
-t=dest[1]+src[1];
-if (t < dest[1]) dest[0]++;
-dest[1]=t;
-}
-
=lnkrobots
-lnk -l |/ram/|/csys/libs/ -o robots -asi robots.files
=robots.c
-/* robots by Andy Tefft, 6/28/92
-
-version 1.0: 6/28/92 (original)
-version 2.0: 6/29/92 (pushable piles) (developed under unix)
-version 2.1: 6/29/92 (2-move robots) (developed under unix)
-version 2.2: 6/29/92 (ported back to hyperc)
-version 2.3: 6/29/92 - disable / until it works
- - add blast command
- - various scoring changes
-version 2.4: 7/4/92 attempt to use long integer array for score
-version 2.5: 7/8/92 added first & last for faster looping
-*/
-
-#define VER "2.5"
-
-#include <std.h>
-
-#define XSIZE 79
-#define YSIZE 22
-#define ROBOT(x) robot_string[robot_moves[x]]
-
-char robot_moves[251];
-char robot_x[251],robot_y[251],player_x,player_y; /* position;
- x=255 means dead */
-char field[XSIZE+1][YSIZE+1]; /* grid array. 0: empty
- 1 - 250: robot #
- 253: wall
- 254: pile
- 255: player */
-
-char pile_x[250],pile_y[250];
-
-int RANDSeed=5343;
-int first,last,blasts,piles,safe_teleports,score[2];
-char get_cmd,rndl,robot_string[4];
-
-main() {
-int result,number; /* number of robots */
-
-printf("Robots by Andy Tefft, version %s.\n",VER);
-
-robot_string=" #&";
-
-while (1) {
- putstr("Seeding random number generator now...\n");
- rs(); /* randomize rndl */
- srandom( (unsigned int) rndl); /* seed with randomized # */
-
- score[0]=0,score[1]=0;
- safe_teleports=0;
- blasts=1;
-
- for (number=10 ;; ++safe_teleports, ++blasts, number += (number < 240) * 10){
-
- init(number); /* initialize arrays to 0 */
- randomize(number); /* fill screen with n robots */
- screensetup(number);
- first=1; last=number;
- get_cmd=0;
-
-while (1) {
- cursor(player_y,player_x);
- result=get_player_move(number);
- if (result==2) quit();
- if (!result) if ((result=robot_move(number))) break;
-}
- if (result==2) { quit(); break; } /* died */
- /* otherwise result==-1 which means end of level so continue */
-}
-}
-}
-
-quit() {
-char key;
- cursor(23,0);
- putstr("\nYour score was: ");
- prscore();
- putstr("\nPress q to quit, any other key to play again: ");
- key=getkey(1);
- cr();
- if (key=='q') exit(0);
-}
-
-/* A random number generator */
-
-srandom(NewSeed)
-int NewSeed;
-
-{
-RANDSeed = NewSeed;
-}
-
-unsigned int random()
-{
- RANDSeed = RANDSeed * 18627;
- if (RANDSeed < 0)
- RANDSeed += 32768;
- return RANDSeed;
-}
-
-#define FIELD(n) field[robot_x[n]][robot_y[n]]
-
-/* robot_move moves the robots, creates piles, checks for dead player.
- returns:
- 0: robots & player are alive
- 2: player died
- -1: all robots are dead
-*/
-
-robot_move(number)
-int number;
-{
-int flag,i,alive,x,n,nx,ny;
-
-for (n=last,flag=0,alive=1; n>=first; n--) {
- if (robot_x[n]==255) continue;
-
- for(i=0; i<robot_moves[n]; i++) {
-
- if (FIELD(n)==n) {
- FIELD(n) = 0;
- cursor(robot_y[n],robot_x[n]);
- putchr(' '); /* blank out old position */
- }
-
- if (robot_x[n] > player_x) --robot_x[n];
- else if (robot_x[n] < player_x) ++robot_x[n];
- if (robot_y[n] > player_y) --robot_y[n];
- else if (robot_y[n] < player_y) ++robot_y[n];
-
- nx=robot_x[n]; ny=robot_y[n];
-
- cursor(ny,nx);
-
- if ((x=FIELD(n)) > n) {
- if (x==255) {
- return 2; /* player just died */
- }
- addscore(number*robot_moves[n]);
- if (get_cmd=='w') addscore(number*robot_moves[n]);
-
- FIELD(n) = 254; /* pile */
-/*
- pile_x[++piles]=robot_x[n];
- pile_y[piles]=robot_y[n];
-*/
- robot_x[n]=255; /* this robot is dead */
- if (x != 254) {
- robot_x[x] = 255; /* kill the other robot too */
- addscore(number*robot_moves[x]);
- if (get_cmd=='w') addscore(number*robot_moves[x]);
- }
- putchr('*'); /* draw pile */
- break; /* don't try and move a dead robot */
- }
- else {
- FIELD(n)=n;
- putchr(ROBOT(n));
- alive=0;
- if (!flag) last=n;
- flag=n;
- }
- }
- if (robot_x[n]==255) continue; /* 2-mover just died */
-}
-first=flag;
-return (-alive);
-}
-
-/* return values:
- 0: normal move
- 1: don't move robots
- 2: quit
-*/
-
-get_player_move(number)
-int number;
-{
-char move;
-int ox,oy,ox1,oy1;
-
- if (!get_cmd) move = getkey();
- else move=get_cmd;
-
- if (!index(" .?qtrhjklyubnw>HJKLYUBNz",move)) return 1; /* legal moves */
- if (move=='q') return 2;
-
- if (move=='t' && !safe_teleports) return 1;
- if (move=='r' || move=='t') {
- field[player_x][player_y]=0;
- cursor(player_y,player_x);
- putchr(' ');
-
- if (move=='r') do {
- player_x=random()%(XSIZE-1)+1;
- player_y=random()%(YSIZE-1)+1;
- } while (field[player_x][player_y]);
-
- else do {
- player_x=random()%(XSIZE-1)+1;
- player_y=random()%(YSIZE-1)+1;
- } while (!safe_pos(player_x,player_y));
- if (move=='t') safe_teleports--;
-
- field[player_x][player_y]=255;
- cursor(player_y,player_x);
- putchr('@');
- cursor(player_y,player_x);
- return 0;
- }
-
- if (move=='.') return 0;
-
- if (move=='?') {
- cursor(23,0);
- putstr("hjklyubn move, . stay, r/t rand/safe, z blast sc: ");
- prscore();
- printf(" tele: %d bl: %d (%d)",safe_teleports,blasts,
- number/10);
- return 1; /* don't do robot move */
- }
-
- if (move==' ') return print_safe();
-
- if (move=='z') return blast();
-
- if (move=='/') {
- screensetup(number);
- return 1;
- }
-
- if (move=='w') {
- get_cmd='w'; return 0;
- }
-
- else if (move=='>') {
- if (safe_pos(player_x,player_y)) {
- get_cmd='>'; return 0;
- } else {
- get_cmd=0; return 1;
- }
- }
-
-/* all commands previous to this point MUST contain a return! */
-
- ox=player_x; oy=player_y;
- field[player_x][player_y]=0;
- cursor(player_y,player_x);
- putchr(' ');
-
-/* move-while-safe moves */
-
- if (move=='H') {
- if (!move_if_safe(player_x-1,player_y)) return put_n_stop();
- else get_cmd='H';
- }
- else if (move=='J') {
- if (!move_if_safe(player_x,player_y+1)) return put_n_stop();
- else get_cmd='J';
- }
- else if (move=='K') {
- if (!move_if_safe(player_x,player_y-1)) return put_n_stop();
- else get_cmd='K';
- }
- else if (move=='L') {
- if (!move_if_safe(player_x+1,player_y)) return put_n_stop();
- else get_cmd='L';
- }
- else if (move=='Y') {
- if (!move_if_safe(player_x-1,player_y-1)) return put_n_stop();
- else get_cmd='Y';
- }
- else if (move=='U') {
- if (!move_if_safe(player_x+1,player_y-1)) return put_n_stop();
- else get_cmd='U';
- }
- else if (move=='B') {
- if (!move_if_safe(player_x-1,player_y+1)) return put_n_stop();
- get_cmd='B';
- }
- else if (move=='N') {
- if (!move_if_safe(player_x+1,player_y+1)) return put_n_stop();
- get_cmd='N';
- }
-
-/* regular moves */
-
- ox1=player_x; oy1=player_y;
-
- if ((move=='h' || move=='y' || move=='b') && player_x > 1 )
- --ox1;
- if ((move=='l' || move=='n' || move=='u') && player_x < XSIZE-1)
- ++ox1;
- if ((move=='j' || move=='b' || move=='n') && player_y < YSIZE-1)
- ++oy1;
- if ((move=='k' || move=='y' || move=='u') && player_y > 1)
- --oy1;
-
- if (field[ox1][oy1]==254) move_pile(ox1,oy1,ox1-player_x,oy1-player_y);
-
- if (!field[ox1][oy1]) player_x=ox1,player_y=oy1;
-
- field[player_x][player_y]=255;
- cursor(player_y,player_x);
-
- putchr('@');
-
- cursor(player_y,player_x);
-
- return (ox==player_x && oy==player_y);
-}
-
-blast() {
-int i,j,x;
- if (!blasts) return 1;
- blasts--;
- for (i=-1; i<2; i++)
- for (j=-1; j<2; j++)
- if ((x=(int)field[player_x+i][player_y+j]) < 251
- && x>0) {
- cursor(player_y+j,player_x+i);
- putchr(' ');
- field[player_x+i][player_y+j]=0;
- robot_x[x]=255;
- }
- return 0;
-}
-
-
-/* move_if_safe(x,y) updates player_x and player_y to x,y if x,y is
- a safe position. It does not update field[][]. Returns 1 if moved. */
-
-move_if_safe(x,y)
-int x,y;
-{
- if (safe_pos(x,y)) {
- player_x=x,player_y=y;
- return 1;
- } else return 0;
-}
-
-
-/* put_n_stop() can be used anytime it is needed to draw the player
- and update the field[][] array with his position. */
-
-put_n_stop() {
- get_cmd=0;
- cursor(player_y,player_x);
- putchr('@');
- field[player_x][player_y]=255;
- return 1;
-}
-
-/* move_pile moves pile from (x,y) to (x+dx,y+dy) if possible. returns 1
- if successful */
-
-move_pile(x,y,dx,dy)
-int x,y,dx,dy;
-{
-if (field[x+dx][y+dy]) return 0;
-field[x][y]=0;
-field[x+dx][y+dy]=254;
-cursor(y,x);
-putchr(' ');
-cursor(y+dy,x+dx);
-putchr('*');
-return 1;
-}
-
-/* safe_pos checks to see if pos (x,y) would be safe to go to. returns 1
- unless:
-
- - wall or pile is there
- - robot would move there if player moved there
-*/
-
-safe_pos(x,y)
-int x,y;
-{
-int i,j;
-
- if (field[x][y]) if (field[x][y] != 255) return 0;
- for (i=-2; i<3; i++)
- for (j=-2; j<3; j++) {
- if (x+i<0 || x+i>XSIZE || y+j<0 || y+j>YSIZE) continue;
- if (field[x+i][y+j]) if (field[x+i][y+j] < 251) {
- if (abs(i)<2 && abs(j)<2) return 0;
- if (robot_moves[field[x+i][y+j]] == 2 &&
- field[x+i/2][y+j/2] != 253) return 0;
- }
- }
- return 1;
-}
-
-init(number)
-int number;
-{
-int x,y;
-
-page();
-printf("initializing...\n");
-
-piles=0;
-for (x=0; x<XSIZE; x++)
- for (y=0; y<YSIZE; y++)
- field[x][y]=0;
-
-}
-
-randomize(number)
-int number;
-{
-int i,x,y;
-putstr("Randomizing...\n");
-for (i=1; i<=number; i++) {
- do {
- x=random()%(XSIZE-1)+1;
- y=random()%(YSIZE-1)+1;
- }
- while (field[x][y]!=0);
-
- robot_x[i]=x; robot_y[i]=y;
- field[x][y]=i;
-
- if (random()%10==2) robot_moves[i]=2;
- else robot_moves[i]=1;
-}
-
- do {
- x=random()%(XSIZE-1)+1;
- y=random()%(YSIZE-1)+1;
- }
- while (field[x][y]!=0);
-
- player_x=x; player_y=y;
- field[x][y]=255;
-}
-
-screensetup(n)
-int n;
-{
-int i;
-
-page();
-
-for (i=0; i<= XSIZE; i++) { putchr('-'); field[i][0]=253; }
-cursor(YSIZE,0);
-for (i=0; i<= XSIZE; i++) { putchr('-'); field[i][YSIZE]=253; }
-
-for (i=1; i<YSIZE; i++) {
- cursor(i,0);
- putchr('|');
- cursor(i,XSIZE);
- putchr('|');
- field[0][i]=253;
- field[XSIZE][i]=253;
-}
-
-for (i=1; i<=n; i++) {
- cursor(robot_y[i],robot_x[i]);
- putchr(ROBOT(i));
-}
-
-for (i=0; i<piles; i++) {
- cursor(pile_y[i],pile_x[i]);
- putchr('*');
-}
-
-cursor(player_y,player_x);
-putchr('@');
-
-}
-
-/* rs waits for a keypress, scrambling rndl until pressed. This seeds
- the random number generator. */
-
-rs() {
-printf("Press a key to begin...");
-while (!keypress()) ++rndl;
-return 0;
-}
-
-/* print_safe() is a kludge to print out the safe moves. */
-
-print_safe() {
-cursor(23,0);
-
-clreol();
-
-if (safe_pos(player_x-1,player_y)) putchr('h');
-if (safe_pos(player_x,player_y-1)) putchr('k');
-if (safe_pos(player_x,player_y+1)) putchr('j');
-if (safe_pos(player_x+1,player_y)) putchr('l');
-if (safe_pos(player_x-1,player_y-1)) putchr('y');
-if (safe_pos(player_x+1,player_y-1)) putchr('u');
-if (safe_pos(player_x-1,player_y+1)) putchr('b');
-if (safe_pos(player_x+1,player_y+1)) putchr('n');
-if (safe_pos(player_x,player_y)) putchr('.');
-
-return 1;
-}
-
-/* addscore adds int i to score[2] */
-
-addscore(i)
-int i;
-{
-int i2[2];
-
-i2[0]=0;
-i2[1]=i;
-
-ladd(score,i2);
-}
-
-/* prscore prints the score in ascii */
-
-prscore() {
-char scorestr[9];
-
-uitostr2(scorestr,score);
-putstr(scorestr);
-}
-
=robots.doc
-This version of robots is based on the robots game that is usually
-distributed with Unix. It is not a port however, but written mostly on
-my Apple //c under Hyperc. The SYS file version was created with the
-use of Gary Desrochers and Andy Werner's 'makesys' programs.
-
-The object of the game is to stay alive while robots chase after you.
-These robots are evil in that they will kill you if they catch you. However,
-they are also stupid, and tend to crash into each other.
-
-You are given two weapons in your fight. One is a teleportation device.
-You are allowed unlimited random teleports (which can drop you right into
-danger), and a limited number of 'guaranteed safe' teleports. You also
-have a blaster which has limited uses; it destroys all robots adjacent
-to you but does not stop the rest from advancing.
-
-When two robots crash into each other, they create a junk heap and you
-get points. Robots which run into junk heaps are also destroyed, giving you
-more points. If a robot runs into you, you die and the game ends. You cannot
-run into junk heaps or the screen borders. You can push a junk heap in any
-direction as long as there is a blank space to move it into.
-
-When all the robots are junk heaps, you advance to the next level.
-You gain one safe teleportation and one blast, and the next level contains
-more robots (up to a maximum of 250). (if all the robots are dead but you
-have not advanced to the next level, press any movement key.)
-
-You are represented on the screen by an inverse '@'. Robots are '#' and
-'&'; the latter move twice as fast as the former. Junk heaps are '*'. Borders
-are obvious.
-
-Keys are as follows (and are the same as vi cursor-motion keys):
-
- y k u >: wait as long as it's safe
- \ | / w: wait until level is cleared or you die
- h - - l .: wait one move
- / | \
- b j n
-
-YUHJKLBN: run in that direction as long as it's safe
-?: show brief help, # of safe teleports (te:), # of blasts (bl:), score (sc:),
- and level
-z: blast (or think of it as zap)
-<space>: show safe moves
-q: quit
-
-Scoring: each '#' robot is worth 10 points times the level number. '&' robots
-are worth double. Each dead robot after you press 'w' is worth double its
-usual value. Robots that you blast are worth 0.
-
------------------------------------------------------------------------
-planned future enhancements:
-
-- high score list
-- ability to skip lower levels
-
------------------------------------------------------------------------
-The files:
-
-robots.doc: this file
-robots: hyperc executable
-robots.c: hyperc source
-robots.system: prodos SYS file
-ladd.c: the ladd() function (see below)
-uitostr.c: the uitostr() function (see below)
-ladd.o, uitostr.o
-robots.files: list of files to link; use -i option with the linker
-lnkrobots: the link command in a script
-
-Please send me any bug reports or enhancements (I'm particularly looking
-for speed improvements and a better random-number generator).
-
-Andy Tefft
-teffta@tsengr.dnet.ge.com
-6/30/90
-------------------------------------------------------------------------
-Version 2.4 (7/4/92):
-
-You only need read this section if you plan on compiling the program.
-You can play robots without compiling the program. You would only need
-to recompile it if you make changes.
-
-So that the score doesn't "roll over" at 65536, I now use a two-integer
-array to store the score. At this time I have decided to start splitting
-up the source because it is taking a long time to compile. Therefore
-this distribution contains two extra files: uitostr.[c,o] and ladd.[c,o].
-
-To compile robots, you now must follow these steps:
-
-1) cc ladd, if ladd.o does not exist (the 'lnk' command will fail,
- but we just need the ladd.o file anyway)
-2) cc uitostr, if uitostr.o does not exist
-
-(note: I have included uitostr.o and ladd.o in the distribution so
-you don't have to compile them again unless you change them)
-
-3) cc robots
-4) do 'lnkrobots' or else type in the lnk command yourself.
-
-Note that you only have to cc the files you change; keep the .o files
-around so that you can just redo 'lnkrobots' after you change & cc
-one or more of the source files.
-
-note on ladd:
-
-ladd(ldest,lsrc) is listed in the hyperc manual. lib /csys/libs/libc shows
-ladd.o. But I kept getting _ladd: unresolved when I linked the program,
-so I wrote my own ladd() function. IMPORTANT: it does *not* add the
-most significant int of the arrays, even though it takes two arrays
-as arguments. I only needed to add an int to a 2-byte int array so that's
-all I made it do, although I made the calling interface the same as
-what the manual specifies.
-
-What this means to you is that if something is screwed up in my copy
-of hyperc, and your copy of hyperc includes ladd like it should, you
-will get a duplicate reference when you link it. If this should happen,
-just remove ladd.o from the 'robots.files' file which is used by the link
-command, and re-link. It should work.
-
-note on uitostr:
-
-It is ugly. If you have a better way to do it, send it to me! If you don't,
-and you want to use uitostr, feel free, and keep these things in mind:
-
-1) uitostr(str,i) converts the integer i[2] to the string str. i[0]
- is the *least* significant 16 bits of i.
-2) uitostr2(str,i) expects i[0] to be the *most* significant bits of i.
-3) i must be positive; it is actually treated as an unsigned int by
- the function. If you want to print a negative number, figure out
- how to take its absolute value, and print a - yourself.
-4) str must be declared with size of at least 9 -- up to 8 digits
- plus a trailing null. No checks are made on this size and the function
- will be more than happy to tromp on other variables if you declare
- the string too small.
-5) the string returned is right-justified. to print it without the leading
- spaces, you can do something like this:
-
- putstr(rindex(str,' ')+1);
-
- (rindex will return a pointer to the last ' ' character in the string).
-
-
=robots.files
-&s.o
-robots.o
-uitostr.o
-ladd.o
-&libc
=uitostr.c
-/* uitostr.c:
-
- prints a two-byte unsigned int in ascii.
- uitostr(buf,i) assumes i[2] with i[0]=least significant;
- uitostr2(buf,i) assumes i[0] is most significant
-
- note: uitostr destroys i; uitostr2 does not.
-*/
-
-
-#include <std.h>
-
-__twodiv(i) /* divides i by 10 and leaves the result in i */
-unsigned int i[2]; /* i[0] is lsb */
-{
-i[0]=(i[0]/10)+6553*(i[1]%10)+(i[0]%10+6*(i[1]%10))/10;
-i[1]=i[1]/10;
-}
-
-__mod10(i) /* returns i%10 */
-unsigned int i[2];
-{
-return (i[0]%10+(6*i[1])%10)%10;
-}
-
-uitostr(buf,i)
-char buf[9]; /* room for 8 chars */
-unsigned int i[2];
-{
-int j;
-for(j=7; j>=0; j--) {
- if (!(i[1]|i[0])) buf[j]=' ';
- else buf[j]=__mod10(i)+'0';
- __twodiv(i);
-}
-buf[8]=0;
-if (buf[7]==' ') buf[7]='0';
-return;
-}
-
-uitostr2(buf,i)
-char buf[9];
-unsigned int i[2];
-{
-unsigned int j[2];
-j[0]=i[1];
-j[1]=i[0];
-uitostr(buf,j);
-}
-
+ END OF ARCHIVE
Technical Details
Message-ID:
<Nov.8.18.12.09.1992.16069@yoko.rutgers.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!rutgers!igor.rutgers.edu!yoko.rutgers.edu!jacShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!rutgers!igor.rutgers.edu!yoko.rutgers.edu!jac From: jac@yoko.rutgers.edu (Jonathan A. Chandross) Newsgroups: comp.sources.apple2 Subject: v001SRC065: Robots for HyperC Message-ID: <Nov.8.18.12.09.1992.16069@yoko.rutgers.edu> Date: 8 Nov 92 23:12:10 GMT Organization: Rutgers Univ., New Brunswick, N.J. Lines: 806 Approved: jac@paul.rutgers.edu