From beb8fa55735e290cbd54747dc3f5158016098a6f Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Mon, 8 Nov 1993 15:12:51 +0000 Subject: [PATCH] Initial revision --- do_level.c | 499 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 do_level.c diff --git a/do_level.c b/do_level.c new file mode 100644 index 0000000..f313124 --- /dev/null +++ b/do_level.c @@ -0,0 +1,499 @@ +/* S K I ! +** +** Version 6.0 of October 14, 1990 +** +** Copyright 1983-1990 by Mark Stevans for Roy's Games, Inc. +*/ + +#include +#include +#ifdef CURSES +#include +#endif /* CURSES */ +#include "ski.h" + +#ifdef A_COLOR +/* Beware of the color yellow. IBM boxes foo it up */ +#define SNOW_COLOR COLOR_WHITE +#define TREE_COLOR COLOR_GREEN +#define PLAYER_COLOR COLOR_MAGENTA +#define DIRT_COLOR COLOR_BLACK +#define ICE_COLOR COLOR_CYAN +#define YETI_COLOR COLOR_BLUE +#define ICBM_COLOR COLOR_MAGENTA +#define DEMON_COLOR COLOR_RED +#endif /* A_COLOR */ + +/* +** "injuries" contains the array of injury descriptions. +*/ + +PRIVATE char *injuries[] = { + "However, you escaped injury!", + "But you weren't hurt at all!", + "But you only got a few scratches.", + "You received some cuts and bruises.", + "You wind up with a concussion and some contusions.", + "You now have a broken rib.", + "Your left arm has been fractured.", + "You suffered a broken ankle.", + "You have a broken arm and a broken leg.", + "You have four broken limbs and a cut!", + "You broke every bone in your body!", + "I'm sorry to tell you that you have been killed....", + NIL(char *) +}; + +/* +** Color support code +** +** hacked in on a whim by Eric Raymond (eric@snark.thyrsus.com) +*/ +#ifdef A_COLOR +#define MAXCOLORS 8 +static char colorstrings[MAXCOLORS][20]; + +void init_colors() +{ + extern char *tparm(), *tgetstr(), *getenv(); + char *cp; + int i; + + tgetent(getenv("TERM"), (char *)NULL); + if ((cp = tgetstr("Sf")) != (char *)NULL) + { + /* wedge those color strings in there */ + for (i = 0; i < MAXCOLORS; i++) + (void) strcpy(colorstrings[i], tparm(cp, i)); + } +} + +#define to_color(n) (void) fputs(colorstrings[n], stdout); + +#endif /* A_COLOR */ + +/* +** "draw_picture" +*/ + +PUBLIC int draw_picture(current_level) +LEVEL *current_level; +{ + char level_picture[LINE_LEN + 1]; +#ifdef A_COLOR + int oldcolor, newcolor; + char *cp; +#endif /* A_COLOR */ + + /* + ** Create a picture of the current level. + */ + + strcpy(level_picture, current_level->slope); + + level_picture[current_level->player_pos] = REP_PLAYER; + + if (EXISTS(current_level->snoman_pos)) + level_picture[current_level->snoman_pos] = REP_SNOMAN; + if (EXISTS(current_level->icbm_pos)) + level_picture[current_level->icbm_pos] = REP_ICBM; + if (EXISTS(current_level->demon_pos)) + level_picture[current_level->demon_pos] = REP_DEMON; + + /* + ** Print the picture of the current level. + */ + +#ifdef A_COLOR + printf("%4d ", current_level->level_num); + oldcolor = COLOR_WHITE; + for (cp = level_picture; *cp; cp++) + { + switch(*cp) + { + case REP_SNOW: + newcolor = SNOW_COLOR; + break; + case REP_TREE: + newcolor = TREE_COLOR; + break; + case REP_PLAYER: + newcolor = PLAYER_COLOR; + break; + case REP_GROUND: + newcolor = DIRT_COLOR; + break; + case REP_ICE: + newcolor = ICE_COLOR; + break; + case REP_SNOMAN: + newcolor = YETI_COLOR; + break; + case REP_ICBM: + newcolor = ICBM_COLOR; + break; + case REP_DEMON: + newcolor = DEMON_COLOR; + break; + } + + if (oldcolor != newcolor) + to_color(newcolor); + oldcolor = newcolor; + putchar(*cp); + } + to_color(COLOR_WHITE); +#else + printf("%4d %s ", current_level->level_num, level_picture); +#endif /* A_COLOR */ + + /* + ** Return a code indicating successful completion. + */ + + return (SUCCESS); +} + +/* +** "do_user" +*/ + +PUBLIC int do_user(current_level) +LEVEL *current_level; +{ + /* + ** If we are jumping, just finish the line. Otherwise, check for + ** obstacles, and do a command. + */ + + if (current_level->jump_count >= 0) + putchar('\n'); + else { + check_obstacles(current_level); + do_command(current_level); + } +} + +/* +** "manipulate_objects" +*/ + +PUBLIC int manipulate_objects(current_level) +LEVEL *current_level; +{ + /* + ** If there is a Snoman, the player's jet-powered skis may melt him, + ** or he may spontaneously melt. + */ + + if (EXISTS(current_level->snoman_pos)) { + if (((ABS(current_level->snoman_pos - current_level->player_pos) <= 1) && + PROB(PROB_SKIS_MELT_SNOMAN)) || + PROB(PROB_SPONTANEOUS_MELT)) { + current_level->snoman_pos = NO_POSITION; + ++current_level->num_snomen_melted; + } + } + + /* + ** If there is a Snoman, move him towards the player. If there is a ** tree in the way, the Snoman is blocked. + */ + + if (EXISTS(current_level->snoman_pos)) { + if (current_level->snoman_pos < current_level->player_pos) { + if (current_level->slope[current_level->snoman_pos + 1] != REP_TREE) + ++current_level->snoman_pos; + } + + else { + if (current_level->slope[current_level->snoman_pos - 1] != REP_TREE) + --current_level->snoman_pos; + } + } + + /* + ** If there is an ICBM, handle it. + */ + + if (EXISTS(current_level->icbm_pos)) { + /* + ** If there is a Snoman, move the ICBM towards him. Else, + ** self-destruct the ICBM. + */ + + if (EXISTS(current_level->snoman_pos)) { + if (current_level->icbm_pos < current_level->snoman_pos) + current_level->icbm_pos += ICBM_SPEED; + else + current_level->icbm_pos -= ICBM_SPEED; + } + else + current_level->icbm_pos = NO_POSITION; + } + + /* + ** If there is a fire demon on the level, handle it. + */ + + if (EXISTS(current_level->demon_pos)) { + /* + ** If there is a Snoman on the current level, move the demon + ** towards him. Else, the demon might decide to leave. + */ + + if (EXISTS(current_level->snoman_pos)) { + if (current_level->demon_pos < current_level->snoman_pos) + current_level->demon_pos += DEMON_SPEED; + else + current_level->demon_pos -= DEMON_SPEED; + } + else { + if (PROB(25.0)) + current_level->demon_pos = NO_POSITION; + } + } + + /* + ** If there is a Snoman and an ICBM on the slope, the Snoman + ** might get melted. + */ + + if (EXISTS(current_level->snoman_pos) && EXISTS(current_level->icbm_pos)) { + if (ABS(current_level->snoman_pos - current_level->icbm_pos) <= ICBM_RANGE) { + current_level->icbm_pos = NO_POSITION; + current_level->snoman_pos = NO_POSITION; + ++current_level->num_snomen_melted; + } + } + + /* + ** If there is a Snoman and a fire demon, he might get melted. + */ + + if (EXISTS(current_level->snoman_pos) && EXISTS(current_level->demon_pos)) { + if (ABS(current_level->snoman_pos - current_level->demon_pos) <= 1) { + current_level->snoman_pos = NO_POSITION; + ++current_level->num_snomen_melted; + } + } +} + +/* +** "accident" is called when the player gets into an accident, which ends the +** game. "msg" is the description of the accident type, and "severity" is +** the severity. This function should never return. +*/ + +PRIVATE int accident(current_level, msg, severity) +LEVEL *current_level; +char *msg; +short severity; +{ + int degree; + long score; + + /* + ** Compute the degree of the player's injuries. + */ + + degree = severity + (RANDOM_GENERATE() % INJURY_RANDOMNESS); + + /* + ** Print a message indicating the termination of the game. + */ + + printf("\n\n%s %s\n\n", msg, injuries[degree]); + + /* + ** Print the statistics of the game. + */ + + printf("You skiied %d meters with %.1f jumps and melted %d Snowm%cn.\n", + current_level->meters_travelled, + current_level->num_jumps_attempted, + current_level->num_snomen_melted, + (current_level->num_snomen_melted == 1) ? 'a' : 'e'); + + /* + ** Initially calculate the player's score based upon the number of + ** meters travelled. + */ + + score = current_level->meters_travelled * POINTS_PER_METER; + + /* + ** Add bonus points for the number of jumps completed. + */ + + score += current_level->num_jumps_attempted * POINTS_PER_JUMP; + + /* + ** Add bonus points for each Snoman that melted during the course of + ** the game. + */ + + score += current_level->num_snomen_melted * POINTS_PER_MELTED_SNOMAN; + + /* + ** Subtract a penalty for the degree of injury experienced by the + ** player. + */ + + score += degree * POINTS_PER_INJURY_DEGREE; + + /* + ** Print the player's score. + */ + + printf("Your score for this run is %ld.\n", score); + + /* + ** Exit the game with a code indicating successful completion. + */ + + exit(0); +} + +/* +** "check_obstacles" +*/ + +PRIVATE int check_obstacles(current_level) +LEVEL *current_level; +{ + short player_pos; + char *slope; + + player_pos = current_level->player_pos; + slope = current_level->slope; + + /* + ** If we are just landing after a jump, we might fall down. + */ + + if ((current_level->jump_count == 0) && PROB(PROB_BAD_LANDING)) + accident(current_level, "Whoops! A bad landing!", + SLIGHT_INJURY); + + /* + ** If there is a tree in our position, we might hit it. + */ + + if ((slope[player_pos] == REP_TREE) && PROB(PROB_HIT_TREE)) + accident(current_level, "Oh no! You hit a tree!", + SEVERE_INJURY); + + /* + ** If there is bare ground under us, we might fall down. + */ + + if ((slope[player_pos] == REP_GROUND) && PROB(PROB_FALL_ON_GROUND)) + accident(current_level, "You fell on the ground!", + MODERATE_INJURY); + + /* + ** If we are on ice, we might slip. + */ + + if ((slope[player_pos] == REP_ICE) && PROB(PROB_SLIP_ON_ICE)) + accident(current_level, "Oops! You slipped on the ice!", + SLIGHT_INJURY); + + /* + ** If there is a Snoman next to us, he may grab us. + */ + + if (EXISTS(current_level->snoman_pos) && + (ABS(current_level->snoman_pos - player_pos) <= 1)) + accident(current_level, "Yikes! The Snoman's got you!", + MODERATE_INJURY); +} + +/* +** "do_command" gets a command from the player and performs it. +*/ + +PRIVATE int do_command(current_level) +LEVEL *current_level; +{ + register int player_pos; + char command_buf[LINE_LEN + 1]; + short command_key; + + player_pos = current_level->player_pos; + + /* + ** Print a prompt, and read a command. + */ + + redo: + printf("? "); + + fgets(command_buf, sizeof command_buf, stdin); + + command_key = command_buf[0]; + + if (islower(command_key)) + command_key = toupper(command_key); + + switch (command_key) { + case '!': + system(command_buf + 1); + draw_picture(current_level); + goto redo; + + case 'R': /* Move right */ + if ((current_level->slope[player_pos] != REP_ICE) && + (current_level->player_speed < MAX_HORIZONTAL_PLAYER_SPEED)) + ++current_level->player_speed; + + break; + + case 'L': /* Move left */ + if ((current_level->slope[player_pos] != REP_ICE) && + (current_level->player_speed > -MAX_HORIZONTAL_PLAYER_SPEED)) + --current_level->player_speed; + + break; + + case 'J': /* jump */ + current_level->jump_count = (RANDOM_GENERATE() % 6) + 4; + current_level->num_jumps_attempted += 1.0; + break; + + case 'H': /* Do a hop */ + current_level->jump_count = (RANDOM_GENERATE() % 3) + 2; + current_level->num_jumps_attempted += 0.5; + break; + + case 'T': /* Attempt teleportation */ + if (PROB(PROB_BAD_TELEPORT)) + accident(current_level, + "You materialized 25 feet in the air!", + SLIGHT_INJURY); + + current_level->player_pos = RANDOM_GENERATE() % LINE_LEN; + break; + + case 'I': /* Launch backpack ICBM */ + if (PROB(PROB_BAD_ICBM)) + accident(current_level, + "Nuclear blast in your backpack!", + SEVERE_INJURY); + + current_level->icbm_pos = player_pos; + break; + + case 'D': /* Incant spell for fire demon */ + if (PROB(PROB_BAD_SPELL)) + accident(current_level, + "A bad spell -- the demon grabs you!", + MODERATE_INJURY); + + current_level->demon_pos = RANDOM_GENERATE() % LINE_LEN; + break; + + default: + break; + } +} -- 2.43.0