|
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 n
Length: 17411 (0x4403) Types: TextFile Names: »newrobots.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Newrobots/newrobots.c«
/* Written by Allan R. Black, Strathclyde University. * This program may be freely distributed provided that * this comment is not removed and that * no profit is gained from such distribution. */ /* * @(#)robots.c 1.7 3/21/84 */ /* 1.7a modified by Stephen J. Muir at Lancaster University. */ /* * Sonic Screwdriver added by Bryan R. Davies at the Univ. of Texas at El Paso */ # include <curses.h> # include <signal.h> # include <pwd.h> # include <ctype.h> # include <sys/file.h> # define MIN_ROBOTS 10 # define MAX_ROBOTS 500 # define MIN_VALUE 10 # define MAX_FREE 3 # define SCREWDRIVERS #ifdef SCREWDRIVERS # define SSKEY 'z' #endif SCREWDRIVERS # define VERT '|' # define HORIZ '-' # define ROBOT '=' # define SCRAP '@' # define ME 'I' # define MUNCH '*' # define DOT '.' # define LEVEL (level+1) # define MSGPOS 39 # define RVPOS 51 # define HOF_FILE "/usr/games/lib/robots_hof" # define TMP_FILE "/usr/games/lib/robots_tmp" # define NUMSCORES 20 # define NUMNAME "Twenty" # define TEMP_DAYS 7 # define TEMP_NAME "Week" # define MAXSTR 100 extern char *getlogin(), *good_moves(); extern struct passwd *getpwnam (); struct scorefile { int s_uid; int s_score; char s_name[MAXSTR]; bool s_eaten; int s_level; int s_days; }; # define FILE_SIZE (NUMSCORES*sizeof(struct scorefile)) /*# define ALLSCORES*/ # define SECSPERDAY 86400 # define BEL 007 # define CTLH 010 # define CTLJ 012 # define CTLK 013 # define CTLL 014 # define CTLY 031 # define CTLU 025 # define CTLB 002 # define CTLN 016 # define CTLR 022 char whoami[MAXSTR]; #ifdef DIK int aflag; /* always give all possible moves */ int bflag; /* automatically execute some 'forced' moves */ int cflag; /* automatically execute 'forced' moves; never 'z' */ #endif DIK int my_x, my_y; int new_x, new_y; int level = 0; int score = 0; int free_teleports = 0; int free_per_level = 1; bool dead = FALSE; bool last_stand; int count; char com, cmd_ch; bool running, adjacent, first_move, bad_move; int dots = 0; int robot_value = MIN_VALUE; int max_robots = MIN_ROBOTS; int robots_alive; struct passwd *pass; struct robot { bool alive; int x; int y; } robot_list[MAX_ROBOTS]; int seed; struct ltchars ltc; char dsusp; int _putchar(); int interrupt(); char *forbidden [] = { "root", "daemon", "uucp", "pop", "ingres", "demo", "chessel", "saturn", "sjm", "cosmos", 0 }; main(argc,argv) int argc; char *argv[]; { register char *x, **xx; if(argc > 1) { if(argv[1][0] == '-') { switch(argv[1][1]) { case 's': scoring(FALSE); exit(0); #ifdef DIK case 'c': cflag++; /* fall into next case */ case 'b': bflag++; /* fall into next case */ case 'a': aflag++; #endif DIK } } } if ((x = getlogin ()) == 0 || (pass = getpwnam (x)) == 0) { printf ("Who the hell are you?\n"); exit (1); } strcpy(whoami,x); for (xx = forbidden; *xx; ++xx) if (strcmp (whoami, *xx) == 0) { printf ("only individuals may play robots\n"); exit (1); } seed = time(0)+pass->pw_uid; signal(SIGQUIT,interrupt); signal(SIGINT,interrupt); initscr(); if(COLS < 80) { printf("your screen is too small for robots\n"); exit(1); } crmode(); noecho(); ioctl(1,TIOCGLTC,<c); dsusp = ltc.t_dsuspc; ltc.t_dsuspc = ltc.t_suspc; ioctl(1,TIOCSLTC,<c); for(;;) { count = 0; running = FALSE; adjacent = FALSE; last_stand = FALSE; if(rnd(free_per_level) < free_teleports) { free_per_level++; if(free_per_level > MAX_FREE) free_per_level = MAX_FREE; } free_teleports += free_per_level; leaveok(stdscr,FALSE); draw_screen(); put_robots(); do { my_x = rndx(); my_y = rndy(); move(my_y,my_x); } while(winch(stdscr) != ' '); addch(ME); for(;;) { scorer(); if(robots_alive == 0) break; command(); robots(); if(dead) munch(); } if (!level) nice (2); msg("%d robots are now scrap heaps",max_robots); leaveok(stdscr,FALSE); move(my_y,my_x); refresh(); readchar(); level++; } } draw_screen() { register int x, y; clear(); for(y = 1; y < LINES-2; y++) { mvaddch(y,0,VERT); mvaddch(y,COLS-1,VERT); } for(x = 0; x < COLS; x++) { mvaddch(0,x,HORIZ); mvaddch(LINES-2,x,HORIZ); } } put_robots() { register struct robot *r, *end; register int x, y; robot_value += level*5+rnd(level*10); max_robots += level*3+rnd(level*5); if(max_robots > MAX_ROBOTS) max_robots = MAX_ROBOTS; robots_alive = max_robots; end = &robot_list[max_robots]; for(r = robot_list; r < end; r++) { for(;;) { x = rndx(); y = rndy(); move(y,x); if(winch(stdscr) == ' ') break; } r->x = x; r->y = y; r->alive = TRUE; addch(ROBOT); } } command() { register int x, y; #ifdef DIK if(aflag && last_stand) return; #endif DIK retry: move(my_y,my_x); refresh(); if(last_stand) return; #ifdef DIK if(aflag) { register char *a = good_moves(); move(my_y,my_x); refresh(); if(bflag) { if(cflag && level == 0 && (!equal_coord() || !a[0])) { cmd_ch = 'q'; goto do_it; } if(!a[0]) { cmd_ch = 't'; goto do_it; } if(a[0] == 's') { cmd_ch = 's'; goto do_it; } if((!a[1] || (cflag && a[1] == 'z')) && a[0] != 'z') { cmd_ch = a[0]; goto do_it; } } } #endif DIK bad_move = FALSE; if(!running) { cmd_ch = read_com(); do_it: running = FALSE; switch(cmd_ch) { case CTLH: case CTLJ: case CTLK: case CTLL: case CTLY: case CTLU: case CTLB: case CTLN: cmd_ch |= 0100; adjacent = TRUE; case 'H': case 'J': case 'K': case 'L': case 'Y': case 'U': case 'B': case 'N': cmd_ch |= 040; running = TRUE; first_move = TRUE; case 't': case 'T': #ifdef SCREWDRIVERS case SSKEY: case (SSKEY - 'a' + 'A'): #endif SCREWDRIVERS case 's': case 'S': case 'm': case 'M': case '?': case 'd': case 'D': case CTLR: count = 0; } } switch(cmd_ch) { case '.': return; case 'h': case 'j': case 'k': case 'l': case 'y': case 'u': case 'b': case 'n': do_move(cmd_ch); break; #ifdef SCREWDRIVERS case SSKEY: case (SSKEY - 'a' + 'A'): if(free_teleports > 0) { sonic_screwdriver(); free_teleports--; return; } bad_move = TRUE; break; #endif SCREWDRIVERS case 't': case 'T': teleport: new_x = rndx(); new_y = rndy(); move(new_y,new_x); switch(winch(stdscr)) { case ROBOT: case SCRAP: case ME: goto teleport; } if(free_teleports > 0) { for(x = new_x-1; x <= new_x+1; x++) { for(y = new_y-1; y <= new_y+1; y++) { move(y,x); if(winch(stdscr) == ROBOT) goto teleport; } } free_teleports--; } break; case 's': case 'S': last_stand = TRUE; leaveok(stdscr,TRUE); return; case 'm': case 'M': case '?': good_moves(); goto retry; case 'd': case 'D': if(dots < 2) { dots++; put_dots(); } else { erase_dots(); dots = 0; } goto retry; case 'q': case 'Q': quit(FALSE); case CTLR: clearok(curscr,TRUE); wrefresh(curscr); goto retry; default: bad_move = TRUE; } if(bad_move) { if(running) { if(first_move) putchar(BEL); running = FALSE; adjacent = FALSE; first_move = FALSE; } else { putchar(BEL); } refresh(); count = 0; goto retry; } first_move = FALSE; mvaddch(my_y,my_x,' '); my_x = new_x; my_y = new_y; move(my_y,my_x); if(winch(stdscr) == ROBOT) munch(); mvaddch(my_y,my_x,ME); refresh(); } read_com() { if(count == 0) { if (dots) { put_dots (); move (my_y, my_x); refresh (); } if(isdigit(com = readchar())) { count = com-'0'; while(isdigit(com = readchar())) count = count*10+com-'0'; } if (dots) erase_dots (); } if(count > 0) count--; return(com); } readchar() { static char buf[1]; while(read(0,buf,1) <= 0); return(buf[0]); } do_move(dir) char dir; { register int x, y; new_x = my_x+xinc(dir); new_y = my_y+yinc(dir); move(new_y,new_x); switch(winch(stdscr)) { case VERT: case HORIZ: case SCRAP: bad_move = TRUE; } if(adjacent & !first_move) { for(x = new_x-1; x <= new_x+1; x++) { for(y = new_y-1; y <= new_y+1; y++) { move(y,x); switch(winch(stdscr)) { case ROBOT: case SCRAP: bad_move = TRUE; return; } } } } } put_dots() { register int x, y; for(x = my_x-dots; x <= my_x+dots; x++) { if (x < 1 || x > COLS - 2) continue; for(y = my_y-dots; y <= my_y+dots; y++) { if (y < 1 || y > LINES - 3) continue; move(y,x); if(winch(stdscr) == ' ') addch(DOT); } } } erase_dots() { register int x, y; for(x = my_x-dots; x <= my_x+dots; x++) { if (x < 1 || x > COLS - 2) continue; for(y = my_y-dots; y <= my_y+dots; y++) { if (y < 1 || y > LINES - 3) continue; move(y,x); if(winch(stdscr) == DOT) addch(' '); } } } #ifdef SCREWDRIVERS sonic_screwdriver() { int xtemp, ytemp; struct robot *r, *end; end = &robot_list[max_robots]; for(r = robot_list; r < end; r++) { if(r->alive) { xtemp = ( r->x + sign(my_x-r->x) ) - my_x; ytemp = ( r->y + sign(my_y-r->y) ) - my_y; xtemp = ( xtemp < 0 ) ? -xtemp : xtemp; ytemp = ( ytemp < 0 ) ? -ytemp : ytemp; if( ( xtemp <= 0 ) && ( ytemp <= 0 ) ) { r->alive = FALSE; if ( free_per_level > 1 ) free_per_level--; robots_alive--; move(r->y,r->x); winch(stdscr); addch(SCRAP); } } } } #endif SCREWDRIVERS #ifdef DIK equal_coord() { register struct robot *r, *r2, *end = &robot_list[max_robots]; for(r = robot_list; r < end ; r++) for(r2 = r+1; r2 < end; r2++) if(r->x == r2->x || r->y == r2->y) return(1); return(0); } #endif DIK char * good_moves() { register int x, y; register int test_x, test_y; register char *m, *a; static char moves[] = "hjklyubn."; static char ans[2 + sizeof moves]; a = ans; #ifdef DIK if(aflag) { struct robot *r, *end = &robot_list[max_robots]; for(r = robot_list; r < end; r++) if(r->alive) { test_x = r->x; test_y = r->y; while(test_x != my_x || test_y != my_y) { test_x += sign(my_x - test_x); test_y += sign(my_y - test_y); move(test_y, test_x); switch(winch(stdscr)) { case ME: goto unsafe; case SCRAP: goto nxtr; } } nxtr: ; } *a++ = 's'; unsafe: ; } #endif DIK for(m = moves; *m; m++) { test_x = my_x+xinc(*m); test_y = my_y+yinc(*m); move(test_y,test_x); switch(winch(stdscr)) { case ME: #ifdef DIK if(aflag && free_teleports && free_per_level == MAX_FREE) { register int rct = 0; for(x = test_x-1; x <= test_x+1; x++) { for(y = test_y-1; y <= test_y+1; y++) { move(y,x); if(winch(stdscr) == ROBOT && rct++) goto bad; } } *a++ = (rct ? 'z' : '.'); continue; } #endif DIK /* fall into next case */ case ' ': for(x = test_x-1; x <= test_x+1; x++) { for(y = test_y-1; y <= test_y+1; y++) { move(y,x); if(winch(stdscr) == ROBOT) goto bad; } } *a++ = *m; } bad:; } *a = 0; if(ans[0]) { a = ans; } else { a = "Forget it!"; } mvprintw(LINES-1,MSGPOS,"%*.*-s",RVPOS-MSGPOS,RVPOS-MSGPOS,a); return(ans); } xinc(dir) char dir; { switch(dir) { case 'h': case 'y': case 'b': return(-1); case 'l': case 'u': case 'n': return(1); case 'j': case 'k': default: return(0); } } yinc(dir) char dir; { switch(dir) { case 'k': case 'y': case 'u': return(-1); case 'j': case 'b': case 'n': return(1); case 'h': case 'l': default: return(0); } } robots() { register struct robot *r, *end, *find; end = &robot_list[max_robots]; for(r = robot_list; r < end; r++) { if(r->alive) { mvaddch(r->y,r->x,' '); } } for(r = robot_list; r < end; r++) { if(r->alive) { r->x += sign(my_x-r->x); r->y += sign(my_y-r->y); move(r->y,r->x); switch(winch(stdscr)) { case ME: addch(MUNCH); dead = TRUE; break; case SCRAP: r->alive = FALSE; score += robot_value; robots_alive--; break; case ROBOT: for(find = robot_list; find < r; find++) { if(find->alive) { if(r->x == find->x && r->y == find->y) { find->alive = FALSE; break; } } } r->alive = FALSE; addch(SCRAP); score += robot_value*2; robots_alive -= 2; break; case MUNCH: break; default: addch(ROBOT); } } } } munch() { scorer(); msg("MUNCH! You're robot food"); leaveok(stdscr,FALSE); mvaddch(my_y,my_x,MUNCH); move(my_y,my_x); refresh(); readchar(); quit(TRUE); } quit(eaten) bool eaten; { move(LINES-1,0); refresh(); endwin(); putchar('\n'); ltc.t_dsuspc = dsusp; ioctl(1,TIOCSLTC,<c); scoring(eaten); exit(0); } scoring(eaten) bool eaten; { static char buf[MAXSTR]; sprintf(buf,"for this %s",TEMP_NAME); record_score(eaten,TMP_FILE,TEMP_DAYS,buf); printf("[Press return to continue]"); fflush(stdout); gets(buf); record_score(eaten,HOF_FILE,0,"of All Time"); } record_score(eaten,fname,max_days,type_str) bool eaten; char *fname; int max_days; char *type_str; { int fd; int (*action)(); action = signal(SIGINT,SIG_IGN); if((fd = open(fname,2)) < 0) { perror(fname); } else { if(flock(fd,LOCK_EX) < 0) { perror(fname); } else { do_score(eaten,fd,max_days,type_str); flock(fd,LOCK_UN); } close(fd); } signal(SIGINT,action); } do_score(eaten,fd,max_days,type_str) bool eaten; int fd, max_days; char *type_str; { register struct scorefile *position; register int x; register struct scorefile *remove, *sfile, *eof; struct scorefile *oldest, *this; char *so, *ts; int uid, this_day, limit; static char buf[20]; ts = buf; this_day = max_days ? time(0)/SECSPERDAY : 0; limit = this_day-max_days; sfile = (struct scorefile *)(malloc(FILE_SIZE)); eof = &sfile[NUMSCORES]; this = 0; for(position = sfile; position < eof; position++) { position->s_score = 0; position->s_days = 0; } read(fd,sfile,FILE_SIZE); remove = 0; #ifdef DIK if(score == 0 && aflag) return; #endif DIK if(score > 0) { uid = pass->pw_uid; oldest = 0; x = limit; for(position = eof-1; position >= sfile; position--) { if(position->s_days < x) { x = position->s_days; oldest = position; } } position = 0; for(remove = sfile; remove < eof; remove++) { if(position == 0 && score > remove->s_score) position = remove; # ifndef ALLSCORES if (remove->s_uid == uid) { if (remove->s_days < limit) oldest = remove; else break; } # endif ALLSCORES } if(remove < eof) { if(position == 0 && remove->s_days < limit) position = remove; } else if(oldest) { remove = oldest; if(position == 0) { position = eof-1; } else if(remove < position) { position--; } } else if(position) { remove = eof-1; } if(position) { if(remove < position) { while(remove < position) { *remove = *(remove+1); remove++; } } else { while(remove > position) { *remove = *(remove-1); remove--; } } position->s_score = score; strncpy(position->s_name,whoami,MAXSTR); position->s_eaten = eaten; position->s_level = LEVEL; position->s_uid = uid; position->s_days = this_day; this = position; lseek(fd,0,0); write(fd,sfile,FILE_SIZE); close(fd); } } printf( # ifdef ALLSCORES "\nTop %s Scores %s:\n", # else ALLSCORES "\nTop %s Robotists %s:\n", # endif ALLSCORES NUMNAME, type_str ); printf("Rank Score Name\n"); count = 0; for(position = sfile; position < eof; position++) { if(position->s_score == 0) break; if(position == this && SO && SE) { tputs(SO,0,_putchar); } if (position->s_days >= limit) { printf ("%-6d %-8d %s: %s on level %d.", ++count, position->s_score, position->s_name, position->s_eaten ? "eaten" : "chickened out", position->s_level ); # ifdef OLDSCORES } else { printf ("**OLD** %-8d %s: %s on level %d.", position->s_score, position->s_name, position->s_eaten ? "eaten" : "chickened out", position->s_level ); # endif OLDSCORES } if(position == this && SO && SE) { tputs(SE,0,_putchar); } # ifndef OLDSCORES if (position->s_days >= limit) # endif OLDSCORES putchar ('\n'); } } scorer() { static char infobuf [6]; register int x, y; if ((y = free_teleports-free_per_level) < 0) y = 0; x = free_teleports-y; sprintf(infobuf,"%d+%d",x,y); if (y == 0) infobuf[1] = '\0'; move(LINES-1,0); clrtoeol(); printw("<%s> level: %d score: %d",infobuf,LEVEL,score); mvprintw(LINES-1,RVPOS,"robots: %d value: %d",robots_alive,robot_value); } rndx() { return(rnd(COLS-2)+1); } rndy() { return(rnd(LINES-3)+1); } rnd(mod) int mod; { if(mod <= 0) return(0); return((((seed = seed*11109+13849) >> 16) & 0xffff) % mod); } sign(x) register int x; { return((x < 0) ? -1 : (x == 0) ? 0 : 1); } msg(message,args) char *message; int args; { register int x; static FILE msgpr; static char msgbuf[1000]; msgpr._flag = _IOSTRG | _IOWRT; msgpr._ptr = msgbuf; msgpr._cnt = 1000; _doprnt(message,&args,&msgpr); putc(0,&msgpr); mvaddstr(LINES-1,MSGPOS,msgbuf); clrtoeol(); refresh(); } interrupt() { quit(FALSE); }