module
38

The course disc is hisoftc.mfi, an image of a 40-track double-sided disc for a Tatung Einstein TC-01, built from XtalDOS 1.31's system tracks with the files below on it. It is what S3 boots. A .dsk cannot be written to in MAME (S3); the .mfi can, so your programs are saved on it.
| File | Bytes | What it is |
|---|---|---|
HC.COM | 27,392 | The compiler: HiSoft-C Compiler V1.35 (1985) |
STDIO.H | 3,072 | The names the library needs; the first line of every program |
STDIO.LIB | 11,008 | The standard library, as C source, searched by #include ?STDIO.LIB? |
CPM.LIB | 14,464 | The CP/M library: the command line, files, cpm_bdos (S34) |
EIN.LIB | 5,248 | The Einstein library: screen, keyboard, graphics, sprites, sound (S23) |
EINLIB.HLP | 6,400 | Its help file: DISP EINLIB.HLP |
ED.COM | 9,216 | The editor, ED80, as you run it |
ED80.COM | 9,216 | The same editor under the name the compiler chains to after an error (S7) |
ED.HLP | 2,176 | ED80's help: GRPH-J inside the editor |
BREAKOUT.C | 6,656 | The finished game's source (S33) |
BREAKOUT.COM | 8,704 | The finished game: type BREAKOUT |
DIR shows 116k Size, 72k Free, 190k Total: eleven files, and room for nine or so programs of your own (S6). Nothing else from HiSoft's original disc is needed for the course.
The seven stages of Breakout, S27 to S33, are not on the disc - they would have taken half the free space - and are printed here in full, BREAK1.C to BREAK7.C. BREAK7.C and BREAKOUT.C are the same program. To type one, type it; to skip ahead, BREAKOUT.C on the disc is the finished one.
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define WALL '#'
#define BATCHAR '='
typedef struct {
int left, width;
} bat;
bat paddle;
void draw_court()
{
int i;
cls40();
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void draw_bat(b) bat *b;
{
int i;
curat(b->left, BATROW);
for (i = 0; i < b->width; i++)
putchar(BATCHAR);
}
main()
{
char line[40];
paddle.width = 5;
paddle.left = 18;
draw_court();
draw_bat(&paddle);
curat(0, 22);
curoff();
rawin();
curon();
cls40();
printf("Press ENTER to finish\n");
gets(line);
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define PLAYLEFT 2
#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 'o'
#define TICK 3
typedef struct {
int left, width;
} bat;
typedef struct {
int x, y, dx, dy;
int oldx, oldy;
} ball;
bat paddle;
ball b;
void draw_court()
{
int i;
cls40();
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void draw_bat(p) bat *p;
{
int i;
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
putchar(BATCHAR);
}
void move_ball(p) ball *p;
{
p->oldx = p->x;
p->oldy = p->y;
p->x += p->dx;
p->y += p->dy;
if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
p->dy = -p->dy;
}
void draw_ball(p) ball *p;
{
curat(p->oldx, p->oldy);
putchar(' ');
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
main()
{
char line[40];
paddle.width = 5;
paddle.left = 18;
b.x = 20;
b.y = 12;
b.dx = 1;
b.dy = -1;
b.oldx = b.x;
b.oldy = b.y;
draw_court();
draw_bat(&paddle);
curoff();
while (b.y < BATROW) {
move_ball(&b);
draw_ball(&b);
wait_frames(TICK);
}
curon();
curat(0, 22);
printf("Lost. Press ENTER");
gets(line);
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define PLAYLEFT 2
#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 'o'
#define TICK 3
#define LEFTKEY '['
#define RIGHTKEY ']'
typedef struct {
int left, width;
} bat;
typedef struct {
int x, y, dx, dy;
int oldx, oldy;
} ball;
bat paddle;
ball b;
void draw_court()
{
int i;
cls40();
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void draw_bat(p) bat *p;
{
int i;
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
putchar(BATCHAR);
}
void move_bat(p, dir) bat *p; int dir;
{
if (dir < 0 && p->left > PLAYLEFT) {
p->left--;
curat(p->left + p->width, BATROW);
putchar(' ');
draw_bat(p);
}
if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
curat(p->left, BATROW);
putchar(' ');
p->left++;
draw_bat(p);
}
}
void move_ball(p, q) ball *p; bat *q;
{
int hit;
p->oldx = p->x;
p->oldy = p->y;
p->x += p->dx;
p->y += p->dy;
if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
p->dy = -p->dy;
if (p->y == BATROW && p->x >= q->left && p->x < q->left + q->width) {
p->dy = -1;
p->y = BATROW - 1;
hit = p->x - q->left;
if (hit == 0)
p->dx = -1;
if (hit == q->width - 1)
p->dx = 1;
}
}
void draw_ball(p) ball *p;
{
curat(p->oldx, p->oldy);
putchar(' ');
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
main()
{
char line[40];
int c;
paddle.width = 5;
paddle.left = 18;
b.x = 20;
b.y = BATROW - 1;
b.dx = 1;
b.dy = -1;
b.oldx = b.x;
b.oldy = b.y;
draw_court();
draw_bat(&paddle);
curoff();
for (;;) {
c = kbd();
if (c == LEFTKEY)
move_bat(&paddle, -1);
if (c == RIGHTKEY)
move_bat(&paddle, 1);
move_ball(&b, &paddle);
if (b.y >= BATROW)
break;
draw_ball(&b);
wait_frames(TICK);
}
curat(b.oldx, b.oldy);
putchar(' ');
curon();
curat(0, 22);
printf("Lost. Press ENTER");
gets(line);
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define PLAYLEFT 2
#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
#define BRICKCOLS 18
#define FIRSTBRICKROW 2
#define TICK 3
#define LEFTKEY '['
#define RIGHTKEY ']'
typedef struct {
int left, width;
} bat;
typedef struct {
int x, y, dx, dy;
int oldx, oldy;
} ball;
bat paddle;
ball b;
char bricks[BRICKROWS][BRICKCOLS];
int score, remaining;
void draw_court()
{
int i;
cls40();
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void define_shapes()
{
shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
}
void draw_bricks()
{
int r, c;
for (r = 0; r < BRICKROWS; r++)
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
}
remaining = BRICKROWS * BRICKCOLS;
}
void draw_score()
{
curat(0, 22);
printf("Score: %d", score);
}
void hit_brick(p) ball *p;
{
int r, c;
r = p->y - FIRSTBRICKROW;
c = (p->x - PLAYLEFT) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
if (bricks[r][c] == 0)
return;
bricks[r][c] = 0;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
p->dy = -p->dy;
score += 10;
remaining--;
draw_score();
}
void draw_bat(p) bat *p;
{
int i;
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
putchar(BATCHAR);
}
void move_bat(p, dir) bat *p; int dir;
{
if (dir < 0 && p->left > PLAYLEFT) {
p->left--;
curat(p->left + p->width, BATROW);
putchar(' ');
draw_bat(p);
}
if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
curat(p->left, BATROW);
putchar(' ');
p->left++;
draw_bat(p);
}
}
void move_ball(p, q) ball *p; bat *q;
{
int hit;
p->oldx = p->x;
p->oldy = p->y;
p->x += p->dx;
p->y += p->dy;
if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
p->dy = -p->dy;
if (p->y == BATROW && p->x >= q->left && p->x < q->left + q->width) {
p->dy = -1;
p->y = BATROW - 1;
hit = p->x - q->left;
if (hit == 0)
p->dx = -1;
if (hit == q->width - 1)
p->dx = 1;
}
}
void draw_ball(p) ball *p;
{
curat(p->oldx, p->oldy);
putchar(' ');
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
main()
{
char line[40];
int c;
paddle.width = 5;
paddle.left = 18;
b.x = 20;
b.y = BATROW - 1;
b.dx = 1;
b.dy = -1;
b.oldx = b.x;
b.oldy = b.y;
score = 0;
define_shapes();
draw_court();
draw_bricks();
draw_bat(&paddle);
draw_score();
curoff();
while (remaining > 0) {
c = kbd();
if (c == LEFTKEY)
move_bat(&paddle, -1);
if (c == RIGHTKEY)
move_bat(&paddle, 1);
move_ball(&b, &paddle);
if (b.y >= BATROW)
break;
hit_brick(&b);
draw_ball(&b);
wait_frames(TICK);
}
curat(b.oldx, b.oldy);
putchar(' ');
curon();
curat(12, 22);
if (remaining == 0)
printf("Cleared! Press ENTER");
else
printf("Lost. Press ENTER");
gets(line);
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define PLAYLEFT 2
#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
#define BRICKCOLS 18
#define FIRSTBRICKROW 2
#define TICK 3
#define LIVES 3
#define LAUNCHKEY ' '
#define LEFTKEY '['
#define RIGHTKEY ']'
typedef struct {
int left, width;
} bat;
typedef struct {
int x, y, dx, dy;
int oldx, oldy;
} ball;
bat paddle;
ball b;
char bricks[BRICKROWS][BRICKCOLS];
int score, remaining, lives;
void draw_court()
{
int i;
cls40();
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void define_shapes()
{
shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
}
void draw_bricks()
{
int r, c;
for (r = 0; r < BRICKROWS; r++)
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
}
remaining = BRICKROWS * BRICKCOLS;
}
void draw_score()
{
curat(0, 22);
printf("Score: %4d Lives: %d ", score, lives);
}
void message(s) char *s;
{
int i;
curat(0, 22);
printf("%s", s);
for (i = strlen(s); i < 32; i++)
putchar(' ');
}
void place_ball(p, q) ball *p; bat *q;
{
p->x = q->left + q->width / 2;
p->y = BATROW - 1;
p->oldx = p->x;
p->oldy = p->y;
p->dx = 1;
p->dy = -1;
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_launch()
{
message("SPACE to launch");
while (kbd() != LAUNCHKEY)
;
draw_score();
}
void hit_brick(p) ball *p;
{
int r, c;
r = p->y - FIRSTBRICKROW;
c = (p->x - PLAYLEFT) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
if (bricks[r][c] == 0)
return;
bricks[r][c] = 0;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
p->dy = -p->dy;
score += 10;
remaining--;
draw_score();
}
void draw_bat(p) bat *p;
{
int i;
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
putchar(BATCHAR);
}
void move_bat(p, dir) bat *p; int dir;
{
if (dir < 0 && p->left > PLAYLEFT) {
p->left--;
curat(p->left + p->width, BATROW);
putchar(' ');
draw_bat(p);
}
if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
curat(p->left, BATROW);
putchar(' ');
p->left++;
draw_bat(p);
}
}
void move_ball(p, q) ball *p; bat *q;
{
int hit;
p->oldx = p->x;
p->oldy = p->y;
p->x += p->dx;
p->y += p->dy;
if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
p->dy = -p->dy;
if (p->y == BATROW && p->x >= q->left && p->x < q->left + q->width) {
p->dy = -1;
p->y = BATROW - 1;
hit = p->x - q->left;
if (hit == 0)
p->dx = -1;
if (hit == q->width - 1)
p->dx = 1;
}
}
void draw_ball(p) ball *p;
{
curat(p->oldx, p->oldy);
putchar(' ');
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
main()
{
char line[40];
int c;
paddle.width = 5;
paddle.left = 18;
score = 0;
lives = LIVES;
define_shapes();
draw_court();
draw_bricks();
draw_bat(&paddle);
draw_score();
curoff();
while (lives > 0 && remaining > 0) {
place_ball(&b, &paddle);
wait_launch();
while (remaining > 0) {
c = kbd();
if (c == LEFTKEY)
move_bat(&paddle, -1);
if (c == RIGHTKEY)
move_bat(&paddle, 1);
move_ball(&b, &paddle);
if (b.y >= BATROW)
break;
hit_brick(&b);
draw_ball(&b);
wait_frames(TICK);
}
if (b.y >= BATROW) {
curat(b.oldx, b.oldy);
putchar(' ');
lives--;
draw_score();
}
}
curon();
if (remaining == 0)
message("Cleared! Press ENTER");
else
message("Game over. Press ENTER");
gets(line);
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define PLAYLEFT 2
#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
#define BRICKCOLS 18
#define FIRSTBRICKROW 2
#define STARTTICK 4
#define LIVES 3
#define LAUNCHKEY ' '
#define LEFTKEY '['
#define RIGHTKEY ']'
typedef struct {
int left, width;
} bat;
typedef struct {
int x, y, dx, dy;
int oldx, oldy;
} ball;
bat paddle;
ball b;
char bricks[BRICKROWS][BRICKCOLS];
int score, remaining, lives, level, tick;
void draw_court()
{
int i;
cls40();
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void define_shapes()
{
shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
}
void draw_bricks()
{
int r, c;
for (r = 0; r < BRICKROWS; r++)
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
}
remaining = BRICKROWS * BRICKCOLS;
}
void draw_score()
{
curat(0, 22);
printf("Score: %4d Lives: %d Level: %d ", score, lives, level);
}
void message(s) char *s;
{
int i;
curat(0, 22);
printf("%s", s);
for (i = strlen(s); i < 32; i++)
putchar(' ');
}
void place_ball(p, q) ball *p; bat *q;
{
p->x = q->left + q->width / 2;
p->y = BATROW - 1;
p->oldx = p->x;
p->oldy = p->y;
p->dx = 1;
p->dy = -1;
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_launch()
{
message("SPACE to launch");
while (kbd() != LAUNCHKEY)
;
draw_score();
}
void hit_brick(p) ball *p;
{
int r, c;
r = p->y - FIRSTBRICKROW;
c = (p->x - PLAYLEFT) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
if (bricks[r][c] == 0)
return;
bricks[r][c] = 0;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
p->dy = -p->dy;
score += 10 * level;
remaining--;
draw_score();
if (remaining == BRICKROWS * BRICKCOLS / 2 && tick > 1)
tick--;
}
void draw_bat(p) bat *p;
{
int i;
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
putchar(BATCHAR);
}
void move_bat(p, dir) bat *p; int dir;
{
if (dir < 0 && p->left > PLAYLEFT) {
p->left--;
curat(p->left + p->width, BATROW);
putchar(' ');
draw_bat(p);
}
if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
curat(p->left, BATROW);
putchar(' ');
p->left++;
draw_bat(p);
}
}
void move_ball(p, q) ball *p; bat *q;
{
int hit;
p->oldx = p->x;
p->oldy = p->y;
p->x += p->dx;
p->y += p->dy;
if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
p->dy = -p->dy;
if (p->y == BATROW && p->x >= q->left && p->x < q->left + q->width) {
p->dy = -1;
p->y = BATROW - 1;
hit = p->x - q->left;
if (hit == 0)
p->dx = -1;
if (hit == q->width - 1)
p->dx = 1;
}
}
void draw_ball(p) ball *p;
{
curat(p->oldx, p->oldy);
putchar(' ');
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
main()
{
char line[40];
int c;
paddle.width = 5;
paddle.left = 18;
score = 0;
lives = LIVES;
level = 1;
tick = STARTTICK;
define_shapes();
draw_court();
draw_bricks();
draw_bat(&paddle);
draw_score();
curoff();
while (lives > 0) {
if (remaining == 0) {
level++;
tick = STARTTICK - level + 1;
if (tick < 1)
tick = 1;
draw_bricks();
draw_score();
}
place_ball(&b, &paddle);
wait_launch();
while (remaining > 0) {
c = kbd();
if (c == LEFTKEY)
move_bat(&paddle, -1);
if (c == RIGHTKEY)
move_bat(&paddle, 1);
move_ball(&b, &paddle);
if (b.y >= BATROW)
break;
hit_brick(&b);
draw_ball(&b);
wait_frames(tick);
}
if (b.y >= BATROW) {
curat(b.oldx, b.oldy);
putchar(' ');
lives--;
draw_score();
}
}
curon();
message("Game over. Press ENTER");
gets(line);
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
#include STDIO.H
#define LEFTWALL 0
#define RIGHTWALL 39
#define TOPWALL 0
#define BATROW 21
#define PLAYLEFT 2
#define PLAYRIGHT 37
#define WALL 202
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
#define BRICKCOLS 18
#define FIRSTBRICKROW 2
#define STARTTICK 4
#define LIVES 3
#define LAUNCHKEY ' '
#define WALLCOL 0x51
#define BATCOL 0xF1
#define BALLCOL 0xF1
#define TEXTCOL 0xE1
#define TITLECOL 0xB1
#define BACKDROP 1
#define DEFAULTBACKDROP 4
#define LEFTKEY '['
#define RIGHTKEY ']'
typedef struct {
int left, width;
} bat;
typedef struct {
int x, y, dx, dy;
int oldx, oldy;
} ball;
bat paddle;
ball b;
char bricks[BRICKROWS][BRICKCOLS];
int score, remaining, lives, level, tick, oldcol;
int brickcol[BRICKROWS] = { 0x91, 0xB1, 0x31, 0x71 };
void draw_court()
{
int i;
cls40();
tcol(WALLCOL);
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
putchar(WALL);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
putchar(WALL);
curat(RIGHTWALL, i);
putchar(WALL);
}
}
void define_shapes()
{
shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
shapedef(WALL, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc);
}
void draw_bricks()
{
int r, c;
for (r = 0; r < BRICKROWS; r++)
for (c = 0; c < BRICKCOLS; c++) {
tcol(brickcol[r]);
bricks[r][c] = 1;
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
}
remaining = BRICKROWS * BRICKCOLS;
}
void draw_score()
{
tcol(TEXTCOL);
curat(0, 22);
printf("Score: %4d Lives: %d Level: %d ", score, lives, level);
}
void message(s) char *s;
{
int i;
tcol(TEXTCOL);
curat(0, 22);
printf("%s", s);
for (i = strlen(s); i < 32; i++)
putchar(' ');
}
void place_ball(p, q) ball *p; bat *q;
{
p->x = q->left + q->width / 2;
p->y = BATROW - 1;
p->oldx = p->x;
p->oldy = p->y;
p->dx = 1;
p->dy = -1;
tcol(BALLCOL);
curat(p->x, p->y);
putchar(BALLCHAR);
}
void title()
{
cls40();
tcol(TITLECOL);
curat(12, 6);
printf("B R E A K O U T");
tcol(TEXTCOL);
curat(8, 10);
printf("[ and ] move the bat");
curat(8, 12);
printf("SPACE launches the ball");
curat(8, 14);
printf("%d lives; clear the bricks", LIVES);
curat(8, 17);
printf("Press any key to play");
curat(0, 22);
rawin();
}
void wait_launch()
{
message("SPACE to launch");
while (kbd() != LAUNCHKEY)
;
draw_score();
}
void hit_brick(p) ball *p;
{
int r, c;
r = p->y - FIRSTBRICKROW;
c = (p->x - PLAYLEFT) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
if (bricks[r][c] == 0)
return;
bricks[r][c] = 0;
beep();
tcol(brickcol[r]);
curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
p->dy = -p->dy;
score += 10 * level;
remaining--;
draw_score();
if (remaining == BRICKROWS * BRICKCOLS / 2 && tick > 1)
tick--;
}
void draw_bat(p) bat *p;
{
int i;
tcol(BATCOL);
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
putchar(BATCHAR);
}
void move_bat(p, dir) bat *p; int dir;
{
if (dir < 0 && p->left > PLAYLEFT) {
p->left--;
curat(p->left + p->width, BATROW);
putchar(' ');
draw_bat(p);
}
if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
curat(p->left, BATROW);
putchar(' ');
p->left++;
draw_bat(p);
}
}
void move_ball(p, q) ball *p; bat *q;
{
int hit;
p->oldx = p->x;
p->oldy = p->y;
p->x += p->dx;
p->y += p->dy;
if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
p->dy = -p->dy;
if (p->y == BATROW && p->x >= q->left && p->x < q->left + q->width) {
p->dy = -1;
p->y = BATROW - 1;
hit = p->x - q->left;
if (hit == 0)
p->dx = -1;
if (hit == q->width - 1)
p->dx = 1;
}
}
row_colour(y) int y;
{
if (y >= FIRSTBRICKROW && y < FIRSTBRICKROW + BRICKROWS)
return brickcol[y - FIRSTBRICKROW];
return BALLCOL;
}
void draw_ball(p) ball *p;
{
tcol(row_colour(p->oldy));
curat(p->oldx, p->oldy);
putchar(' ');
tcol(row_colour(p->y));
curat(p->x, p->y);
putchar(BALLCHAR);
}
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
void play()
{
int c;
paddle.width = 5;
paddle.left = 18;
score = 0;
lives = LIVES;
level = 1;
tick = STARTTICK;
draw_court();
draw_bricks();
draw_bat(&paddle);
draw_score();
curoff();
while (lives > 0) {
if (remaining == 0) {
level++;
tick = STARTTICK - level + 1;
if (tick < 1)
tick = 1;
draw_bricks();
draw_score();
}
place_ball(&b, &paddle);
wait_launch();
while (remaining > 0) {
c = kbd();
if (c == LEFTKEY)
move_bat(&paddle, -1);
if (c == RIGHTKEY)
move_bat(&paddle, 1);
move_ball(&b, &paddle);
if (b.y >= BATROW)
break;
hit_brick(&b);
draw_ball(&b);
wait_frames(tick);
}
if (b.y >= BATROW) {
curat(b.oldx, b.oldy);
putchar(' ');
lives--;
beep();
draw_score();
}
}
curon();
}
main()
{
char line[40];
int c;
define_shapes();
oldcol = peek(0xfb38);
bcol(BACKDROP);
for (;;) {
title();
play();
message("Game over. Again? (Y/N)");
c = rawin();
if (c != 'Y' && c != 'y')
break;
}
tcol(oldcol);
bcol(DEFAULTBACKDROP);
cls40();
printf("Press ENTER to finish\n");
gets(line);
}
#include ?EIN.LIB?
#include ?STDIO.LIB?