/* Header: /usr/src/games/warp/RCS/score.c,v 1.1 87/07/03 02:13:26 games Exp */ /* Log: score.c,v * Revision 7.0.1.2a 87/07/03 02:13:26 games * Fixed numerous long vs. int bugs in printfs, etc. * * Revision 7.0.1.2 86/10/20 12:06:56 lwall * Made all exits reset tty. * * Revision 7.0.1.1 86/10/16 10:52:47 lwall * Added Damage. Fixed random bugs. * * Revision 7.0 86/10/08 15:13:14 lwall * Split into separate files. Added amoebas and pirates. * */ #include "EXTERN.h" #include "warp.h" #include "intrp.h" #include "object.h" #include "play.h" #include "sig.h" #include "term.h" #include "us.h" #include "util.h" #include "weapon.h" #include "INTERN.h" #include "score.h" void score_init(void) { char *s; int i; FILE *savfil; if (stat(SAVEDIR,&filestat)) { printf("Cannot access %s\r\n",SAVEDIR); finalize(1); } if (filestat.st_gid != getegid() && geteuid() != 0) { printf("Warp will not run right without being setgid.\r\n"); finalize(1); } if ((filestat.st_mode & 0605) != 0605) { printf("%s is not protected correctly (must be u+rw o+rx).\r\n",SAVEDIR); finalize(1); } #ifdef SCOREFULL interp(longlognam, sizeof longlognam, "%N"); for (i=strlen(longlognam); i<24; i++) longlognam[i] = ' '; /* make sure it is 24 long for strncmp */ longlognam[24] = '\0'; #else interp(longlognam, sizeof longlognam, "%L"); for (i=strlen(longlognam); i<8; i++) longlognam[i] = ' '; /* make sure it is 8 long for strncmp */ longlognam[8] = '\0'; #endif if (scorespec) wscore(); snprintf(savefilename, sizeof(savefilename), "%s/save.%s", SAVEDIR, logname); savfil = experimenting ? NULL : fopen(savefilename,"r"); if (savfil != NULL && fgets(spbuf,100,savfil) != NULL) { char tmpbuf[80]; spbuf[strlen(spbuf)-1] = '\0'; if (fgets(tmpbuf,80,savfil) != NULL) { int processnum; tmpbuf[strlen(tmpbuf)-1] = '\0'; printf("You seem to have left a game %s.\r\n",tmpbuf+9); s = strchr(tmpbuf+9, ','); *s = '\0'; processnum = atoi(s+11); if (kill(processnum, SIGINT)) { /* does process not exist? */ /* (warp ignores SIGINT) */ printf("\r\n\ That process does not seem to exist anymore, so you'll have to start the\r\n"); printf( "last wave over.\r\n\n"); printf( " [type anything to continue]"); fflush(stdout); eat_typeahead(); getcmd(tmpbuf); if (*tmpbuf == INTRCH) finalize(0); printf("\r\n"); } else { if (strcmp(term+8,tmpbuf+23)) { printf( "That is not your current terminal--you are on %s.\r\n", term+5); printf("\r\nYour options:\r\n"); printf(" 1) Exit and find the terminal it's running on\r\n"); } else { printf("\r\nYour options:\r\n"); printf(" 1) Exit and try to foreground it\r\n"); } printf(" 2) Let me terminate the other game\r\n\n"); printf("What do you want to do? "); fflush(stdout); eat_typeahead(); getcmd(tmpbuf); printf("\r\n"); if (*tmpbuf == INTRCH) finalize(0); if (*tmpbuf == '1') { printf( "If you don't succeed, come back and do option 2 instead. Good luck.\r\n"); finalize(0); } printf( "Ok, hang on a few moments \r\n"); fclose(savfil); if (kill(processnum, SIGQUIT)) { printf("Unable to kill process #%d!\r\n",processnum); roundsleep(2); } else { #ifdef SIGCONT kill(processnum, SIGCONT); #endif for (i=15; i; --i) { sleep(1); if (kill(processnum,SIGINT)) /* does process not exist? */ /* (warp ignores SIGINT) */ break; } didkill = true; } savfil = fopen(savefilename,"r"); if (savfil != NULL) { fgets(spbuf,100,savfil); } } } } else savfil = NULL; if (savfil == NULL) { totalscore = smarts = cumsmarts = wave = 0; numents = 5; numbases = 3; } else { totalscore = atol(spbuf+9); smarts = atoi(spbuf+20); cumsmarts = atoi(spbuf+24); numents = atoi(spbuf+30); numbases = atoi(spbuf+33); wave = atoi(spbuf+36); apolspec = (spbuf[40] == 'a'); beginner = (spbuf[41] == 'b'); crushspec = (spbuf[42] == 'c'); gornspec = (spbuf[43] == 'g'); massacre = (spbuf[44] == 'm'); romspec = (spbuf[45] == 'r'); tholspec = (spbuf[46] == 't'); lowspeed = (spbuf[47] == 'l') || lowspeed; amoebaspec = (spbuf[48] == '&'); fclose(savfil); } if (!ismarts) { ismarts = 1; clear(); page(NEWSFILE,false); if (smarts) { printf("\r\nSaved game: SCORE DIFF CUMDIFF ENTERPRISES BASES WAVE"); printf("\r\n %7ld %2d %4d %1d %1d %3d", totalscore,smarts,cumsmarts,numents,numbases,wave); } printf("\r\nWould you like instructions? "); fflush(stdout); eat_typeahead(); getcmd(buf); printf("\r\n"); if (*buf == INTRCH) finalize(0); if (*buf == 'Y' || *buf == 'y') { page(HELPFILE,false); printf("\r\nWould you like to play easy games for a while? "); fflush(stdout); eat_typeahead(); getcmd(buf); printf("\r\n"); if (*buf == 'Y' || *buf == 'y') { beginner = true; lowspeed = true; } } } if (!smarts) smarts = ismarts; } void wscore(void) { clear(); printf(" TOP WARPISTS\r\n\n"); printf("RANK WHO AKA SCORE DIFF CUMDIFF WHEN\r\n"); page(SCOREBOARD,true); printf(" [Type anything to continue]"); fflush(stdout); getcmd(spbuf); if (*spbuf == INTRCH) finalize(0); clear(); printf(" TOP LOW-SPEED WARPISTS\r\n\n"); printf("RANK WHO AKA SCORE DIFF CUMDIFF WHEN\r\n"); page(LSCOREBOARD,true); printf(" [Type anything to continue]"); fflush(stdout); getcmd(spbuf); if (*spbuf == INTRCH) finalize(0); clear(); printf(" TOP FUNNY WARPISTS\r\n\n"); printf("RANK WHO AKA SCORE DIFF CUMDIFF WHEN\r\n"); page(FSCOREBOARD,true); printf(" [Type anything to continue]"); fflush(stdout); getcmd(spbuf); if (*spbuf == INTRCH) finalize(0); clear(); printf(" GAMES SAVED OR IN PROGRESS\r\n\n"); printf("WHO SCORE DF CDF E B WV FLAGS\r\n"); resetty(); snprintf(spbuf, sizeof(spbuf), "/bin/cat %ssave.*",SAVEDIR); execl("/bin/sh", "sh", "-c", spbuf, NULL); finalize(1); } void display_status(void) { int tmp; static const char *status_names[] = {"Impl", "Warp", "Base", "****" }; if (oldstatus != status) { snprintf(spbuf, sizeof(spbuf), "%-4s",status_names[status]); mvaddstr(0,0, spbuf); oldstatus = status; } if (ent) { if (ent->energy != oldeenergy) { oldeenergy = ent->energy; snprintf(spbuf, sizeof(spbuf), "%4ld",oldeenergy); mvaddstr(0,8, spbuf); } if (etorp != oldetorp) { snprintf(spbuf, sizeof(spbuf), "%2d",etorp); mvaddstr(0,13, spbuf); oldetorp = etorp; } } else { if (etorp >= 0) { etorp = -1; mvaddstr(0,8,"*******"); damage = 0; } } if (base) { if (base->energy != oldbenergy) { oldbenergy = base->energy; snprintf(spbuf, sizeof(spbuf), "%5ld",oldbenergy); mvaddstr(0,19, spbuf); } if (btorp != oldbtorp) { snprintf(spbuf, sizeof(spbuf), "%3d",btorp); mvaddstr(0,25, spbuf); oldbtorp = btorp; } } else { if (btorp >= 0) { btorp = -1; mvaddstr(0,19,"*********"); } } if (damage) { if (!olddamage) mvaddstr(0,42,"*** "); if (damage > 1 || !damflag[dam]) { do { if (++dam == MAXDAMAGE) dam = 0; } while (!damflag[dam]); } if (!--damflag[dam]) { olddamage = damage; damage--; snprintf(spbuf, sizeof(spbuf), "%s OK *** ",dammess[dam]); spbuf[15] = '\0'; mvaddstr(0,46,spbuf); } else if (dam == NOSHIELDS) { olddamage = damage; tmp = (34 - damflag[dam]) * 3 - rand_mod(3); if (tmp < 0) tmp = 0; snprintf(spbuf, sizeof(spbuf), "%d%% %s *** ",tmp,dammess[dam]); spbuf[15] = '\0'; mvaddstr(0,46,spbuf); } else if (dam != lastdam || !olddamage) { olddamage = damage; snprintf(spbuf, sizeof(spbuf), "NO %s *** ",dammess[dam]); spbuf[15] = '\0'; mvaddstr(0,46,spbuf); } if (status < 2) { if (dam == NOIMPULSE && !entmode) status = entmode = 1; if (dam == NOWARP && entmode) status = entmode = 0; } tmp = damflag[dam] * damage; snprintf(spbuf, sizeof(spbuf), "%3d.%1d ETR",tmp/10,tmp%10); mvaddstr(0,69,spbuf); lastdam = dam; } else { if (olddamage) { snprintf(spbuf, sizeof(spbuf), "Stars: %-3d Stardate",numstars); mvaddstr(0,42,spbuf); lastdam = -1; olddamage = 0; oldcurscore = -1; } else if (numstars != oldstrs) { snprintf(spbuf, sizeof(spbuf), "%-3d",numstars); mvaddstr(0,49, spbuf); } oldstrs = numstars; } if (numenemies != oldenemies) { snprintf(spbuf, sizeof(spbuf), "%-3d",numenemies); mvaddstr(0,38, spbuf); oldenemies = numenemies; } if ((tmp = timer%10) != 0) { snprintf(spbuf, sizeof(spbuf), "%1d",tmp); mvaddstr(0,67, spbuf); } else { snprintf(spbuf, sizeof(spbuf), "%5d.%1d",timer/10+smarts*100,tmp); mvaddstr(0,61, spbuf); } if ((!damage || !damflag[dam]) && curscore != oldcurscore) { snprintf(spbuf, sizeof(spbuf), "%9ld",curscore); mvaddstr(0,69, spbuf); oldcurscore = curscore; } } void wavescore(void) { double power, effectscore, starscore, pi_over_2; long bonuses; long tmp; FILE *mapfp; int row; clear(); if (curscore > possiblescore) curscore = possiblescore; pi_over_2 = 3.14159265 / 2.0; power = pow((double)inumenemies+ /* total number of enemies */ inumroms*2+ /* count roms 3 times */ inumgorns+ /* count gorns 2 times */ inumthols+ /* count thols 2 times */ inumapollos*4+ /* count apollo 5 times */ inumcrushes*3+ /* count crushers 4 times */ inumamoebas*5 /* count amoebas 6 times */ , 0.50) * /* skew it a little */ (double)smarts; /* average energy and intelligence */ if (inumstars < 350 && inumenemies > 5) power += (350.0 - (double)inumstars) * ((double)inumenemies - 5.0); if (inumstars > 850 && inumenemies > 2) power += ((double)inumstars - 850.0) * ((double)inumenemies - 2.0); effectscore = ((double)curscore / possiblescore) * atan2(power, (double) timer + 1.0) / pi_over_2; if (inumstars) starscore = (double) numstars / (double) inumstars; else starscore = 1.0; wave++; snprintf(spbuf, sizeof(spbuf), "Wave = %d, Difficulty = %d, cumulative difficulty = %d", wave, smarts, cumsmarts); mvaddstr(1, 13+(smarts<10), spbuf); mvaddstr( 4, 68, " BONUS"); snprintf(spbuf, sizeof(spbuf), "Efficiency rating: %1.8f (diff=%0.2f,time=%d)", effectscore, power, timer + 1); mvaddstr( 5,5, spbuf); if (effectscore < 0.8) bonuses = tmp = 0; else bonuses = tmp = (long) ((effectscore-0.8) * smarts * 1000); snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr( 5, 68, spbuf); snprintf(spbuf, sizeof(spbuf), "Star save ratio: %1.8f (%d/%d)", starscore, numstars, inumstars); mvaddstr( 6,5, spbuf); bonuses += tmp = (long) (((double)curscore / possiblescore) * (starscore*starscore) * smarts * 20); snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr( 6, 68, spbuf); row = 7; if (inuminhab != numinhab) { snprintf(spbuf, sizeof(spbuf), "Inhabited stars depopulated: %5d", inuminhab-numinhab); mvaddstr(row,5, spbuf); bonuses += tmp = (long) (inuminhab-numinhab) * -500; snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr(row, 68, spbuf); row++; } if (inumfriends != numfriends) { snprintf(spbuf, sizeof(spbuf), "Friendly craft destroyed: %5d", inumfriends-numfriends); mvaddstr(row,5, spbuf); bonuses += tmp = (long) (inumfriends-numfriends) * -250; snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr(row, 68, spbuf); row++; } if (deadmudds) { mvaddstr(row,5,"For destroying Harry Mudd:"); bonuses += tmp = (long) rand_mod(deadmudds * 20 + 1) - deadmudds*10; snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr(row, 68, spbuf); row++; } if (bombed_out) { mvaddstr(row,5, "For running away from reality:"); bonuses += tmp = (long) -possiblescore/2; snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr(row, 68, spbuf); row++; } if (row < 9) row++; snprintf(spbuf, sizeof(spbuf), "Enterprise: %-9s%5d remaining", !ient?"":ent?"saved":"destroyed", numents); mvaddstr(row,5, spbuf); bonuses += tmp = ent && !bombed_out ? (smarts+1)*15 : 0; snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr(row, 68, spbuf); row++; snprintf(spbuf, sizeof(spbuf), "Base: %-9s %5d remaining", !ibase?"":base?"saved":"destroyed", numbases); mvaddstr(row,5, spbuf); bonuses += tmp = base && !bombed_out ? (smarts+1)*10 : 0; snprintf(spbuf, sizeof(spbuf), "%6ld", tmp); mvaddstr(row, 68, spbuf); if (beginner) { mvaddstr(13+(row>11),19, "(Special games count only a tenth as much)"); curscore /= 10; bonuses /= 10; } snprintf(spbuf, sizeof(spbuf), "Previous point total:%10ld",lastscore); mvaddstr(15,24, spbuf); snprintf(spbuf, sizeof(spbuf), "Points this round: %10ld",curscore); mvaddstr(16,24, spbuf); snprintf(spbuf, sizeof(spbuf), "Bonuses: %10ld",bonuses); mvaddstr(17,24, spbuf); totalscore = lastscore + curscore + bonuses; snprintf(spbuf, sizeof(spbuf), "New point total: %10ld",totalscore); mvaddstr(18,24, spbuf); if (lastscore / ENTBOUNDARY < totalscore / ENTBOUNDARY) { mvaddstr(row-1,42,"+ 1 new"); numents++; } else if (numents>0 && lastscore / ENTBOUNDARY > totalscore / ENTBOUNDARY) { mvaddstr(row-1,42,"- 1 obsolete"); numents--; } if (lastscore / BASEBOUNDARY < totalscore / BASEBOUNDARY) { mvaddstr(row,42,"+ 1 new"); numbases++; } else if (numbases>0 && lastscore / BASEBOUNDARY > totalscore / BASEBOUNDARY) { mvaddstr(row,42,"- 1 obsolete"); numbases--; } if (starscore < 0.8 && inumstars > 200 && numstars > 50) { snprintf(spbuf, sizeof(spbuf), "smap.%d",rand_mod(MAPS-PERMMAPS)+PERMMAPS); if ((mapfp = fopen(spbuf, "w")) != NULL) { OBJECT *obj; fprintf(mapfp,"%d\n",numstars); for (obj = root.next; obj != &root; obj = obj->next) { if (obj->type == Star) { fprintf(mapfp,"%d %d\n",obj->posy,obj->posx); } } fclose(mapfp); } } } void score(void) { char tmp, *retval, cdate[30]; FILE *logfd; FILE *outfd; int i; time_t nowtime; const char *scoreboard; for (i=0; link(LOGFILE, LOCKFILE) == -1 && i<10; i++) sleep(1); nowtime = time(NULL); strcpy(cdate,ctime(&nowtime)); if ((logfd = fopen(LOGFILE,"a")) != NULL) { fprintf(logfd, "%-24s%-9s%7ld%c%2d %4d %s", realname, logname, totalscore, c,smarts, cumsmarts, cdate); fclose(logfd); } strcpy(cdate+11,cdate+20); if (beginner) scoreboard = FSCOREBOARD; else if (lowspeed) scoreboard = LSCOREBOARD; else scoreboard = SCOREBOARD; if (eaccess(scoreboard,0)) { if ((logfd = fopen(scoreboard,"w")) != NULL) fclose(logfd); } if ((logfd = fopen(scoreboard,"r")) != NULL && (outfd = fopen(TMPSCOREBOARD,"w")) != NULL) { for (i=0; i<20; i++) { if ((retval = fgets(buf, 100, logfd)) == NULL) break; if (atol(buf+32) < totalscore) break; if (strnEQ(buf+COMPOFF,COMPNAME,COMPLEN)) { i = 100; break; } fprintf(outfd, "%s", buf); } if (i == 100) { mvaddstr(20,21, "You did not better your previous score"); fclose(outfd); unlink(TMPSCOREBOARD); } else if (i < 20) { fprintf(outfd, "%-24s%-8s%8ld%c %2d %4d %s", realname, logname, totalscore, c,smarts, cumsmarts, cdate); i++; snprintf(spbuf, sizeof(spbuf), " Congratulations--you've placed %d%s", i, i==1?"st":(i==2?"nd":(i==3?"rd":"th"))); if (retval != NULL) { if (strnNE(buf+COMPOFF,COMPNAME,COMPLEN)) { fprintf(outfd, "%s", buf); i++; } else strcpy(spbuf, "Congratulations--you've bettered your score"); while (i<20) { if (fgets(buf, 100, logfd) == NULL) break; if (strnNE(buf+COMPOFF,COMPNAME,COMPLEN)) { fprintf(outfd, "%s", buf); i++; } } } mvaddstr(20,19, spbuf); fclose(logfd); fclose(outfd); while (unlink(scoreboard) == 0) ; link(TMPSCOREBOARD,scoreboard); unlink(TMPSCOREBOARD); logfd = fopen(scoreboard,"r"); } else { mvaddstr(20,22,"You did not place within the top 20"); fclose(outfd); } } else { snprintf(spbuf, sizeof(spbuf), "(Cannot access %s file, error %d)", (logfd==NULL?"log":"tmp"),errno); mvaddstr(20,22,spbuf); } move(23,0,0); erase_eol(); mvaddstr(23,11, "[Hit space for scoreboard, 'r' for new game, 'q' to quit]"); unlink(LOCKFILE); fflush(stdout); eat_typeahead(); do { getcmd(&tmp); } while (tmp != INTRCH && tmp != BREAKCH && !strchr(" rqQ",tmp)); if (strchr("qQr",tmp)) { justonemoretime = (tmp == 'r'); if (logfd != NULL) fclose(logfd); } else { clear(); if (logfd != NULL) { fseek(logfd, 0L, 0); if (beginner) mvaddstr(0,31,"TOP FUNNY WARPISTS"); else if (lowspeed) mvaddstr(0,29,"TOP LOW-SPEED WARPISTS"); else mvaddstr(0,33,"TOP WARPISTS"); mvaddstr(2,0,"RANK WHO AKA SCORE DIFF CUMDIFF WHEN"); for (i=1; i<=20; i++) { if (fgets(buf, 100, logfd) == NULL) break; buf[strlen(buf)-1] = '\0'; snprintf(spbuf, sizeof(spbuf), " %2d %s", i, buf); mvaddstr(i+2,0, spbuf); } fclose(logfd); } roundsleep(1); mvaddstr(23,25,"Would you like to play again?"); eat_typeahead(); do { getcmd(&tmp); } while (tmp != INTRCH && tmp != BREAKCH && !strchr("nNyY \n\r",tmp)); if (tmp == 'n' || tmp == 'N' || tmp == INTRCH || tmp == BREAKCH) justonemoretime = false; } smarts = ismarts; totalscore = cumsmarts = wave = 0; numents = 5; numbases = 3; apolspec = false; beginner = false; crushspec = false; gornspec = false; massacre = (ismarts >= 40); romspec = false; tholspec = false; } void save_game(void) { FILE *savfil; if (experimenting) return; if ((savfil = fopen(savefilename,"w")) == NULL) { int e = errno; resetty(); printf("Cannot save game in %s (%s)\r\n", savefilename, strerror(e)); finalize(1); } fprintf(savfil, "%-8s %10ld, %2d,%5d,%2d,%2d,%3d %c%c%c%c%c%c%c%c%c\n", logname, totalscore, smarts, cumsmarts, numents, numbases, wave, apolspec ? 'a' : ' ', beginner ? 'b' : ' ', crushspec ? 'c' : ' ', gornspec ? 'g' : ' ', massacre ? 'm' : ' ', romspec ? 'r' : ' ', tholspec ? 't' : ' ', lowspeed ? 'l' : ' ', amoebaspec ? '&' : ' ' ); fclose(savfil); resetty(); if (panic) finalize(0); clear(); finalize(0); }