Skip to content

Instantly share code, notes, and snippets.

@wernsey
Created October 28, 2022 15:19
Show Gist options
  • Save wernsey/ca4ac0c73eaaf2f7ff8d9db884d3c40e to your computer and use it in GitHub Desktop.
Save wernsey/ca4ac0c73eaaf2f7ff8d9db884d3c40e to your computer and use it in GitHub Desktop.
/***************************************************************************
*
*
* chase appeared in Creative Computing
* magazine way back in 1976. According
* to the book "More BASIC Computer Games"
* it was written by Mac Oglesby, with
* improvements by Bill Cotter and Arnold
* Loveridge.
* This version, in C, was written by
* Ken Brown. 7/25/84
* Code specific to the Microsoft C compiler
* is noted.
* The cursor movement routines assume that
* the DOS 2.x ANSI.SYS driver has been
* loaded.
*
* It was further modified in 2022 by Werner Stoop (https://github.com/wernsey)
* to make the code C89 and get it working with Borland Turbo C (under DOSBox)
* It even compiles with GCC under Linux, though the characters are wrong
* I found it in \MSDOS\C\CHASE.ZIP in a Symtel CD on archive.org
*
*
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* constant definitions */
#define TRUE 1
#define FALSE 0
#define XDIM 60
#define YDIM 20
#define MAX_ROBOTS 120
#define MAX_FENCES 120
#define MIN_FENCES 5
#define MIN_ROBOTS 5
#define MY_CHAR '\002'
#define ROB_CHAR '\004'
#define JUNK_CHAR '@'
#define FENCE_CHAR 'X'
/* global variable definitions */
char field[YDIM][XDIM],
field_save[YDIM][XDIM];
int robot_y[MAX_ROBOTS],
robot_x[MAX_ROBOTS],
robot_y_save[MAX_ROBOTS],
robot_x_save[MAX_ROBOTS],
my_x,
my_y,
last_stand,
my_x_save,
my_y_save,
no_robots,
no_fences;
unsigned int seed;
/* Prototypes */
void initial(void);
void instruct(void);
void new_board(void);
void old_board(void);
int move_me(void);
int move_robots(void);
int more_robots(void);
void draw_board(void);
void getnum(int *number);
void findspot(int *new_y, int *new_x);
int rnd(int range);
int sgn(int number);
void move(int y, int x);
void clrtoeol(int y, int x);
void clear(void);
void print_me(void);
void print_robot(void);
void flash(int y, int x);
int main()
{
int i_won,
game_over,
set_up,
c;
initial();
instruct();
set_up=TRUE;
while(TRUE) {
if(set_up)
new_board();
else
old_board();
last_stand=FALSE;
game_over=FALSE;
i_won=FALSE;
while(!game_over) {
if(!last_stand)
game_over=move_me();
if(!game_over)
game_over=move_robots();
else
break;
if(!game_over) {
if(more_robots()==TRUE)
continue;
else {
i_won=TRUE;
break;
}
}
}
if (i_won) {
move(21,0);
printf("You have destroyed all your opponents -- the game is yours");
}
move(22,0);
printf("another game? (y/n)");
c=getchar();
c=tolower(c);
if(c=='n')
break;
move(23,0);
printf("same set-up? (y/n)");
c=getchar();
c=tolower(c);
if(c=='y')
set_up=FALSE;
else
set_up=TRUE;
}
clear();
move(22,0);
return EXIT_SUCCESS;
}
/*
* get a seed for the random number generator
*/
void initial()
{
clear();
do {
clrtoeol(10,0);
printf("Enter a seed for the random number generator? ");
getnum((int *)&seed);
} while(seed<=0);
move(18,0);
printf("Be sure to lock the NUM LOCK KEY to use the numeric keypad");
}
/*
* print instructions
*/
void instruct()
{
int c;
move(20,0);
printf("do you want instructions? (y/n)");
c=getchar();
c=tolower(c);
if (c=='y') {
clear();
move(2,0);
printf("you are within the walls of a high voltage maze\r\n");
printf("the areas marked '%c' are high voltage fences\r\n",FENCE_CHAR);
printf("being chased by robots\r\n");
printf("your only chance for survival is to maneuver each\r\n");
printf("robot into a fence\r\n");
printf("you are the '%c' the robots are the '%c'\r\n",MY_CHAR,ROB_CHAR);
printf("moves are: 7.8.9\r\n");
printf(" 4.*.6\r\n");
printf(" 1.2.3\r\n");
printf("\r\nj = a tremendous (but unfortunately random leap)\r\n");
printf("s = no move for rest of the game\r\n");
printf("q = gave up, situation hopeless.\r\n");
printf("\r\n\r\ngood luck!!");
move(22,0);
printf("press any key to begin");
c=getchar();
}
}
/*
* create and display a new playing board
*/
void new_board()
{
int y_coor,
x_coor,
fen_count,
rob_count;
clear();
do {
clrtoeol(10,0);
printf("how many robots? (5 to 120) ");
getnum(&no_robots);
} while(no_robots<MIN_ROBOTS||no_robots>MAX_ROBOTS);
do {
clrtoeol(12,0);
printf("how many fences? (5 to 120) ");
getnum(&no_fences);
} while(no_fences<MIN_FENCES||no_fences>MAX_FENCES);
clear();
move(10,34);
printf("working.....");
for(y_coor=0; y_coor<YDIM; y_coor++) {
for(x_coor=0; x_coor<XDIM; x_coor++)
field[y_coor][x_coor]=' ';
}
for (y_coor=0; y_coor<YDIM; y_coor++) {
field[y_coor][0]=FENCE_CHAR;
field[y_coor][XDIM-1]=FENCE_CHAR;
}
for(x_coor=0; x_coor<XDIM; x_coor++) {
field[0][x_coor]=FENCE_CHAR;
field[YDIM-1][x_coor]=FENCE_CHAR;
}
for(fen_count=0; fen_count<no_fences; fen_count++) {
findspot(&y_coor, &x_coor);
field[y_coor][x_coor]=FENCE_CHAR;
}
findspot(&my_y, &my_x);
field[my_y][my_x]=MY_CHAR;
for (rob_count=0; rob_count<no_robots; rob_count++) {
findspot(&robot_y[rob_count], &robot_x[rob_count]);
field[robot_y[rob_count]][robot_x[rob_count]]=ROB_CHAR;
}
for (y_coor=0; y_coor<YDIM; y_coor++) {
for (x_coor=0; x_coor<XDIM; x_coor++) {
field_save[y_coor][x_coor]=field[y_coor][x_coor];
}
}
for (rob_count=0; rob_count<no_robots; rob_count++) {
robot_y_save[rob_count]=robot_y[rob_count];
robot_x_save[rob_count]=robot_x[rob_count];
}
my_y_save=my_y;
my_x_save=my_x;
draw_board();
}
/*
* reload and display the previous board
*/
void old_board()
{
int y_coor,
x_coor,
rob_count;
for(y_coor=0; y_coor<YDIM; y_coor++) {
for(x_coor=0; x_coor<XDIM; x_coor++) {
field[y_coor][x_coor]=field_save[y_coor][x_coor];
}
}
for(rob_count=0; rob_count<no_robots; rob_count++) {
robot_y[rob_count]=robot_y_save[rob_count];
robot_x[rob_count]=robot_x_save[rob_count];
}
my_y=my_y_save;
my_x=my_x_save;
draw_board();
}
/*
* player's movement routine
*/
int move_me()
{
int c,
my_x_old,
my_y_old;
my_x_old=my_x;
my_y_old=my_y;
move(22,69);
putchar('*');
putchar('\b');
while(TRUE) {
c=getchar();
c=tolower(c);
if(isdigit(c)||c=='j'||c=='s'||c=='q')
break;
if(c==0) /* trap for funtion keys */
c=getchar();
putchar('\007');
}
putchar(c);
switch(c) {
case '1':
my_y++;
my_x--;
break;
case '2':
my_y++;
break;
case '3':
my_y++;
my_x++;
break;
case '4':
my_x--;
break;
case '6':
my_x++;
break;
case '7':
my_y--;
my_x--;
break;
case '8':
my_y--;
break;
case '9':
my_y--;
my_x++;
break;
case 'q':
clear();
move(10,36);
printf("chicken\n\n\n");
move(22,0);
exit(0);
case 'j':
my_y=1+rnd(YDIM-2);
my_x=1+rnd(XDIM-2);
break;
case 's':
last_stand=TRUE;
break;
default:
break;
}
field[my_y_old][my_x_old]=' ';
move(my_y_old,my_x_old);
putchar(' ');
c=field[my_y][my_x];
switch(c) {
case ROB_CHAR:
flash(my_y,my_x);
flash(my_y,my_x);
move(my_y,my_x);
printf("**MUNCH**");
move(21,0);
printf("You have been eaten by robots");
return(TRUE);
case FENCE_CHAR:
case JUNK_CHAR:
flash(my_y,my_x);
flash(my_y,my_x);
move(my_y,my_x);
printf("**ZAP**");
move(21,0);
printf("High Voltage!!! Zap, you're dead!");
return(TRUE);
default:
field[my_y][my_x]=MY_CHAR;
move(my_y,my_x);
print_me();
break;
}
return(FALSE);
}
/*
* movement routine for robots
*/
int move_robots()
{
int rob_count,
c;
for(rob_count=0; rob_count<no_robots; rob_count++) {
if((c=field[robot_y[rob_count]][robot_x[rob_count]])!=ROB_CHAR)
continue;
move(robot_y[rob_count], robot_x[rob_count]);
putchar(' ');
field[robot_y[rob_count]][robot_x[rob_count]]=' ';
robot_y[rob_count]=robot_y[rob_count]+sgn(my_y-robot_y[rob_count]);
robot_x[rob_count]=robot_x[rob_count]+sgn(my_x-robot_x[rob_count]);
c=field[robot_y[rob_count]][robot_x[rob_count]];
switch(c) {
case MY_CHAR:
move(robot_y[rob_count],robot_x[rob_count]);
print_robot();
field[robot_y[rob_count]][robot_x[rob_count]]=ROB_CHAR;
flash(robot_y[rob_count],robot_x[rob_count]);
flash(robot_y[rob_count],robot_x[rob_count]);
move(robot_y[rob_count],robot_x[rob_count]);
printf("**MUNCH**");
move(21,0);
printf("you have been eaten by robots");
return(TRUE);
case ROB_CHAR:
move(robot_y[rob_count],robot_x[rob_count]);
putchar(JUNK_CHAR);
field[robot_y[rob_count]][robot_x[rob_count]]=JUNK_CHAR;
flash(robot_y[rob_count],robot_x[rob_count]);
break;
case JUNK_CHAR:
flash(robot_y[rob_count],robot_x[rob_count]);
break;
case FENCE_CHAR:
flash(robot_y[rob_count],robot_x[rob_count]);
break;
default:
move(robot_y[rob_count],robot_x[rob_count]);
print_robot();
field[robot_y[rob_count]][robot_x[rob_count]]=ROB_CHAR;
break;
}
}
return(FALSE);
}
/*
* check whether more robots are still alive
*/
int more_robots()
{
int rob_count;
for(rob_count=0; rob_count<no_robots; rob_count++) {
if(field[robot_y[rob_count]][robot_x[rob_count]]==ROB_CHAR)
return(TRUE);
}
return(FALSE);
}
/*
* draw the board from the array board[][]
*/
void draw_board()
{
int y_coor,
x_coor,
rob_count;
clear();
move(0,0);
for(y_coor=0; y_coor<YDIM; y_coor++) {
for(x_coor=0; x_coor<XDIM; x_coor++) {
putchar(field[y_coor][x_coor]);
}
move(y_coor+1,0);
}
move(my_y,my_x);
print_me();
for(rob_count=0; rob_count<no_robots; rob_count++) {
move(robot_y[rob_count],robot_x[rob_count]);
print_robot();
}
move(1,63);
printf("Move Control:");
move(2,67);
printf("7 8 9");
move(3,68);
printf("\\|/");
move(4,67);
printf("4-5-6");
move(5,68);
printf("/|\\");
move(6,67);
printf("1 2 3");
move(9,66);
printf("Commands:");
move(10,63);
printf("j - a giant jump");
move(11,63);
printf("s - last stand");
move(12,63);
printf("q - quit");
move(15,66);
printf("Key:");
move(16,63);
printf("* - you");
move(17,63);
printf("+ - robot");
move(18,63);
printf("@ - junked robot");
move(19,63);
printf("X - electic fence");
move(22,63);
printf("Move [*]");
}
/*
* get a numeric input from the player
* non-numberic characters are locked out
* and the maximum length is arbitrarily set
* at 5 digits
*/
void getnum(int *number)
{
int c,
count;
char string[6];
count=0;
while((c=getchar())!='\n'&&c!='\r') {
switch(c) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
if(count<5) {
string[count++]=c;
putchar(c);
}
break;
case '\b':
if(count>0) {
count--;
putchar('\b');
putchar(' ');
putchar('\b');
} else {
putchar('\007');
}
break;
default:
putchar('\007');
break;
}
}
string[count]='\0';
*number = atoi(string);
}
/*
* locate a empty board position
*/
void findspot(int *new_y, int *new_x)
{
do {
*new_y=1+rnd(YDIM-2);
*new_x=1+rnd(XDIM-2);
} while(field[*new_y][*new_x] != ' ');
}
/*
* generate a random number in the
* range 0<= number < range
*/
int rnd(int range)
{
float x;
seed = (seed * 15625) & 0xFFFF; /* Multiplication mod 65536 */
x=(seed/65536.0)*(float)range;
return((int)x);
}
/*
* return the sign of a number
*/
int sgn(int number)
{
if (number<0)
return(-1);
if(number>0)
return(1);
return(0);
}
/*****************************************************************************
*
* these routines assume that the ANSI.SYS driver
* has been loaded
*
*****************************************************************************/
void move(int y, int x)
{
printf("\033[%d;%dH",y+1,x+1); /* cursor postions are incremented
by one because playing board
starts at (0,0) and screen
starts at (1,1) */
}
void clrtoeol(int y, int x)
{
move(y,x);
printf("\033[K");
}
void clear()
{
printf("\033[2J");
}
void print_me()
{
printf("\033[1m");
putchar(MY_CHAR);
printf("\033[0m");
}
void print_robot()
{
printf("\033[1m");
putchar(ROB_CHAR);
printf("\033[0m");
}
void flash(int y, int x)
{
int count,
c;
c=field[y][x];
move(y,x);
for(count=0; count<20; count++) {
printf("\033[1m");
putchar(80);
putchar('\b');
printf("\033[0m");
putchar(c);
putchar('\b');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment