void spacewarp(int w) { struct point p; int j; const char *str; snrand(&you); p.col = COLS / 2 - 8; p.line = LINES / 2 - 1; if (p.col < 0) p.col = 0; if (p.line < 0) p.line = 0; if (w) { str = "BONUS!!!"; loot = loot - penalty; penalty = 0; } else { str = "SPACE WARP!!!"; penalty += loot / PENALTY; } for (j = 0; j < 3; j++) { erase(); refresh(); delay(5); mvaddstr(p.line + 1, p.col + 1, str); refresh(); delay(10); } setup(); winnings(cashvalue); }
double testdeviation(int seed, double sd) { int i; double A, Q, rn; double calcsd, deviation; A = 0; Q = 0; snrand(seed); for (i = 0; i < N; ++i) { rn = nrandsd(sd); if (i) { Q = Q + (i * sqr(rn - A)) / (i+1); A = A + (rn - A)/(i+1); } else { A = rn; Q = 0; } } calcsd = sqrt(Q / N); deviation = fabs(1 - (calcsd / sd)); printf("[%s] - Calculated deviation %f is %2.2f%% from given deviation %f.\n", (deviation < MAXDEV)?" OK ":"FAIL", calcsd, deviation*100, sd); return rn; }
/* Main command loop */ void mainloop(void) { int k; int c, lastc = 0; int repeat = 1; for (;;) { if (wantstop) { endwin(); length(moves); exit(0); } /* Highlight you, not left & above */ move(you.line + 1, you.col + 1); refresh(); if (((c = getch()) <= '9') && (c >= '0')) { repeat = c - '0'; while (((c = getch()) <= '9') && (c >= '0')) repeat = 10 * repeat + (c - '0'); } else { if (c != '.') repeat = 1; } if (c == '.') c = lastc; if (!fast) flushinp(); lastc = c; switch (c) { case CTRL('z'): suspend(); continue; case '\044': case 'x': case 0177: /* del or end of file */ case ERR: endwin(); length(moves); #ifdef LOGGING logit("quit"); #endif exit(0); case CTRL('l'): setup(); winnings(cashvalue); continue; case 'p': case 'd': snap(); continue; case 'w': spacewarp(0); continue; case 'A': repeat = you.col; c = 'h'; break; case 'H': case 'S': repeat = you.col - money.col; c = 'h'; break; case 'T': repeat = you.line; c = 'k'; break; case 'K': case 'E': repeat = you.line - money.line; c = 'k'; break; case 'P': repeat = ccnt - 1 - you.col; c = 'l'; break; case 'L': case 'F': repeat = money.col - you.col; c = 'l'; break; case 'B': repeat = lcnt - 1 - you.line; c = 'j'; break; case 'J': case 'C': repeat = money.line - you.line; c = 'j'; break; } for (k = 1; k <= repeat; k++) { moves++; switch (c) { case 's': case 'h': #ifdef KEY_LEFT case KEY_LEFT: #endif case '\b': if (you.col > 0) { if ((fast) || (k == 1)) pchar(&you, ' '); you.col--; if ((fast) || (k == repeat) || (you.col == 0)) pchar(&you, ME); } break; case 'f': case 'l': #ifdef KEY_RIGHT case KEY_RIGHT: #endif case ' ': if (you.col < ccnt - 1) { if ((fast) || (k == 1)) pchar(&you, ' '); you.col++; if ((fast) || (k == repeat) || (you.col == ccnt - 1)) pchar(&you, ME); } break; case CTRL('p'): case 'e': case 'k': #ifdef KEY_UP case KEY_UP: #endif case 'i': if (you.line > 0) { if ((fast) || (k == 1)) pchar(&you, ' '); you.line--; if ((fast) || (k == repeat) || (you.line == 0)) pchar(&you, ME); } break; case CTRL('n'): case 'c': case 'j': #ifdef KEY_DOWN case KEY_DOWN: #endif case '\n': case '\r': case 'm': if (you.line + 1 < lcnt) { if ((fast) || (k == 1)) pchar(&you, ' '); you.line++; if ((fast) || (k == repeat) || (you.line == lcnt - 1)) pchar(&you, ME); } break; } if (same(&you, &money)) { loot += 25; if (k < repeat) pchar(&you, ' '); do { snrand(&money); } while ((money.col == finish.col && money.line == finish.line) || (money.col < 5 && money.line == 0) || (money.col == you.col && money.line == you.line)); pchar(&money, TREASURE); winnings(cashvalue); /* continue; Previously, snake missed a turn! */ } if (same(&you, &finish)) { win(&finish); flushinp(); endwin(); printf("You have won with $%d.\n", cashvalue); fflush(stdout); #ifdef LOGGING logit("won"); #endif length(moves); post(cashvalue, 1); close(rawscores); exit(0); } if (pushsnake()) break; } } }
int main(int argc, char *argv[]) { struct sigaction sa; int ch, i; if (pledge("stdio rpath wpath cpath tty", NULL) == -1) err(1, "pledge"); #ifdef LOGGING const char *home; home = getenv("HOME"); if (home == NULL || *home == '\0') err(1, "getenv"); snprintf(logpath, sizeof(logpath), "%s/%s", home, ".snake.log"); logfile = fopen(logpath, "a"); #endif while ((ch = getopt(argc, argv, "hl:stw:")) != -1) switch ((char)ch) { case 'w': /* width */ ccnt = strtonum(optarg, 1, INT_MAX, NULL); break; case 'l': /* length */ lcnt = strtonum(optarg, 1, INT_MAX, NULL); break; case 's': /* score */ if (readscores(0)) snscore(0); else printf("no scores so far\n"); return 0; break; case 't': /* slow terminal */ fast = 0; break; case 'h': default: fprintf(stderr, "usage: %s [-st] [-l length] " "[-w width]\n", getprogname()); return 1; } readscores(1); penalty = loot = 0; initscr(); #ifdef KEY_LEFT keypad(stdscr, TRUE); #endif nonl(); cbreak(); noecho(); if (!lcnt || lcnt > LINES - 2) lcnt = LINES - 2; if (!ccnt || ccnt > COLS - 3) ccnt = COLS - 3; i = lcnt < ccnt ? lcnt : ccnt; if (i < 4) { endwin(); errx(1, "screen too small for a fair game."); } /* * chunk is the amount of money the user gets for each $. * The formula below tries to be fair for various screen sizes. * We only pay attention to the smaller of the 2 edges, since * that seems to be the bottleneck. * This formula is a hyperbola which includes the following points: * (24, $25) (original scoring algorithm) * (12, $40) (experimentally derived by the "feel") * (48, $15) (a guess) * This will give a 4x4 screen $99/shot. We don't allow anything * smaller than 4x4 because there is a 3x3 game where you can win * an infinite amount of money. */ if (i < 12) i = 12; /* otherwise it isn't fair */ /* * Compensate for border. This really changes the game since * the screen is two squares smaller but we want the default * to be $25, and the high scores on small screens were a bit * much anyway. */ i += 2; chunk = (675.0 / (i + 6)) + 2.5; /* min screen edge */ memset(&sa, 0, sizeof sa); sigemptyset(&sa.sa_mask); sa.sa_handler = stop; sigaction(SIGINT, &sa, NULL); snrand(&finish); snrand(&you); snrand(&money); snrand(&snake[0]); for (i = 1; i < 6; i++) chase(&snake[i], &snake[i - 1]); setup(); mainloop(); return 0; }