GAME: Robots, unfinished (2006)

This commit is contained in:
kougyokugentou 2021-10-24 16:19:06 -07:00
parent 0e0f5e966a
commit ad4c5e0650
2 changed files with 612 additions and 0 deletions

508
robots/my_robots.c Normal file
View File

@ -0,0 +1,508 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <ncurses/curses.h>
#include "my_robots.h"
#include "alloc_perm.h"
/* function declarations */
void init_plr_data(PLAYER_DATA *player);
void init_robots(int level);
void game_loop(PLAYER_DATA *player);
void DrawPerimeter(void);
void PlayerInput(PLAYER_DATA *player);
void RedrawScreen(PLAYER_DATA *player);
void move_ch(PLAYER_DATA *player);
int CheckWalls(PLAYER_DATA *player);
void robot_movement(PLAYER_DATA *player);
void locate(int x, int y);
int rnd(int range);
/* curses
int clear(void); //clears the screen
int move(int y, int x); //move the cursor
int getch(void); //gets a character
int refresh(void); //must be called to get output to the terminal
chtype winch(WINDOW *win); //get character at current cursor location
int addstr(const char *str); //curses printf
int addch(const ctype *ch); //curses putchar (dont move anything)
int insch(ctype *ch); //putchar (move everything right, use after delch)
int delch(void) //curses 'delete character' (moves everything left)
*/
/* global vars */
int game_over;
int num_robots;
WINDOW *robot_game;
/* Begin Program */
int main(void)
{
PLAYER_DATA *player;
game_over = FALSE;
player = alloc_perm(sizeof(*player));
// malloc(sizeof(*player));
/* init curses */
robot_game = initscr();
cbreak();
noecho();
nonl();
intrflush(robot_game, FALSE);
// keypad(robot_game, TRUE);
leaveok(robot_game, TRUE);
/* GO TIME */
clear();
refresh();
DrawPerimeter();
init_plr_data(player);
init_robots(player->level);
do
{
game_loop(player);
}
while(!game_over);
locate(0,BOTTOM_ROW+1);
addstr("GAME OVER press enter to exit the game.");
getch();
/* uninit curses */
nocbreak();
echo();
nl();
leaveok(robot_game, FALSE);
clear();
refresh();
locate(0,0);
endwin();
return 0;
}
void init_plr_data(PLAYER_DATA *player)
{
player->level = 1;
player->prev_level = 1;
player->restart_level = FALSE;
player->lives = LIVES;
player->current_x = 40;
player->current_y = 12;
player->NewX = player->current_x;
player->NewY = player->current_y;
locate(player->current_x, player->current_y);
addch(PLAYER);
return; //game_loop
}
void init_robots(int level)
{
int rnd_x;
int rnd_y;
int robot = 0;
seedrnd();
switch(level)
{
case 1:
case 2:
case 3:
case 4:
num_robots = rnd(6); //up to 6 robots at first.
break;
case 5:
case 6:
case 7:
case 8:
num_robots = rnd(10)+5; //level 5 - 10 robots
break;
case 9:
case 10:
case 11:
num_robots = rnd(13)+9; //level 9 - 13 robots
break;
case 12:
case 13:
case 14:
num_robots = rnd(18)+12; //level 12 - 18 robots
break;
case 15:
default:
num_robots = rnd(20)+15; //level 15 - 20 robots
break;
}
/* make it possible to win */
if(num_robots <= 1)
num_robots = 2;
for(robot = 0; robot < num_robots; robot++)
{
/* do not place a dead robot -- for use in RedrawScreen
if(robot_table[robot].dead == 1)
continue;
*/
for(;;)
{
rnd_x = number_range(2, LAST_COLUMN-1);
rnd_y = number_range(2, BOTTOM_ROW-1);
locate(rnd_x, rnd_y);
if( (winch(robot_game) & A_CHARTEXT) == ROBOT
|| (winch(robot_game) & A_CHARTEXT) == PLAYER)
continue;
break;
}
/* Place the robots. */
robot_table[robot].x = rnd_x;
robot_table[robot].y = rnd_y;
robot_table[robot].dead = 0;
addch(ROBOT);
refresh();
}
return;
}
void DrawPerimeter(void)
{
int DrawX;
int DrawY;
for(DrawX = 0; DrawX <= LAST_COLUMN; DrawX++)
{
locate(DrawX,0);
addch(WALL);
locate(DrawX,BOTTOM_ROW);
addch(WALL);
}
for(DrawY = 1; DrawY < BOTTOM_ROW; DrawY++)
{
locate(0,DrawY);
addch(WALL);
locate(LAST_COLUMN,DrawY);
addch(WALL);
}
return;
}
void game_loop(PLAYER_DATA *player)
{
locate(player->current_x, player->current_y);
PlayerInput(player);
robot_movement(player);
/* Level Up and Player Death */
if(player->level > player->prev_level //level up
|| player->restart_level == TRUE) //player death
{
player->prev_level = player->level;
clear();
refresh();
DrawPerimeter();
player->restart_level = FALSE;
player->current_x = 40;
player->current_y = 12;
locate(player->current_x, player->current_y);
addch(PLAYER);
init_robots(player->level);
}
return;
}
/* Move all robots towards the player. */
void robot_movement(PLAYER_DATA *player)
{
int robot = 0;
int num_robots_left = 0;
int dead_robot = 0;
if(game_over)
return;
for(robot = 0; robot < num_robots; robot++)
{
/* if the robot is destroyed, skip it. */
if(robot_table[robot].dead == TRUE)
continue;
num_robots_left++;
}
/* If all the robots are dead, we have passed the level.
* May give a BUG where robots will no longer move after
* one or more robots are destroyed */
if(num_robots_left == 0)
return;
for(robot = 0; robot < num_robots; robot++)
{
/* if the robot is destroyed, skip it. */
if(robot_table[robot].dead == TRUE)
continue;
locate(robot_table[robot].x, robot_table[robot].y);
delch();
insch(' ');
refresh();
//printf("\b \b"); //erase robot character
/* move robot left */
if(robot_table[robot].x > player->current_x)
{
robot_table[robot].x -= 1;
}
/* move robot right */
if(robot_table[robot].x < player->current_x)
{
robot_table[robot].x += 1;
}
/* move robot up */
if(robot_table[robot].y > player->current_y)
{
robot_table[robot].y -=1;
}
/* move robot down */
if(robot_table[robot].y < player->current_y)
{
robot_table[robot].y += 1;
}
locate(robot_table[robot].x, robot_table[robot].y);
/* delch(); //erase whatever's there
insch(ROBOT);
*/
/* Player is DEAD!!! */
if(robot_table[robot].x == player->current_x
&& robot_table[robot].y == player->current_y)
{
player->lives--;
player->restart_level = TRUE;
if(player->lives <= 0) //Game Over
{
game_over = TRUE;
return;
}
}
/* Robot runs into another robot, destroy them. */
if( (winch(robot_game) & A_CHARTEXT) == ROBOT
|| (winch(robot_game) & A_CHARTEXT) == DEAD_ROBOT)
{
delch();
insch(DEAD_ROBOT);
refresh();
robot_table[robot].dead = TRUE;
for(dead_robot = 0; dead_robot < num_robots; dead_robot++)
{ /* robot = already dead (above) dead_robot = dying robot */
if(robot_table[robot].number == robot_table[dead_robot].number)
continue;
if(robot_table[robot].x == robot_table[dead_robot].x
&& robot_table[robot].y == robot_table[dead_robot].y)
{
robot_table[dead_robot].dead = TRUE; //We ran into this robot.
}
}
}
/* Place the live robot*/
if(!robot_table[robot].dead)
{
delch();
insch(ROBOT);
refresh();
}
} //end for
/* end robot movement */
return;
}
void PlayerInput(PLAYER_DATA *player)
{
char key;
int OldX;
int OldY;
int rnd_x;
int rnd_y;
int robot = 0;
int num_robots_left = 0;
OldX = player->current_x;
OldY = player->current_y;
player->NewX = player->current_x;
player->NewY = player->current_y;
seedrnd();
/* This is here as a cheap hack so you dont have to move again
* after the level is cleared of all robots */
for(robot = 0; robot < num_robots; robot++)
{
/* if the robot is destroyed, skip it. */
if(robot_table[robot].dead == TRUE)
continue;
num_robots_left++;
}
/* If there are no more robots left, win level. */
if(num_robots_left == 0)
{
player->level++;
return;
}
for(;;)
{
rnd_x = number_range(2, LAST_COLUMN-1);
rnd_y = number_range(2, BOTTOM_ROW-1);
locate(rnd_x, rnd_y);
if(rnd_x == player->current_x
&& rnd_y == player->current_y)
continue;
if( (winch(robot_game) & A_CHARTEXT) != ROBOT
&& (winch(robot_game) & A_CHARTEXT) != DEAD_ROBOT
&& (winch(robot_game) & A_CHARTEXT) != PLAYER
&& (winch(robot_game) & A_CHARTEXT) != WALL )
break;
}
key = getch();
if(key == ESC)
{
game_over = TRUE;
return;
}
switch(toupper(key))
{
case ESC:
game_over = TRUE;
break;
case 'W':
player->NewY = OldY-1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'A':
player->NewX = OldX-1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'S':
player->NewY = OldY+1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'D':
player->NewX = OldX+1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'Q':
player->NewX = OldX-1;
player->NewY = OldY-1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'E':
player->NewX = OldX+1;
player->NewY = OldY-1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'Z':
player->NewX = OldX-1;
player->NewY = OldY+1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'X':
case 'C':
player->NewX = OldX+1;
player->NewY = OldY+1;
if( !CheckWalls(player) ) move_ch(player);
break;
case 'R':
player->NewX = rnd_x;
player->NewY = rnd_y;
if( !CheckWalls(player) ) move_ch(player);
break;
/* case 'H':
locate(0,1);
printf("\n\r# -= HELP=-");
printf("\n\r# 1. Controls:");
printf("\n\r# ESC KEY: Quit the game.");
printf("\n\r# W - Up; A - Left; S - Down; D - Right");
printf("\n\r#\n\r# Press Enter to continue with the game.");
getch();
RedrawScreen(player);
break;
*/
default:
/* printf("\n\r# I don't know that command. Press any key to continue, then Type H for help.");
getch();
RedrawScreen(player); */
break;
}
return;
}
void move_ch(PLAYER_DATA *player)
{
locate(player->current_x, player->current_y);
delch();
insch(' ');
refresh();
player->current_x = player->NewX;
player->current_y = player->NewY;
locate(player->current_x, player->current_y);
addch(PLAYER);
return;
}
int CheckWalls(PLAYER_DATA *player)
{
int CheckX;
int CheckY;
CheckX = player->NewX;
CheckY = player->NewY;
locate(CheckX, CheckY);
if( (winch(robot_game) & A_CHARTEXT) == WALL
|| (winch(robot_game) & A_CHARTEXT) == ROBOT
|| (winch(robot_game) & A_CHARTEXT) == DEAD_ROBOT
|| CheckX < 0 || CheckX > LAST_COLUMN-1
|| CheckY < 0 || CheckY > BOTTOM_ROW-1 )
return(TRUE);
return(FALSE);
}

104
robots/my_robots.h Normal file
View File

@ -0,0 +1,104 @@
//#define PLAYER 0x01
#define PLAYER 'X'
#define ROBOT 'o'
#define DEAD_ROBOT '%'
#define WALL '#'
#define BOTTOM_ROW 22
#define LAST_COLUMN 79
#define ESC 0x1b //Escape Key
#define TRUE 1
#define FALSE 0
#define LIVES 3
/* globals */
typedef struct player_data PLAYER_DATA;
struct player_data
{
int current_x;
int current_y;
int NewX;
int NewY;
int level;
int restart_level;
int prev_level;
int lives;
};
struct robot_data
{
int number;
int x;
int y;
int dead;
};
struct robot_data robot_table[21] = //20 max robots for now
{
/* { number, x, y, dead } */
{ 1, 0, 0, 0 },
{ 2, 0, 0, 0 },
{ 3, 0, 0, 0 },
{ 4, 0, 0, 0 },
{ 5, 0, 0, 0 },
{ 6, 0, 0, 0 },
{ 7, 0, 0, 0 },
{ 8, 0, 0, 0 },
{ 9, 0, 0, 0 },
{ 10, 0, 0, 0 },
{ 11, 0, 0, 0 },
{ 12, 0, 0, 0 },
{ 13, 0, 0, 0 },
{ 14, 0, 0, 0 },
{ 15, 0, 0, 0 },
{ 16, 0, 0, 0 },
{ 17, 0, 0, 0 },
{ 18, 0, 0, 0 },
{ 19, 0, 0, 0 },
{ 20, 0, 0, 0 },
{ 0, 0, 0, 0} //all 0's is the end
};
/* Randomizer. */
void seedrnd(void) //Seed the randomizer
{
srand((unsigned)time(NULL));
}
int rnd(int range)
{
return(rand()%range); //spit up random num 0-range
}
long number_mm(void)
{
return random() >> 6;
}
int number_range(int from, int to)
{
int power;
int number;
if (from == 0 && to == 0)
return 0;
if ( ( to = to - from + 1 ) <= 1 )
return from;
for ( power = 2; power < to; power <<= 1)
;
while ( ( number = number_mm() & (power -1 ) ) >= to )
;
return from+number;
}
void locate(int x, int y)
{
move(y, x);
refresh();
return;
}