|
|
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);
}