home *** CD-ROM | disk | FTP | other *** search
- /* Turing Machine V 1.0 (C) Copyright 1991 Kevin Dahlhausen */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <conio.h>
- #include <dos.h>
-
- #define TAPESIZE 1000 /* number of positions on tape */
- #define MAXNUMSTATES 256 /* max number of internal states */
-
- #define BLANK '0' /* blank character on tape */
- #define UNDEFINED -1 /* 'next state' field of an undefined state */
- #define INITIALSTATE 0 /* tm begins execution in this state */
-
- #define SCREENWIDTH 80
- #define TAPEY 5 /* tape y position on screen */
- #define TMXADJ 4 /* distance UL corner of tm picture to read head */
-
- typedef struct {
- int state;
- char read; /* mark on tape to match */
- int nextstate; /* next state to goto */
- char write; /* put this symbol on the tape */
- char command; /* what to do here */
- } statedef;
-
- /* function prototypes */
- char ReadTape(int);
- void WriteTape(int, char);
-
- /* global variables */
- int TapeBase; /* index of leftmost tape mark on screen */
- char tape[TAPESIZE];
-
- /**************************************************************************/
- void SetCursor(char start, char end)
- /* requires: none
- * ensures: cursor start, end lines set as given
- *
- * Note: This routine is only used for aesthetic purposes
- */
- {
- struct REGPACK regs;
- regs.r_ax=0x0100;
- regs.r_cx=(start*256)+end;
- intr(0x10, ®s);
- }
-
- /**************************************************************************/
- void DrawTM(int x, int y, int state)
- /* requires: none
- * ensures: TM is drawn at x,y with state
- */
- {
- gotoxy(x,y+0); printf(" ║ ");
- gotoxy(x,y+1); printf("╔═══╩═╗");
- gotoxy(x,y+2); printf("║ ║");
- gotoxy(x,y+3); printf("╚═════╝");
- gotoxy(x+2,y+2); printf("%-3d",state);
- }
-
- /**************************************************************************/
- void EraseTM(int x, int y)
- /* requires: none
- * ensures: TM is erased
- */
- {
- gotoxy(x,y); printf(" ");
- gotoxy(x,y+1); printf(" ");
- gotoxy(x,y+2); printf(" ");
- gotoxy(x,y+3); printf(" ");
- }
-
-
- /**************************************************************************/
- void DrawTape(int y, int start)
- /* requires: none
- * ensures: tape is drawn on screen at position y starting at index start
- */
- {
- int i;
- gotoxy(1,y);
- for (i=0;i<SCREENWIDTH;i++) printf("%c",ReadTape(start++));
- }
-
-
- /**************************************************************************/
- void InitTape(int *itp)
- /* requires: none
- * ensures: tape is initialized for use
- */
- {
- int i;
- int index;
- char string[255];
-
- for (i=0;i<TAPESIZE;i++) tape[i]=BLANK;
-
- printf("\nTape index at start of string (tape length is %d): ", TAPESIZE);
- scanf("%d",&index);
- printf("\nString to put at position %d:",index);
- scanf("%s",&string);
- strncpy(&tape[index],string,strlen(string));
- printf("\nInitial read/write head position?");
- scanf("%d",itp);
-
- }
-
-
- /**************************************************************************/
- char ReadTape(int HeadPos)
- /* requiers: 0<=HeadPos<TAPESIZE
- * ensures: symbol at HeadPos is read
- * returns: BLANK or MARK
- */
- {
- if ( (0<=HeadPos)&&(HeadPos<TAPESIZE)) return tape[HeadPos];
- else {
- printf("\n Error: attempted read past end of tape");
- exit(1);
- }
- }
-
-
- /**************************************************************************/
- void WriteTape(int HeadPos, char value)
- /* requires: 0<=HeadPos<TAPESIZE
- * ensures: value is written to tape at position HeadPos
- */
- {
- if ( (0<=HeadPos)&&(HeadPos<TAPESIZE)) tape[HeadPos]=value;
- else {
- printf("\n Error: attempted write past end of tape");
- exit(1);
- }
- DrawTape(TAPEY, TapeBase);
- }
-
-
- /**************************************************************************/
- void RightMove(int *HeadPos, int state)
- /* requires: HeadPos+1<TAPESIZE
- * ensures: machine moved one space to right on tape
- */
- {
- EraseTM(*HeadPos-TMXADJ+1-TapeBase,TAPEY+1);
- (*HeadPos)++;
- if (*HeadPos>=TAPESIZE) {
- printf("\n Error: attempted move past right end of tape");
- exit(1);
- }
- if ((*HeadPos-TMXADJ+1-TapeBase)>SCREENWIDTH-10) {
- TapeBase=TapeBase+(SCREENWIDTH*0.5);
- if (TapeBase>(TAPESIZE-SCREENWIDTH)) TapeBase=(TAPESIZE-SCREENWIDTH);
- DrawTape(TAPEY, TapeBase);
- }
- DrawTM(*HeadPos-TMXADJ+1-TapeBase,TAPEY+1, state);
- }
-
-
- /**************************************************************************/
- void LeftMove(int *HeadPos, int state)
- /* requires: 0<HeadPos
- * ensures: machine moved one space to left on tape
- */
- {
- EraseTM(*HeadPos-TMXADJ+1-TapeBase,TAPEY+1);
- (*HeadPos)--;
- if (0>*HeadPos) {
- printf("\n Error: attempted move past left end of tape");
- exit(1);
- }
- if ((*HeadPos-TMXADJ+1-TapeBase)<5) {
- TapeBase=TapeBase-(SCREENWIDTH*0.5);
- if (TapeBase<0) TapeBase=0;
- DrawTape(TAPEY, TapeBase);
- }
-
- DrawTM(*HeadPos-TMXADJ+1-TapeBase,TAPEY+1, state);
- }
-
-
- /**************************************************************************/
- void Stop()
- /* requires: none
- * ensures: bell is rung, machine stopped, signals completion of calculation
- */
- {
- printf("\x07");
- getch();
- }
-
-
- /**************************************************************************/
- void GetTM(char *filename, statedef *t, int *NumDefs)
- /* requires: filename is a valid TM definition file
- * ensures: turing machine definition is read from a file
- */
- {
- int i;
- FILE *infile;
- char nextline[81];
- char result;
-
- for (i=0;i<MAXNUMSTATES;i++) t[i].nextstate=UNDEFINED;
-
- if ((infile=fopen(filename,"rt"))==NULL) {
- printf("\nError: Unable to open file:%s",filename);
- exit(1);
- }
-
- i=0;
- while((fgets(nextline,80,infile) != NULL)&&(i<MAXNUMSTATES)) {
- if (nextline[0] != '#') { /* ignore comments */
- result=sscanf(nextline, "%d,%c->%d,%c,%c",
- &t[i].state, &t[i].read, &t[i].nextstate,
- &t[i].write, &t[i].command);
- if (result != 5) { /* sscanf should convert 5 fields */
- printf("\nError: Bad state format, line %d: %s",i+1,nextline);
- exit(1);
- }
- i++;
- }
- }
- fclose(infile);
- *NumDefs=i;
- }
-
-
- /**************************************************************************/
- void LookUp(statedef tm[], int NumDefs, int state, char sym,
- int *nstate, char *wsym, char *command)
- /* requires: tm[0]..tm[NumDefs-1] are valid state definitions
- * ensures: nstate, wsym, commmand are set as required when
- * the tm is in state and has read sym from the tape
- *
- * NOTE: Presently this is just a a linear search of the tm definition
- * array. This action was made a separate funcion to ease any
- * future changes to the access method.
- */
- {
- int i=0, found=0;
-
- while( (!found)&&(i<NumDefs)) {
- if ((tm[i].state==state)&&(tm[i].read==sym)) {
- found=1;
- *nstate=tm[i].nextstate;
- *wsym=tm[i].write;
- *command=tm[i].command;
- }
- i++;
- }
-
- if (!found) {
- printf("\nError: Unable to find definition for read of %c in state %d",
- sym,state);
- exit(1);
- }
- }
-
- /**************************************************************************/
- void InitScreen(int base, int HeadPos)
- /* requires: HeadPos - base < SCREENWIDTH + TMXADJ
- * ensure: screen is drawn with tape starting at base, tm at HeadPos
- */
- {
- clrscr();
- printf(" Turing Machine Simulator (C) Copyright 1991 Kevin Dahlhausen");
- TapeBase=base;
- DrawTape(TAPEY, TapeBase);
- DrawTM(HeadPos-TMXADJ+1-TapeBase,TAPEY+1, 0);
- }
-
-
- /**************************************************************************/
- void RunTM( statedef tm[], int NumDefs, int itp)
- /* requires: tm[0]..tm[NumDefs-1] are valid state definitions
- * itp is the initial postion of the tm on the tape
- * ensures: turing machine computation is simulated
- */
- {
- int state=INITIALSTATE; /* current state number */
- char symbol; /* last symbol read from tape */
- int notdone=1;
- long int cycles=1;
- int HeadPos; /* position of tm on tape */
- int nextstate; /* next state to go to */
- char writesym; /* symbol to write on tape */
- char command; /* command to perform */
-
- HeadPos=itp;
-
-
- InitScreen(HeadPos-20, HeadPos); /* draw initial screen */
-
- while (notdone) {
- symbol=ReadTape(HeadPos);
- LookUp(tm, NumDefs, state, symbol, &nextstate, &writesym, &command);
- WriteTape(HeadPos, writesym);
- gotoxy(1,20);
- printf("Position:%3d State:%-3d Read:%c Next state:%-3d Wrote:%c ",
- HeadPos, state, symbol, nextstate, writesym);
- printf(" Command:%c Cycles:%d", command ,cycles);
-
- switch (command) {
- case 'R': RightMove(&HeadPos, state);
- break;
- case 'L': LeftMove(&HeadPos, state);
- break;
- case 'S': Stop();
- notdone=0;
- break;
- default: printf("\nError: illegal command in state %d read &c",
- state, symbol);
- exit(1);
- }
- state=nextstate;
- cycles++;
- }
- }
-
-
- /**************************************************************************/
- main()
- {
- int NumDefs; /* number of state definitions */
- int itp; /* initial tape position */
- char name[80];
-
- statedef tm[MAXNUMSTATES]; /* internal definition of Turing Machine (tm) */
-
- printf("\n Turing Machine Simulator (C) Copyright 1991 Kevin Dahlhausen");
- printf("\nMachine to run? ");
- scanf("%s",name);
-
- GetTM(name, tm, &NumDefs); /* input internal state definitions */
- InitTape(&itp); /* setup the tape */
-
- SetCursor(32, 32);
- RunTM(tm, NumDefs, itp);
- SetCursor(6,7);
- }