]> thyrsus.com Git - ski.git/commitdiff
Initial revision
authorEric S. Raymond <esr@thyrsus.com>
Mon, 8 Nov 1993 15:12:51 +0000 (15:12 +0000)
committerEric S. Raymond <esr@thyrsus.com>
Mon, 8 Nov 1993 15:12:51 +0000 (15:12 +0000)
do_level.c [new file with mode: 0644]

diff --git a/do_level.c b/do_level.c
new file mode 100644 (file)
index 0000000..f313124
--- /dev/null
@@ -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 <stdio.h>
+#include <ctype.h>
+#ifdef CURSES
+#include <curses.h>
+#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;
+       }
+}