
One solution to each exercise, compiled and run as every listing in the course was. Yours need not match; it needs to work. Where a solution's output depends on what was typed, the note says what was typed. Every program begins with #include STDIO.H and ends with #include ?STDIO.LIB? (after ?EIN.LIB? or ?CPM.LIB? where those are used), as in the sections.
4.1
#include STDIO.H
main()
{
printf("Gavin\n");
printf("ZX81\n");
printf("1982\n");
}
#include ?STDIO.LIB?
Gavin
ZX81
1982
4.2
#include STDIO.H
main()
{
printf("Gavin, ZX81, 1982\n");
}
#include ?STDIO.LIB?
Gavin, ZX81, 1982
7.1
No program: (a) printf("x") with no ; is reported at once, missing ';' at the line after; (b) printf("x" is reported at once, missing ')'; (c) prinf is reported at the end, ERROR - 27 - undefined symbol prinf; (d) two mains are reported at once, ERROR 21 ... duplicate declaration - storage class mismatch at the second.
7.2
#include STDIO.H
main()
{
int a
a = 1
printf("%d\n", a);
}
#include ?STDIO.LIB?
The compiler reported only the first: ERROR 48 AT LINE 6 IN FILE E72.C / bad declaration. Fix it (E, edit, GRPH-K X) and the compile restarts and finds the second.
8.1
#include STDIO.H
main()
{
printf("%-12s%6d\n", "Tea", 120);
printf("%-12s%6d\n", "Biscuits", 85);
printf("%-12s%6d\n", "Newspaper", 1250);
}
#include ?STDIO.LIB?
Tea 120
Biscuits 85
Newspaper 1250
8.2
#include STDIO.H
main()
{
printf("%4x%4o%4d\n", 1, 1, 1);
printf("%4x%4o%4d\n", 2, 2, 2);
printf("%4x%4o%4d\n", 3, 3, 3);
printf("%4x%4o%4d\n", 4, 4, 4);
printf("%4x%4o%4d\n", 5, 5, 5);
}
#include ?STDIO.LIB?
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
8.3
#include STDIO.H
main()
{
printf("%d%% of %dK is %dK\n", 50, 64, 32);
}
#include ?STDIO.LIB?
50% of 64K is 32K
9.1
#include STDIO.H
main()
{
printf("%d minutes in a day\n", 24 * 60);
printf("%d seconds in a day\n", 24 * 60 * 60);
}
#include ?STDIO.LIB?
86400 does not fit an int: 86400 - 65536 = 20864.
1440 minutes in a day
20864 seconds in a day
9.2
#include STDIO.H
main()
{
printf("%d\n", 65535);
printf("%u\n", -1);
}
#include ?STDIO.LIB?
-1
65535
9.3
#include STDIO.H
main()
{
printf("%d\n", 0100);
}
#include ?STDIO.LIB?
0100 is octal: 64.
64
10.1
#include STDIO.H
main()
{
int year, born, age;
year = 2026;
born = 1970;
age = year - born;
printf("born %d, age %d\n", born, age);
}
#include ?STDIO.LIB?
born 1970, age 56
10.2
#include STDIO.H
main()
{
int a, b, keep;
a = 3;
b = 8;
printf("before: %d %d\n", a, b);
keep = a;
a = b;
b = keep;
printf("after: %d %d\n", a, b);
}
#include ?STDIO.LIB?
before: 3 8
after: 8 3
10.3
#include STDIO.H
int lives = 3;
main()
{
printf("%d\n", lives);
lives = lives - 1;
printf("%d\n", lives);
}
#include ?STDIO.LIB?
3
2
11.1
#include STDIO.H
main()
{
int temp;
temp = 14;
if (temp < 0)
printf("freezing\n");
else if (temp < 10)
printf("cold\n");
else if (temp < 20)
printf("mild\n");
else
printf("hot\n");
}
#include ?STDIO.LIB?
mild
11.2
#include STDIO.H
main()
{
int a, b, c, big;
a = 4;
b = 9;
c = 6;
big = a;
if (b > big)
big = b;
if (c > big)
big = c;
printf("%d\n", big);
big = a > b ? (a > c ? a : c) : (b > c ? b : c);
printf("%d\n", big);
}
#include ?STDIO.LIB?
9
9
11.3
#include STDIO.H
main()
{
int year;
year = 1984;
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
printf("%d is a leap year\n", year);
else
printf("%d is not\n", year);
}
#include ?STDIO.LIB?
1984 is a leap year
12.1
#include STDIO.H
main()
{
int i, j;
for (i = 1; i <= 4; i++) {
for (j = 1; j <= 4; j++)
printf("%3d", i * j);
printf("\n");
}
}
#include ?STDIO.LIB?
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
12.2
#include STDIO.H
main()
{
int p;
p = 1;
while (p > 0) {
printf("%d ", p);
p = p * 2;
}
printf("\n");
}
#include ?STDIO.LIB?
16384 doubled is 32768, which an int holds as -32768 (S9), and you would expect p > 0 to stop the loop there. On this compiler it did not: -32768 was printed as well, and the loop stopped only when the next doubling gave 0. A test that does not lean on the sign - while (p <= 16384) - stops at the last true power of two.
1 2 4 8 16 32 64 128 256 512 1024 2048 4
096 8192 16384 -32768
12.3
#include STDIO.H
main()
{
int i, count;
count = 0;
for (i = 1; i <= 1000; i++)
if (i % 7 == 0 && i % 5 != 0)
count++;
printf("%d\n", count);
}
#include ?STDIO.LIB?
114
13.1
#include STDIO.H
cube(n) int n;
{
return n * n * n;
}
main()
{
int i;
for (i = 1; i <= 5; i++)
printf("%d cubed is %d\n", i, cube(i));
for (i = 30; i <= 33; i++)
printf("%d cubed is %d\n", i, cube(i));
}
#include ?STDIO.LIB?
32 cubed is 32768, which does not fit: it prints -32768, and 33 cubed is wrong too. 31 is the last correct cube.
1 cubed is 1
2 cubed is 8
3 cubed is 27
4 cubed is 64
5 cubed is 125
30 cubed is 27000
31 cubed is 29791
32 cubed is -32768
33 cubed is -29599
13.2
#include STDIO.H
smaller(a, b) int a, b;
{
if (a < b)
return a;
return b;
}
smallest(a, b, c) int a, b, c;
{
return smaller(smaller(a, b), c);
}
main()
{
printf("%d %d %d\n", smallest(1, 2, 3), smallest(2, 3, 1), smallest(3, 1, 2));
printf("%d %d %d\n", smallest(1, 3, 2), smallest(2, 1, 3), smallest(3, 2, 1));
}
#include ?STDIO.LIB?
1 1 1
1 1 1
13.3
#include STDIO.H
power(base, n) int base, n;
{
if (n == 0)
return 1;
return base * power(base, n - 1);
}
main()
{
int i;
for (i = 1; i <= 11; i++)
printf("3 to the %d is %d\n", i, power(3, i));
}
#include ?STDIO.LIB?
3 to the 10th is 59049, which does not fit an int: it comes out as -6487, and the 11th is wrong too.
3 to the 1 is 3
3 to the 2 is 9
3 to the 3 is 27
3 to the 4 is 81
3 to the 5 is 243
3 to the 6 is 729
3 to the 7 is 2187
3 to the 8 is 6561
3 to the 9 is 19683
3 to the 10 is -6487
3 to the 11 is -19461
14.1
#include STDIO.H
main()
{
char line[40];
int a, b;
printf("First number: ");
gets(line);
a = atoi(line);
printf("Second number: ");
gets(line);
b = atoi(line);
printf("sum %d, difference %d, product %d\n", a + b, a - b, a * b);
}
#include ?STDIO.LIB?
Typed 12 and 5.
First number: 12
Second number: 5
sum 17, difference 7, product 60
14.2
#include STDIO.H
main()
{
char line[40];
int c, n;
printf("Type a line: ");
n = 0;
while ((c = getchar()) != '\n')
line[n++] = c;
while (n > 0)
printf("%c", line[--n]);
printf("\n");
}
#include ?STDIO.LIB?
Typed Einstein (with CAPS LOCK on).
Type a line: EINSTEIN
NIETSNIE
14.3
#include STDIO.H
main()
{
int c;
printf("Press any key\n");
c = rawin();
printf("%d, or %x in hex\n", c, c);
}
#include ?STDIO.LIB?
Pressed e with CAPS LOCK on: 69, E.
Press any key
69, or 45 in hex
15.1
#include STDIO.H
main()
{
int sq[10], i;
for (i = 0; i < 10; i++)
sq[i] = (i + 1) * (i + 1);
for (i = 9; i >= 0; i--)
printf("%d ", sq[i]);
printf("\n");
}
#include ?STDIO.LIB?
100 81 64 49 36 25 16 9 4 1
15.2
#include STDIO.H
int marks[6] = { 40, 72, 15, 99, 63, 8 };
biggest(a, n) int a[], n;
{
int i, best;
best = a[0];
for (i = 1; i < n; i++)
if (a[i] > best)
best = a[i];
return best;
}
main()
{
printf("%d\n", biggest(marks, 6));
printf("%d\n", biggest(marks, 3));
}
#include ?STDIO.LIB?
99
72
15.3
#include STDIO.H
main()
{
char row[41];
int i;
for (i = 0; i < 20; i++)
row[i] = '#';
row[20] = 0;
printf("%s\n", row);
row[10] = ' ';
printf("%s\n", row);
}
#include ?STDIO.LIB?
####################
########## #########
16.1
#include STDIO.H
both(a, b) int *a, *b;
{
int sum;
sum = *a + *b;
*a = sum;
*b = sum;
}
main()
{
int x, y;
x = 3;
y = 4;
both(&x, &y);
printf("%d %d\n", x, y);
}
#include ?STDIO.LIB?
7 7
16.2
#include STDIO.H
count(s) char *s;
{
int n;
n = 0;
while (*s++)
n++;
return n;
}
main()
{
printf("%d %d\n", count("Einstein"), count(""));
}
#include ?STDIO.LIB?
8 0
16.3
#include STDIO.H
typedef char *char_ptr;
main()
{
char *p;
int i;
p = cast(char_ptr) 0x7000;
for (i = 0; i < 16; i++)
p[i] = i;
for (i = 0; i < 16; i++)
printf("%d ", peek(0x7000 + i));
printf("\n");
}
#include ?STDIO.LIB?
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
17.1
#include STDIO.H
count(s, c) char *s, c;
{
int n;
n = 0;
while (*s) {
if (*s == c)
n++;
s++;
}
return n;
}
main()
{
printf("%d %d %d\n", count("Einstein", 'n'), count("Einstein", 'z'), count("", 'a'));
}
#include ?STDIO.LIB?
2 0 0
17.2
#include STDIO.H
main()
{
char line[40];
int i;
printf("Type a line: ");
gets(line);
for (i = 0; line[i]; i++)
if (line[i] == ' ')
line[i] = '_';
printf("%s\n", line);
}
#include ?STDIO.LIB?
Typed the tatung einstein (CAPS LOCK on).
Type a line: THE TATUNG EINSTEIN
THE_TATUNG_EINSTEIN
17.3
#include STDIO.H
ends(s, c) char *s, c;
{
int n;
n = strlen(s);
if (n == 0)
return 0;
return s[n - 1] == c;
}
main()
{
printf("%d %d %d\n", ends("Einstein", 'n'), ends("Einstein", 'E'), ends("", 'n'));
}
#include ?STDIO.LIB?
1 0 0
18.1
#include STDIO.H
typedef struct {
int x, y;
} point;
taxi(a, b) point *a, *b;
{
return abs(a->x - b->x) + abs(a->y - b->y);
}
main()
{
point p, q;
p.x = 1;
p.y = 1;
q.x = 4;
q.y = 6;
printf("%d %d\n", taxi(&p, &q), taxi(&q, &p));
}
#include ?STDIO.LIB?
8 8
18.2
#include STDIO.H
typedef struct {
int x, y, dx, dy;
} ball;
ball balls[3];
main()
{
int i, t;
for (i = 0; i < 3; i++) {
balls[i].x = 10 * i;
balls[i].y = 0;
balls[i].dx = 1;
balls[i].dy = i + 1;
}
for (t = 0; t < 3; t++)
for (i = 0; i < 3; i++) {
balls[i].x += balls[i].dx;
balls[i].y += balls[i].dy;
}
for (i = 0; i < 3; i++)
printf("ball %d at (%d,%d)\n", i, balls[i].x, balls[i].y);
}
#include ?STDIO.LIB?
ball 0 at (3,3)
ball 1 at (13,6)
ball 2 at (23,9)
18.3
#include STDIO.H
typedef struct {
char name[10];
int score;
} player;
main()
{
player best;
strcpy(best.name, "Gavin");
best.score = 1500;
printf("%s has %d\n", best.name, best.score);
printf("%d bytes\n", sizeof(player));
}
#include ?STDIO.LIB?
Gavin has 1500
12 bytes
19.1
#include STDIO.H
#define ROWS 3
#define COLS 8
main()
{
char grid[ROWS][COLS + 1];
int r, c;
for (r = 0; r < ROWS; r++) {
for (c = 0; c < COLS; c++)
grid[r][c] = '.';
grid[r][COLS] = 0;
}
for (r = 0; r < ROWS; r++)
printf("%s\n", grid[r]);
}
#include ?STDIO.LIB?
........
........
........
19.2
#include STDIO.H
square(x) int x;
{
return x * x;
}
main()
{
printf("%d\n", square(12));
}
#include ?STDIO.LIB?
#define SQUARE(x) x * x is refused: RESTRICTION: macros may not have parameters (S19). The function is the answer: 144.
19.3
#include STDIO.H
#include MY.H
main()
{
printf("%s\n", GREETING);
}
#include ?STDIO.LIB?
With MY.H on the disc containing #define GREETING "Hello, Einstein".
20.1
#include STDIO.H
main()
{
FILE *f;
char line[40];
int i;
f = fopen("NAMES.TXT", "w");
for (i = 1; i <= 3; i++) {
printf("Name %d: ", i);
gets(line);
fputs(line, f);
fputs("\n", f);
}
fclose(f);
f = fopen("NAMES.TXT", "r");
i = 1;
while (fgets(line, 40, f))
printf("%d. %s", i++, line);
fclose(f);
}
#include ?STDIO.LIB?
Typed Ada, Grace, Alan (CAPS LOCK on).
Name 1: ADA
Name 2: GRACE
Name 3: ALAN
1. ADA
2. GRACE
3. ALAN
20.2
#include STDIO.H
main()
{
FILE *f;
char line[40];
int score;
f = fopen("SCORE.TXT", "r");
if (f == 0) {
printf("no score file\n");
return;
}
fgets(line, 40, f);
fclose(f);
score = atoi(line) + 10;
f = fopen("SCORE.TXT", "w");
fprintf(f, "%d\n", score);
fclose(f);
printf("score is now %d\n", score);
}
#include ?STDIO.LIB?
and E202A.C:
#include STDIO.H
main()
{
FILE *f;
f = fopen("SCORE.TXT", "w");
fprintf(f, "%d\n", 100);
fclose(f);
printf("written\n");
}
#include ?STDIO.LIB?
E202A.C writes the file first (below). Three runs of E202B printed score is now 110, 120, 130.
score is now 110
20.3
#include STDIO.H
main()
{
FILE *f;
int c, lines;
f = fopen("STDIO.H", "r");
lines = 0;
while ((c = getc(f)) != EOF)
if (c == 10)
lines++;
fclose(f);
printf("%d lines\n", lines);
}
#include ?STDIO.LIB?
134 lines
21.1
#include STDIO.H
typedef int *int_ptr;
main()
{
int *p, i, sum;
p = cast(int_ptr) malloc(10 * sizeof(int));
for (i = 0; i < 10; i++)
p[i] = i + 1;
sum = 0;
for (i = 0; i < 10; i++)
sum += p[i];
printf("%d\n", sum);
free(p);
}
#include ?STDIO.LIB?
55
21.2
#include STDIO.H
main()
{
int n;
n = 0;
while (malloc(1000) != 0)
n++;
printf("%d blocks of 1000\n", n);
}
#include ?STDIO.LIB?
heap full is printed by malloc itself on the call that fails.
heap full
52 blocks of 1000
21.3
#include STDIO.H
deeper(n) int n;
{
char pad[100];
if (n % 50 == 0)
printf("%d ", n);
deeper(n + 1);
}
main()
{
deeper(1);
}
#include ?STDIO.LIB?
It printed 50 100 150 ... 500 and then stack overflow, and the prompt came back.
22.1
#include STDIO.H
main()
{
int c;
char line[40];
printf("Arrows; Q to stop\n");
for (;;) {
while ((c = kbd()) == 0)
;
if (c == '[')
printf("left\n");
if (c == ']')
printf("right\n");
if (c == 'Q')
break;
while (kbd() != 0)
;
}
printf("Press ENTER to finish\n");
gets(line);
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
LEFT, RIGHT, then Q.
22.2
#include STDIO.H
main()
{
int n;
char line[40];
printf("Hold SPACE\n");
while (kbd() != ' ')
;
n = 0;
while (kbd() == ' ')
n++;
printf("%d times round\n", n);
printf("Press ENTER to finish\n");
gets(line);
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
SPACE held for about a second: 227 passes.
22.3
#include STDIO.H
waitkey()
{
int c;
while ((c = kbd()) == 0)
;
while (kbd() != 0)
;
return c;
}
main()
{
char line[40];
cls40();
curat(10, 5);
printf("X");
curat(0, 22);
waitkey();
curat(0, 15);
printf("again");
waitkey();
cls40();
printf("Press ENTER to finish\n");
gets(line);
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
The screen appeared as in S24 and each key moved it on; the prompt was clean, but the listing keeps the gets because kbd() was used.
23.1
#include STDIO.H
void clear()
{
rawout(14);
}
void at(h, v)
{
poke(0xfb4a, h);
poke(0xfb4b, v);
}
main()
{
clear();
at(10, 5);
printf("here");
at(0, 22);
rawin();
clear();
}
#include ?STDIO.LIB?
It compiles with ?STDIO.LIB? alone: rawout is built in and poke is in the standard library. here appears at column 10, row 5.
23.2
#include STDIO.H
void home()
{
poke(0xfb4a, 0);
poke(0xfb4b, 0);
}
main()
{
cls40();
curat(5, 5);
printf("middle");
home();
printf("top");
curat(0, 22);
rawin();
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
top at the top left over middle at (5,5).
23.3
#include STDIO.H
dpeek(addr) unsigned addr;
{
return peek(addr) + 256 * peek(addr + 1);
}
main()
{
doke(0x7000, 1234);
printf("%d %d %d\n", peek(0x7000), peek(0x7001), dpeek(0x7000));
doke(0x7000, -1);
printf("%u\n", dpeek(0x7000));
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
doke writes the low byte first: 210 then 4 for 1234; dpeek reads them back; -1 reads back as 65535.
210 4 1234
65535
24.1
#include STDIO.H
main()
{
int i;
cls40();
for (i = 0; i < 40; i++) {
curat(i, 0);
putchar('#');
curat(i, 20);
putchar('#');
}
for (i = 1; i < 20; i++) {
curat(0, i);
putchar('#');
curat(39, i);
putchar('#');
}
curat(0, 22);
rawin();
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
A box of # round the top twenty-one rows.
24.2
#include STDIO.H
main()
{
int i;
cls40();
for (i = 0; i < 10; i++) {
curat(38, i);
printf("%2d", i);
}
curat(0, 22);
rawin();
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
0 to 9 in the last two columns of rows 0-9.
24.3
#include STDIO.H
main()
{
int score, i, j;
cls40();
curat(31, 0);
printf("Score: 0");
for (score = 1; score <= 20; score++) {
for (j = 0; j < 3000; j++)
;
curat(38, 0);
printf("%d", score);
}
curat(0, 22);
rawin();
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
Score: 0 at the top right, counting up to 20 in place.
25.1
#include STDIO.H
main()
{
int i;
cls40();
shapedef(201, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
curat(10, 5);
for (i = 0; i < 20; i++)
putchar(201);
curat(0, 22);
rawin();
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
Twenty bricks in a row on row 5, each with a one-pixel gap at the right and the bottom.
25.2
#include STDIO.H
main()
{
int c;
cls40();
for (c = 1; c <= 15; c++) {
curat(0, 10);
printf("colour %d ", c);
bcol(c);
rawin();
}
bcol(4);
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
The backdrop changes at each key through the fifteen colours and ends dark blue.
25.3
#include STDIO.H
void spriteshape(s, n)
{
s <<= 2;
s += 0x3b02;
vpoke(s, n);
}
main()
{
int x;
cls40();
mag(0);
spriteshape(0, 'O');
spritecol(0, 0x0F);
for (x = 0; x <= 240; x += 4) {
spritepos(0, x, 90);
while ((inp(9) & 0x80) == 0)
;
}
curat(0, 22);
printf("done");
rawin();
cls40();
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
The sprite crosses the screen in about a second and done appears.
26.1
#include STDIO.H
main()
{
int i;
cls40();
curat(0, 5);
printf("put-start\n");
for (i = 0; i < 1000; i++) {
putchar('*');
if (i % 40 == 39)
putchar(13);
}
printf("\nput-end\n");
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
About 3.7 seconds for the thousand, printed on one row and overwritten - the same four milliseconds a character as with curat.
26.2
#include STDIO.H
void wait_frames(n) int n;
{
while (n-- > 0)
while ((inp(9) & 0x80) == 0)
;
}
main()
{
int i;
printf("count-start\n");
for (i = 1; i <= 10; i++) {
printf("%d ", i);
wait_frames(50);
}
printf("\ncount-end\n");
}
#include ?EIN.LIB?
#include ?STDIO.LIB?
1 to 10 appear one a second, then count-end.
26.3
TICK.C is Code 1200 149A (666 bytes), KEYS.C 1465 (613), SCREEN.C 1429 (553). The gets in KEYS.C and the frame loop in TICK.C cost most: gets brings its library function in.
27.1
Starting from BREAK1.C, the changes (- lines out, + lines in, @@ marks where):
@@ -7,4 +7,5 @@
#define WALL '#'
#define BATCHAR '='
+#define BOTTOMROW 22
typedef struct {
@@ -30,4 +31,14 @@
}
+void draw_message(s) char *s;
+{
+ int i;
+ curat(0, BOTTOMROW);
+ for (i = 0; i < 40; i++)
+ putchar(' ');
+ curat(0, BOTTOMROW);
+ printf("%s", s);
+}
+
void draw_bat(b) bat *b;
{
@@ -45,11 +56,11 @@
draw_court();
draw_bat(&paddle);
- curat(0, 22);
+ draw_message("Any key");
curoff();
rawin();
curon();
+ draw_message("Press ENTER to finish");
+ gets(line);
cls40();
- printf("Press ENTER to finish\n");
- gets(line);
}
Any key on the bottom row, then Press ENTER to finish in its place.
27.2
Starting from BREAK1.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,5 +5,6 @@
#define TOPWALL 0
#define BATROW 21
-#define WALL '#'
+#define TOPCHAR '-'
+#define SIDECHAR '|'
#define BATCHAR '='
@@ -20,11 +21,11 @@
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
- putchar(WALL);
+ putchar(TOPCHAR);
}
for (i = TOPWALL + 1; i <= BATROW; i++) {
curat(LEFTWALL, i);
- putchar(WALL);
+ putchar(SIDECHAR);
curat(RIGHTWALL, i);
- putchar(WALL);
+ putchar(SIDECHAR);
}
}
- along the top, | down the sides - which the Einstein draws as a double bar.
27.3
Starting from BREAK1.C, the changes (- lines out, + lines in, @@ marks where):
@@ -18,4 +18,5 @@
int i;
cls40();
+ tcol(0x51);
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
@@ -33,4 +34,5 @@
{
int i;
+ tcol(0xB1);
curat(b->left, BATROW);
for (i = 0; i < b->width; i++)
@@ -45,4 +47,5 @@
draw_court();
draw_bat(&paddle);
+ tcol(0xF4);
curat(0, 22);
curoff();
Cyan walls on black, yellow bat, white message.
28.1
Starting from BREAK2.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -54,7 +52,7 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
- if (p->y <= TOPWALL + 1)
+ if (p->y <= TOPWALL + 1 || p->y >= BATROW)
p->dy = -p->dy;
}
@@ -89,5 +87,5 @@
draw_bat(&paddle);
curoff();
- while (b.y < BATROW) {
+ while (kbd() != 'Q') {
move_ball(&b);
draw_ball(&b);
@@ -96,5 +94,5 @@
curon();
curat(0, 22);
- printf("Lost. Press ENTER");
+ printf("Stopped. Press ENTER");
gets(line);
cls40();
The ball bounces off row 21 as off the top and never stops; Q ends it with Stopped. Press ENTER.
28.2
Starting from BREAK2.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -54,8 +52,11 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
- if (p->y <= TOPWALL + 1)
+ if (p->y <= TOPWALL + 1) {
p->dy = -p->dy;
+ if (p->dx == 0)
+ p->dx = 1;
+ }
}
@@ -82,5 +83,5 @@
b.x = 20;
b.y = 12;
- b.dx = 1;
+ b.dx = 0;
b.dy = -1;
b.oldx = b.x;
Straight up the middle, off the top, and then diagonally: the first bounce gives it dx = 1.
28.3
Starting from BREAK2.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -23,4 +21,5 @@
bat paddle;
ball b;
+int ticks;
void draw_court()
@@ -54,5 +53,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -93,8 +92,9 @@
draw_ball(&b);
wait_frames(TICK);
+ ticks++;
}
curon();
curat(0, 22);
- printf("Lost. Press ENTER");
+ printf("Lost after %d ticks. Press ENTER", ticks);
gets(line);
cls40();
Lost after 31 ticks. Press ENTER for the ball starting at (20, 12).
29.1
Starting from BREAK3.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -52,5 +50,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -58,5 +56,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -73,5 +71,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -83,4 +81,8 @@
if (hit == 0)
p->dx = -1;
+ if (hit == 1)
+ p->dx = -1;
+ if (hit == q->width - 2)
+ p->dx = 1;
if (hit == q->width - 1)
p->dx = 1;
@@ -107,5 +109,5 @@
char line[40];
int c;
- paddle.width = 5;
+ paddle.width = 7;
paddle.left = 18;
b.x = 20;
@@ -118,5 +120,5 @@
draw_bat(&paddle);
curoff();
- for (;;) {
+ while (b.y <= BATROW) {
c = kbd();
if (c == LEFTKEY)
@@ -125,11 +127,7 @@
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);
A seven-wide bat; the two end columns send the ball outward, the next two the same, the middle three leave dx alone.
29.2
Starting from BREAK3.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -13,4 +11,5 @@
#define LEFTKEY '['
#define RIGHTKEY ']'
+#define BATSPEED 2
typedef struct {
@@ -52,14 +51,17 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
- p->left--;
+ int i;
+ if (dir < 0 && p->left - BATSPEED > LEFTWALL) {
+ p->left -= BATSPEED;
curat(p->left + p->width, BATROW);
- putchar(' ');
+ for (i = 0; i < BATSPEED; i++)
+ putchar(' ');
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width + BATSPEED <= RIGHTWALL) {
curat(p->left, BATROW);
- putchar(' ');
- p->left++;
+ for (i = 0; i < BATSPEED; i++)
+ putchar(' ');
+ p->left += BATSPEED;
draw_bat(p);
}
@@ -73,5 +75,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -118,5 +120,5 @@
draw_bat(&paddle);
curoff();
- for (;;) {
+ while (b.y <= BATROW) {
c = kbd();
if (c == LEFTKEY)
@@ -125,11 +127,7 @@
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);
With BATSPEED 2 the bat moves two columns a tick and rubs two out; no smear.
29.3
Starting from BREAK3.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -52,5 +50,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -58,5 +56,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -73,5 +71,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -118,5 +116,5 @@
draw_bat(&paddle);
curoff();
- for (;;) {
+ while (b.y <= BATROW) {
c = kbd();
if (c == LEFTKEY)
@@ -124,15 +122,16 @@
if (c == RIGHTKEY)
move_bat(&paddle, 1);
+ if (c == 'Q')
+ break;
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");
+ if (b.y >= BATROW)
+ printf("Lost. Press ENTER");
+ else
+ printf("Quit. Press ENTER");
gets(line);
cls40();
Q gives Quit. Press ENTER.
30.1
Starting from BREAK4.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define TICK 3
@@ -50,6 +48,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -60,5 +58,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -77,5 +75,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -83,9 +81,9 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
p->dy = -p->dy;
- score += 10;
+ score += 10 * (BRICKROWS - r);
remaining--;
draw_score();
@@ -102,5 +100,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -108,5 +106,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -123,5 +121,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
The bottom row scores 10, the top 40.
30.2
Starting from BREAK4.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,12 +5,11 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
+#define HARDCHAR 202
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define TICK 3
@@ -50,6 +49,7 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
+ shapedef(HARDCHAR, 0xfe, 0xaa, 0xd6, 0xaa, 0xd6, 0xaa, 0xfe, 0x00);
}
@@ -59,8 +59,13 @@
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);
+ bricks[r][c] = (r == 0) ? 2 : 1;
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
+ if (r == 0) {
+ putchar(HARDCHAR);
+ putchar(HARDCHAR);
+ } else {
+ putchar(BRICKCHAR);
+ putchar(BRICKCHAR);
+ }
}
remaining = BRICKROWS * BRICKCOLS;
@@ -77,11 +82,17 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 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);
+ bricks[r][c]--;
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
+ if (bricks[r][c] == 1) {
+ putchar(BRICKCHAR);
+ putchar(BRICKCHAR);
+ p->dy = -p->dy;
+ return;
+ }
putchar(' ');
putchar(' ');
@@ -102,5 +113,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -108,5 +119,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -123,5 +134,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
The top row is drawn with character 202 and takes two hits, turning into an ordinary brick on the first.
30.3
Starting from BREAK4.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define TICK 3
@@ -50,6 +48,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -60,5 +58,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -70,5 +68,5 @@
{
curat(0, 22);
- printf("Score: %d", score);
+ printf("Score: %d Bricks: %d ", score, remaining);
}
@@ -77,5 +75,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -83,5 +81,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -102,5 +100,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -108,5 +106,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -123,5 +121,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
Score: 0 Bricks: 76, counting down.
31.1
Starting from BREAK5.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define TICK 3
@@ -52,6 +50,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -62,5 +60,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -71,6 +69,11 @@
void draw_score()
{
+ int i;
curat(0, 22);
- printf("Score: %4d Lives: %d ", score, lives);
+ printf("Score: %4d Lives: ", score);
+ for (i = 0; i < lives; i++)
+ putchar(BALLCHAR);
+ for (i = lives; i < 12; i++)
+ putchar(' ');
}
@@ -108,5 +111,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -114,5 +117,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -133,5 +136,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -139,5 +142,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -154,5 +157,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
Lives: followed by three ball characters, then two, then one.
31.2
Starting from BREAK5.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define TICK 3
@@ -52,6 +50,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -62,5 +60,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -96,9 +94,23 @@
}
-void wait_launch()
-{
+void wait_launch(p, q) ball *p; bat *q;
+{
+ int c;
message("SPACE to launch");
- while (kbd() != LAUNCHKEY)
- ;
+ for (;;) {
+ c = kbd();
+ if (c == LAUNCHKEY)
+ break;
+ if (c == LEFTKEY || c == RIGHTKEY) {
+ curat(p->x, p->y);
+ putchar(' ');
+ move_bat(q, c == LEFTKEY ? -1 : 1);
+ p->x = q->left + q->width / 2;
+ p->oldx = p->x;
+ curat(p->x, p->y);
+ putchar(BALLCHAR);
+ wait_frames(TICK);
+ }
+ }
draw_score();
}
@@ -108,5 +120,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -114,5 +126,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -133,5 +145,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -139,5 +151,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -154,5 +166,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -200,5 +212,5 @@
while (lives > 0 && remaining > 0) {
place_ball(&b, &paddle);
- wait_launch();
+ wait_launch(&b, &paddle);
while (remaining > 0) {
c = kbd();
LEFT and RIGHT move the bat while SPACE to launch shows, and the ball rides on it.
31.3
Starting from BREAK5.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,9 +10,10 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define TICK 3
#define LIVES 3
#define LAUNCHKEY ' '
+#define BONUS 100
#define LEFTKEY '['
#define RIGHTKEY ']'
@@ -32,5 +31,5 @@
ball b;
char bricks[BRICKROWS][BRICKCOLS];
-int score, remaining, lives;
+int score, remaining, lives, bonus_given;
void draw_court()
@@ -52,6 +51,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -62,5 +61,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -108,5 +107,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -114,5 +113,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -120,4 +119,8 @@
score += 10;
remaining--;
+ if (score >= BONUS && bonus_given == 0) {
+ bonus_given = 1;
+ lives++;
+ }
draw_score();
}
@@ -133,5 +136,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -139,5 +142,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -154,5 +157,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
With BONUS 100 for the test, a fourth ball was granted once the score passed 100.
32.1
Starting from BREAK6.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define STARTTICK 4
@@ -33,4 +31,5 @@
char bricks[BRICKROWS][BRICKCOLS];
int score, remaining, lives, level, tick;
+int rowtick[BRICKROWS];
void draw_court()
@@ -52,6 +51,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -62,5 +61,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -108,5 +107,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -114,5 +113,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -121,6 +120,5 @@
remaining--;
draw_score();
- if (remaining == BRICKROWS * BRICKCOLS / 2 && tick > 1)
- tick--;
+ tick = rowtick[r];
}
@@ -135,5 +133,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -141,5 +139,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -156,5 +154,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -196,4 +194,8 @@
level = 1;
tick = STARTTICK;
+ rowtick[0] = 1;
+ rowtick[1] = 2;
+ rowtick[2] = 3;
+ rowtick[3] = 4;
define_shapes();
draw_court();
rowtick[] holds a tick per brick row; a hit on the top row sets the tick to 1.
32.2
Starting from BREAK6.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define STARTTICK 4
@@ -52,6 +50,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -62,5 +60,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -108,5 +106,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -114,5 +112,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -135,5 +133,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -141,5 +139,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -156,5 +154,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -209,4 +207,6 @@
tick = 1;
draw_bricks();
+ message("Level up!");
+ wait_frames(50);
draw_score();
}
Level up! on the status row for a second before the next ball, once a wall is cleared.
32.3
Starting from BREAK6.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,6 +5,4 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
#define WALL '#'
#define BATCHAR '='
@@ -12,5 +10,5 @@
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#define FIRSTBRICKROW 2
#define STARTTICK 4
@@ -52,6 +50,6 @@
void define_shapes()
{
- shapedef(BALLCHAR, 0x00, 0x30, 0x78, 0xfc, 0xfc, 0x78, 0x30, 0x00);
- shapedef(BRICKCHAR, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -62,5 +60,5 @@
for (c = 0; c < BRICKCOLS; c++) {
bricks[r][c] = 1;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -108,5 +106,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -114,5 +112,5 @@
return;
bricks[r][c] = 0;
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -135,5 +133,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -141,5 +139,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -156,5 +154,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -204,4 +202,7 @@
while (lives > 0) {
if (remaining == 0) {
+ score += 100 * level;
+ message("Wall cleared: bonus!");
+ wait_frames(50);
level++;
tick = STARTTICK - level + 1;
Wall cleared: bonus! and 100 * level added, once a wall is cleared. (Clearing a wall takes a player; the code path is draw_bricks, as at the start.)
33.1
Starting from BREAK7.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,23 +5,14 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
-#define WALL 202
+#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#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 ']'
@@ -39,6 +30,5 @@
ball b;
char bricks[BRICKROWS][BRICKCOLS];
-int score, remaining, lives, level, tick, oldcol;
-int brickcol[BRICKROWS] = { 0x91, 0xB1, 0x31, 0x71 };
+int score, remaining, lives, level, tick, high;
void draw_court()
@@ -46,5 +36,4 @@
int i;
cls40();
- tcol(WALLCOL);
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
@@ -61,7 +50,6 @@
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);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -71,7 +59,6 @@
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);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -82,5 +69,4 @@
void draw_score()
{
- tcol(TEXTCOL);
curat(0, 22);
printf("Score: %4d Lives: %d Level: %d ", score, lives, level);
@@ -90,5 +76,4 @@
{
int i;
- tcol(TEXTCOL);
curat(0, 22);
printf("%s", s);
@@ -105,5 +90,4 @@
p->dx = 1;
p->dy = -1;
- tcol(BALLCOL);
curat(p->x, p->y);
putchar(BALLCHAR);
@@ -113,8 +97,6 @@
{
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");
@@ -123,5 +105,7 @@
curat(8, 14);
printf("%d lives; clear the bricks", LIVES);
- curat(8, 17);
+ curat(8, 16);
+ printf("High score: %d", high);
+ curat(8, 18);
printf("Press any key to play");
curat(0, 22);
@@ -141,5 +125,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -148,6 +132,5 @@
bricks[r][c] = 0;
beep();
- tcol(brickcol[r]);
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -163,5 +146,4 @@
{
int i;
- tcol(BATCOL);
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
@@ -171,5 +153,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -177,5 +159,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -192,5 +174,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -207,17 +189,8 @@
}
-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);
@@ -285,9 +258,9 @@
int c;
define_shapes();
- oldcol = peek(0xfb38);
- bcol(BACKDROP);
for (;;) {
title();
play();
+ if (score > high)
+ high = score;
message("Game over. Again? (Y/N)");
c = rawin();
@@ -295,6 +268,4 @@
break;
}
- tcol(oldcol);
- bcol(DEFAULTBACKDROP);
cls40();
printf("Press ENTER to finish\n");
High score: 0 on the title, and High score: 130 on the title after a game that scored 130.
33.2
Starting from BREAK7.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,23 +5,14 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
-#define WALL 202
+#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#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 ']'
@@ -39,6 +30,5 @@
ball b;
char bricks[BRICKROWS][BRICKCOLS];
-int score, remaining, lives, level, tick, oldcol;
-int brickcol[BRICKROWS] = { 0x91, 0xB1, 0x31, 0x71 };
+int score, remaining, lives, level, tick, high;
void draw_court()
@@ -46,5 +36,4 @@
int i;
cls40();
- tcol(WALLCOL);
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
@@ -61,7 +50,6 @@
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);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -71,7 +59,6 @@
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);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -82,5 +69,4 @@
void draw_score()
{
- tcol(TEXTCOL);
curat(0, 22);
printf("Score: %4d Lives: %d Level: %d ", score, lives, level);
@@ -90,5 +76,4 @@
{
int i;
- tcol(TEXTCOL);
curat(0, 22);
printf("%s", s);
@@ -105,5 +90,4 @@
p->dx = 1;
p->dy = -1;
- tcol(BALLCOL);
curat(p->x, p->y);
putchar(BALLCHAR);
@@ -113,8 +97,6 @@
{
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");
@@ -123,5 +105,7 @@
curat(8, 14);
printf("%d lives; clear the bricks", LIVES);
- curat(8, 17);
+ curat(8, 16);
+ printf("High score: %d", high);
+ curat(8, 18);
printf("Press any key to play");
curat(0, 22);
@@ -141,5 +125,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -148,6 +132,5 @@
bricks[r][c] = 0;
beep();
- tcol(brickcol[r]);
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -163,5 +146,4 @@
{
int i;
- tcol(BATCOL);
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
@@ -171,5 +153,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -177,5 +159,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -192,5 +174,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -207,17 +189,8 @@
}
-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);
@@ -280,4 +253,27 @@
}
+void load_high()
+{
+ FILE *f;
+ char line[40];
+ high = 0;
+ f = fopen("BREAKOUT.HI", "r");
+ if (f == 0)
+ return;
+ fgets(line, 40, f);
+ fclose(f);
+ high = atoi(line);
+}
+
+void save_high()
+{
+ FILE *f;
+ f = fopen("BREAKOUT.HI", "w");
+ if (f == 0)
+ return;
+ fprintf(f, "%d\n", high);
+ fclose(f);
+}
+
main()
{
@@ -285,9 +281,12 @@
int c;
define_shapes();
- oldcol = peek(0xfb38);
- bcol(BACKDROP);
+ load_high();
for (;;) {
title();
play();
+ if (score > high) {
+ high = score;
+ save_high();
+ }
message("Game over. Again? (Y/N)");
c = rawin();
@@ -295,6 +294,4 @@
break;
}
- tcol(oldcol);
- bcol(DEFAULTBACKDROP);
cls40();
printf("Press ENTER to finish\n");
After the game, DISP BREAKOUT.HI shows 130, and the next start shows it on the title.
33.3
Starting from BREAK7.C, the changes (- lines out, + lines in, @@ marks where):
@@ -5,23 +5,14 @@
#define TOPWALL 0
#define BATROW 21
-#define PLAYLEFT 2
-#define PLAYRIGHT 37
-#define WALL 202
+#define WALL '#'
#define BATCHAR '='
#define BALLCHAR 200
#define BRICKCHAR 201
#define BRICKROWS 4
-#define BRICKCOLS 18
+#define BRICKCOLS 19
#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 ']'
@@ -39,6 +30,5 @@
ball b;
char bricks[BRICKROWS][BRICKCOLS];
-int score, remaining, lives, level, tick, oldcol;
-int brickcol[BRICKROWS] = { 0x91, 0xB1, 0x31, 0x71 };
+int score, remaining, lives, level, tick;
void draw_court()
@@ -46,5 +36,4 @@
int i;
cls40();
- tcol(WALLCOL);
for (i = LEFTWALL; i <= RIGHTWALL; i++) {
curat(i, TOPWALL);
@@ -61,7 +50,6 @@
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);
+ shapedef(BALLCHAR, 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00);
+ shapedef(BRICKCHAR, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0x00);
}
@@ -71,7 +59,6 @@
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);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(BRICKCHAR);
putchar(BRICKCHAR);
@@ -82,5 +69,4 @@
void draw_score()
{
- tcol(TEXTCOL);
curat(0, 22);
printf("Score: %4d Lives: %d Level: %d ", score, lives, level);
@@ -90,5 +76,4 @@
{
int i;
- tcol(TEXTCOL);
curat(0, 22);
printf("%s", s);
@@ -105,5 +90,4 @@
p->dx = 1;
p->dy = -1;
- tcol(BALLCOL);
curat(p->x, p->y);
putchar(BALLCHAR);
@@ -113,8 +97,6 @@
{
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");
@@ -141,5 +123,5 @@
int r, c;
r = p->y - FIRSTBRICKROW;
- c = (p->x - PLAYLEFT) / 2;
+ c = (p->x - 1) / 2;
if (r < 0 || r >= BRICKROWS || c < 0 || c >= BRICKCOLS)
return;
@@ -148,6 +130,5 @@
bricks[r][c] = 0;
beep();
- tcol(brickcol[r]);
- curat(PLAYLEFT + 2 * c, FIRSTBRICKROW + r);
+ curat(1 + 2 * c, FIRSTBRICKROW + r);
putchar(' ');
putchar(' ');
@@ -163,5 +144,4 @@
{
int i;
- tcol(BATCOL);
curat(p->left, BATROW);
for (i = 0; i < p->width; i++)
@@ -171,5 +151,5 @@
void move_bat(p, dir) bat *p; int dir;
{
- if (dir < 0 && p->left > PLAYLEFT) {
+ if (dir < 0 && p->left > LEFTWALL + 1) {
p->left--;
curat(p->left + p->width, BATROW);
@@ -177,5 +157,5 @@
draw_bat(p);
}
- if (dir > 0 && p->left + p->width - 1 < PLAYRIGHT) {
+ if (dir > 0 && p->left + p->width < RIGHTWALL) {
curat(p->left, BATROW);
putchar(' ');
@@ -192,5 +172,5 @@
p->x += p->dx;
p->y += p->dy;
- if (p->x <= PLAYLEFT || p->x >= PLAYRIGHT)
+ if (p->x <= LEFTWALL + 1 || p->x >= RIGHTWALL - 1)
p->dx = -p->dx;
if (p->y <= TOPWALL + 1)
@@ -207,17 +187,8 @@
}
-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);
@@ -262,4 +233,12 @@
if (c == RIGHTKEY)
move_bat(&paddle, 1);
+ if (c == 'P') {
+ message("Paused - any key");
+ while (kbd() != 0)
+ ;
+ while (kbd() == 0)
+ ;
+ draw_score();
+ }
move_ball(&b, &paddle);
if (b.y >= BATROW)
@@ -285,6 +264,4 @@
int c;
define_shapes();
- oldcol = peek(0xfb38);
- bcol(BACKDROP);
for (;;) {
title();
@@ -295,6 +272,4 @@
break;
}
- tcol(oldcol);
- bcol(DEFAULTBACKDROP);
cls40();
printf("Press ENTER to finish\n");
P shows Paused - any key on the status row; a key resumes and the score is redrawn.
34.1
#include STDIO.H
main()
{
int argc, i;
char **argv;
char buffer[80];
cpm_cmd_line(&argc, &argv, buffer);
for (i = 1; i < argc; i++) {
printf("%s", argv[i]);
if (i < argc - 1)
printf(" ");
}
printf("\n");
}
#include ?CPM.LIB?
#include ?STDIO.LIB?
E341 THE TATUNG EINSTEIN prints THE TATUNG EINSTEIN; E341 alone prints an empty line.
THE TATUNG EINSTEIN
34.2
#include STDIO.H
extern char *strupper();
main()
{
int argc, c, n;
char **argv;
char buffer[80];
char *text;
FILE *f;
cpm_cmd_line(&argc, &argv, buffer);
if (argc < 2) {
printf("UPPER filename\n");
return;
}
f = fopen(argv[1], "r");
if (f == 0) {
printf("no such file\n");
return;
}
text = malloc(5000);
n = 0;
while ((c = getc(f)) != EOF && n < 4999)
text[n++] = c;
text[n] = 0;
fclose(f);
strupper(text);
printf("%s", text);
}
#include ?CPM.LIB?
#include ?STDIO.LIB?
E342 SMALL.TXT, with SMALL.TXT holding two lines, prints them in capitals; E342 NOSUCH.TXT prints no such file. read_file would do the reading, but it does not say how many bytes it read, and strupper needs the 0 straight after them, so the solution reads with getc and puts the 0 itself. The extern char *strupper(); line is needed, and S34 says why.
ONE LINE OF TEXT
AND ANOTHER
34.3
#include STDIO.H
main()
{
int argc, c;
char **argv;
char buffer[80];
cpm_cmd_line(&argc, &argv, buffer);
if (argc < 2) {
printf("WIPE filename\n");
return;
}
printf("Delete %s - sure? ", argv[1]);
c = rawin();
if (c == 'Y' || c == 'y') {
unlink(argv[1]);
printf("\ngone\n");
} else
printf("\nkept\n");
}
#include ?CPM.LIB?
#include ?STDIO.LIB?
E343 SMALL.TXT and N: kept; with Y: gone, and DIR SMALL.TXT says No File.