Showing posts with label BDS C. Show all posts
Showing posts with label BDS C. Show all posts

Wednesday, April 16, 2014

My Text Adventure Game Running on CP/M

After a couple more hours of work and I have my Abandoned Farmhouse text adventure game ported to CP/M using the BDS C compiler. The changes were similar to those needed for the Yum game, and included some changes for the available string functions and initialization of some large arrays.

I haven't played the game to completion but it seems to be working well. You can find source code and a CP/M binary here.

Below is a transcript of playing a short game.


B>advent
                      Abandoned Farmhouse Adventure
                            By Jeff Tranter

Your four-year-old grandson has gone missing and was last seen headed in the
direction of the abandoned family farm. It's a dangerous place to play. You
have to find him before he gets hurt, and it will be getting dark soon...

? help
Valid Commands:
Go east/west/north/south/up/down
Look
Use object
Examine object
Take object
Drop object
Inventory
Help
Quit
You can abbreviate commands and directions to the first letter.
Type just the first letter of a direction to move.
? i
You are carrying:
  flashlight
? l
You are at the door to the house.
You see:
  key
  bottle
You can go: east west
? drop flashlight
Dropped flashlight.
? t key
Took key.
? t bottle
Took bottle.
? n
You can't go north from here.
? l
You are at the door to the house.
You see:
  flashlight
You can go: east west
? w
You are in the kitchen.
? l
You are in the kitchen.
You see:
  candybar
You can go: south east down
? t candybar
Took candybar.
? w
You can't go west from here.
? l
You are in the kitchen.
You see:
  nothing special
You can go: south east down
? s
You are in the dining room.
? l
You are in the dining room.
You see:
  stale meat
You can go: north west
? u stale meat
The meat looked and tasted bad. You feel very sick and pass out.
Game over after 7 turns.
Do you want to play again (y/n)? n

B>

Tuesday, April 15, 2014

Yum Game ported to BDS C

I've been playing some more with the Briel Altair 8800 running CP/M.

As a larger test of the BDS C compiler I was able to port the "Yum" game that I originally wrote to run on the Briel Apple Replica 1.

Porting it to BDS C was a few hours of work (mostly spent transferring new versions of the code between my Linux desktop and SD card and compiling on the Altair 8800.

The changes required were not too major. I was impressed by the reasonably complete run-time library included with BDS C. In all, the changes I had to make were the following:

  • Includes changed (BDSC C has everything in stdio.h).
  • sizeof does not work for arrays, so used a constant.
  • Arrays cannot be initialized, but can use initptr() function instead.
  • No bool type, so use int.
  • Function declarations have to use old K&R format.
  • Text supports lower case (original Apple 1 version had to be upper case only).
  • Some text lines (like help) made wider due to 80 column screen.
  • Variables cannot be initialized when declared.
  • No strtol() so use atoi().
  • Remove const qualifiers.
  • Clear screen using ANSI escape sequence.

Below is a partial log of a session playing the game against the computer.



#     # #     # #     #
 #   #  #     # ##   ##
  # #   #     # # # # #
   #    #     # #  #  #
   #    #     # #     #
   #    #     # #     #
   #     #####  #     #


Welcome to Yum!
Do you want instructions (y/n) ? y

This is a computer version of the game Yum, similar to games known as Yahtzee,
Yacht and Generala. Each player rolls five dice up to three times and then
applies the dice toward a category to claim points. The game has 12 rounds
during which each player attempts to claim the most points in each category.

The winner is the person scoring the most points at the end of the game.
This version supports up to three players of which any can be human or
computer players.

Categories are as follows:
1'S through 6'S - dice of same type
Low Straight (15) - 1 2 3 4 5
High Straight (20) - 2 3 4 5 6
Low Score - total 21 or more
High Score - total 22 or more
Full House (25) - 3 of a kind and pair
Yum (30) - 5 dice the same
Bonus of 25 points if upper section is 63 or more.

How many human players (0-3)? 1
How many computer players (0-2)? 1
Name of player 1? Jeff
Press to start the game
Wait a few seconds, and type a CR: 

Jeff's turn. Press to roll 
First roll is: 2 2 2 4 5
Enter dice to roll again or D for dice or S for score: 4 5
Second roll is: 2 2 2 2 2
Enter dice to roll again or D for dice or S for score: 

 1  - 1'S
 2  - 2'S
 3  - 3'S
 4  - 4'S
 5  - 5'S
 6  - 6'S
 9  - Low Straight
10  - High Straight
11  - Low Score
12  - High Score
13  - Full House
14  - Yum

Jeff, What category do you want to claim? (1-14)? 14

Altair's turn. Press to roll 
First roll is: 1 1 4 4 5
Altair keeps: 1 1 4 4
Second roll is: 1 1 4 4 5
Altair keeps: 1 1 4 4
Last roll is: 1 1 2 4 4
Altair plays 1'S

Press to continue 

Score after 1 of 12 rounds:

Roll           Jeff    Altair  
1'S                    2       
2'S                            
3'S                            
4'S                            
5'S                            
6'S                            
Sub-total      0       2       
Bonus          0       0       
Low Straight                   
High Straight                  
Low Score                      
High Score                     
Full House                     
Yum            30              
Total          30      2       

Press to continue 

Jeff's turn. Press to roll 
First roll is: 1 2 2 6 6
Enter dice to roll again or D for dice or S for score: 1
Second roll is: 2 2 4 6 6
Enter dice to roll again or D for dice or S for score: 4
Last roll is: 2 2 6 6 6

 1  - 1'S
 2  - 2'S
 3  - 3'S
 4  - 4'S
 5  - 5'S
 6  - 6'S
 9  - Low Straight
10  - High Straight
11  - Low Score
12  - High Score
13  - Full House

Jeff, What category do you want to claim? (1-14)? 13

Altair's turn. Press to roll 
First roll is: 2 4 4 6 6
Altair keeps: 4 4 6 6
Second roll is: 4 4 4 6 6
Altair keeps: 4 4 4 6 6
Altair plays Full House

Press to continue 

Score after 2 of 12 rounds:

Roll           Jeff    Altair  
1'S                    2       
2'S                            
3'S                            
4'S                            
5'S                            
6'S                            
Sub-total      0       2       
Bonus          0       0       
Low Straight                   
High Straight                  
Low Score                      
High Score                     
Full House     25      25      
Yum            30              
Total          55      27      

Press to continue


I put the source code as well as a CP/M binary here on github.  Next, I plan to try porting my text adventure game.

Tuesday, March 18, 2014

Using the CP/M BDS C Compiler

I'll continue giving more details on the programs I demonstrated in the YouTube video The Briel Altair 8800 Kit, Part 5: Advanced Topics.

This time, the BDS C Compiler.

Go to Leo Zolman's BDS C web page and download the release file bdsc-all.zip.

BDS C comes with extensive documentation in the file bdsc-guide.pdf, but for the purposes of a simple demo, you can do the following. Unzip the file and copy these files to an SD card, and then transfer them to a CP/M drive:

BDSCIO.H C.CCC CC.COM CC2.COM
CLINK.COM DEFF.CRL DEFF2.CRL STDIO.H

The example program TAIL.C used in the demonstration was found here.

Here is an even shorter example C program that I  wrote. I entered it as the filename EX1.C:

/* BDS C example 1 */
#include

main(argc,argv)
char **argv;
{
    int i;

    printf("Example Program 1\n");
    for (i=1; i <=10; i++) {
        printf("%d\n", i);
    }
    return 0;
}

Here is a sample session showing EX1.C and TAIL.C being compiled, linked, and run (commands typed by the user are in bold).

B>dir

B: EX1      C   : NQUEENS  C   : BDSCIO   H   : C        CCC
B: CC       COM : CC2      COM : CLINK    COM : DEFF     CRL
B: DEFF2    CRL : STDIO    H   : TAIL     C

B>cc ex1

BD Software C Compiler v1.60  (part I)
  37K elbowroom
BD Software C Compiler v1.60 (part II)
  34K to spare

B>clink ex1

BD Software C Linker   v1.60

Last code address: 0E8D 
Externals start at 0E8E, occupy 0006 bytes, last byte at 0E93 
Top of memory: E805 
Stack space: D972 
Writing output...
  46K link space remaining

B>ex1

Example Program 1
1
2
3
4
5
6
7
8
9
10

B>cc tail

BD Software C Compiler v1.60  (part I)
  36K elbowroom
BD Software C Compiler v1.60 (part II)
  33K to spare

B>clink tail

BD Software C Linker   v1.60

Last code address: 1402 
Externals start at 1403, occupy 0006 bytes, last byte at 1408 
Top of memory: E805 
Stack space: D3FD 
Writing output...
  44K link space remaining

B>tail -10 tail.c

}
                                


int lastchar(c)
char c;
{
        return (!c) || (c == CPMEOF);
}

B>tail

Usage: tail [-#]

B>dir

B: TAIL     CRL : TAIL     COM : NQUEENS  CRL : NQUEENS  COM
B: EX1      C   : NQUEENS  C   : BDSCIO   H   : C        CCC
B: CC       COM : CC2      COM : CLINK    COM : DEFF     CRL
B: DEFF2    CRL : STDIO    H   : TAIL     C   : EX1      CRL
B: EX1      COM

Finally, here is the N Queens example program shown in the YouTube video. It will take a while to run to completion.   First the source code, followed by example output.

/* Solve the n queens problem */

#include

#define MAX_N 8

int  board[MAX_N*MAX_N];
int tries;
int  solutions;
int  n;
int  nsq;
int cache[MAX_N+1]; /* get some savings by caching last position */

/* display the board */
void print_board()
{
  int i;
  
  printf("+");
  for (i = 0; i < n ; i++)
    printf("---");
  printf("+\n");

  for (i = 0; i < nsq ; i++) {
    if ((i % n) == 0)
      printf("|");
    if (board[i])
      printf(" Q ");
    else
      printf(" . ");
    if (((i+1) % n) == 0)
      printf("|\n");
  }

  printf("+");
  for (i = 0; i < n ; i++)
    printf("---");
  printf("+\n");
}

/* find position of a piece */
int piece(n)
{
  int i;

  /* first try the cache */
  if (board[cache[n]] == n)
    return cache[n];
  
  for (i = 0 ; i < nsq ; i++)
    if (board[i] == n) {
      cache[n] = i; /* cache it for next time */
      return i;
    }
  return -1;
}

/* see if board is a solution */
void check_board()
{
  int i, p, r, c, j;

  /* loop over all pieces */
  for (i = 1 ; i <= n ; i++) {
    p = piece(i);

    /* not a solution if piece in same row */
    r = p / n;
    for (c = 0 ; c < n ; c++) {
      if (board[r*n+c] != 0 && board[r*n+c] != i)
return;
    }

    /* not a solution if piece in same column */
    c = p % n;
    for (r = 0 ; r < n ; r++) {
      if (board[r*n+c] != 0 && board[r*n+c] != i)
return;
    }
    
    /* not a solution if piece in same \ diagonal */
    for (j = -n ; j < n ; j++) {
      r = p / n + j;
      c = p % n + j;
      if ((r >= 0) && (r < n) && (c >= 0) && (c < n) &&
 (board[r*n+c] != 0) && (board[r*n+c] != i))
return;
    }
    /* not a solution if piece in same / diagonal */
    for (j = -n ; j < n ; j++) {
      r = p / n + j;
      c = p % n - j;
      if ((r >= 0) && (r < n) && (c >= 0) && (c < n) &&
 (board[r*n+c] != 0) && (board[r*n+c] != i))
return;
    }
  }
  solutions++;
  print_board();
}

/* move piece p to next position */
int next_pos(p)
{
  int i, t;

  if (p < 1)
    return 0;

  i = piece(p);

  if (i < nsq-n+p-1) {
    board[i] = 0;
    board[i+1] = p;
    return 1;
  } else {
    t = next_pos(p-1);
    board[i] = 0;
    board[piece(p-1)+1] = p;
    return t;
  }
}

/* generate the next possible solution */
int next_board()
{
  return next_pos(n);
}


int main()
{
  int i;

  solutions = 0;
  n = 5;
  nsq = n*n;           /* save n^2 to avoid calculating it again */

  printf("\n\n\n\nSOLVING N QUEENS PROBLEM FOR N = %d\n", n);

  /* clear the board */
  for (i = 0 ; i < nsq ; i++)
    board[i] = 0;

  /* initially place the queens */
  for (i = 0 ; i < n ; i++)
    board[i] = i+1;

  do {
    tries++;
    check_board();
  } while (next_board());
  
  printf("FOUND %d SOLUTIONS AFTER %ld TRIES.\n", solutions, tries);
        
  return 0;
}

B>nqueens

SOLVING N QUEENS PROBLEM FOR N = 5
+---------------+
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
+---------------+
+---------------+
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
+---------------+
+---------------+
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
+---------------+
+---------------+
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
+---------------+
+---------------+
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
+---------------+
+---------------+
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
+---------------+
+---------------+
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
+---------------+
+---------------+
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
+---------------+
+---------------+
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
+---------------+
+---------------+
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
+---------------+
FOUND 10 SOLUTIONS AFTER -12406 TRIES.

B>