Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * This is a demonstration of the old Game of Life algorithm
- * which was a popular programming experiment back in the late
- * 1970s and early 1980s. The idea is that each simple cell can
- * only live and multiply under certain circumstances, as stated
- * on the opening screen of the programme.
- *
- * @Author: Shaun B
- * @Version: 1.0.2a - 2013-04-30
- * @Todo: Probably could do with speeding up, using ROM
- * to out the char and track the cursor, there is
- * definitely a quicker way, but it was written to
- * calculate off-sets of a flat array so it behaves
- * like a 2D array. Quality.
- *
- **/
- /// Included libraries:
- #include <zx81.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <input.h>
- /// Pre-processor symbols:
- #define INVERSE(A) (0x80 | A)
- #define SCRLOC(X,Y) (X<<8 | Y)
- #define DIVBYTEN(Z) ((Z>>3) - (Z>>1))
- #define PRINTAT 0x08f5
- #define PRINT 0x10
- #define MAXWIDTH 32
- #define MAXHEIGHT 20
- #define WIDTH 16
- #define HEIGHT 16
- #define MAXSTEPS 32767
- #define MINSTEPS 12
- #define MINWIDTH 9
- #define MINHEIGHT 9
- // ZX81 character set:
- #define CLEAR 0x00
- #define TL 0x01
- #define TR 0x02
- #define TOP 0x03
- #define BL 0x04
- #define LEFT 0x05
- #define CHECKER 0x06
- #define CORNER 0x07
- #define CHESSB 0x08
- #define CHESSBOT 0x09
- #define CHESSTOP 0x0a
- #define QUOTE 0x0b
- #define POUND 0x0c
- #define DOLLAR 0x0d
- #define COLON 0x0e
- #define QM 0x0f
- #define OBRACKET 0x10
- #define CBRACKET 0x11
- #define GRT 0x12
- #define LST 0x13
- #define EQUALS 0x14
- #define PLUS 0x15
- #define DASH 0x16
- #define STAR 0x17
- #define SLASH 0x18
- #define SEMI 0x19
- #define COMMA 0x1a
- #define DOT 0x1b
- #define ZERO 0x1c
- #define ONE 0x1d
- #define TWO 0x1e
- #define THREE 0x1f
- #define FOUR 0x20
- #define FIVE 0x21
- #define SIX 0x22
- #define SEVEN 0x23
- #define EIGHT 0x24
- #define NINE 0x25
- #define _A 0x26
- #define _B 0x27
- #define _C 0x28
- #define _D 0x29
- #define _E 0x2a
- #define _F 0x2b
- #define _G 0x2c
- #define _H 0x2d
- #define _I 0x2e
- #define _J 0x2f
- #define _K 0x30
- #define _L 0x31
- #define _M 0x32
- #define _N 0x33
- #define _O 0x34
- #define _P 0x35
- #define _Q 0x36
- #define _R 0x37
- #define _S 0x38
- #define _T 0x39
- #define _U 0x3a
- #define _V 0x3b
- #define _W 0x3c
- #define _X 0x3d
- #define _Y 0x3e
- #define _Z 0x3f
- #define EOS 0x40
- /// Function prototypes:
- static void main(void);
- static void clearGrid(void);
- static void fillArray(void);
- static void printNumber(signed short num);
- static void printArray(signed short stepNumber);
- static void checkNeighbour(void);
- static void setSize(void);
- static void print(short ch);
- static void printat(short xy);
- static void pause(char z);
- /// Global variables:
- /// Global variables:
- unsigned char choice=0;
- unsigned char x=WIDTH;
- unsigned char y=HEIGHT;
- unsigned char i=0;
- unsigned char j=0;
- unsigned char c=0;
- unsigned char title[]=
- {
- CLEAR,CLEAR,CLEAR,CLEAR,INVERSE(_G),INVERSE(_A),INVERSE(_M),
- INVERSE(_E),CLEAR,INVERSE(_O),INVERSE(_F),CLEAR,INVERSE(_L),
- INVERSE(_I),INVERSE(_F),INVERSE(_E),CLEAR,INVERSE(_V),
- INVERSE(ONE),INVERSE(DOT),INVERSE(ZERO),INVERSE(DOT),
- INVERSE(TWO),CLEAR,INVERSE(_Z),INVERSE(_X),INVERSE(EIGHT),
- INVERSE(ONE),0x76,0x76,EOS
- };
- unsigned char instructions[]=
- {
- _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
- ONE,CLEAR,_O,_R,CLEAR,ZERO,0x76,
- _N,_E,_I,_G,_H,_B,_O,_U,_R,_S,CLEAR,_D,_I,_E,_S,CLEAR,
- _F,_R,_O,_M,CLEAR,_L,_O,_N,_E,_L,_I,_N,_E,_S,_S,0x76,
- _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
- _F,_O,_U,_R,CLEAR,_O,_R,CLEAR,_M,_O,_R,_E,0x76,
- _N,_E,_I,_G,_H,_B,_O,_U,_R,_S,CLEAR,_D,_I,_E,_S,CLEAR,
- _F,_R,_O,_M,CLEAR,_O,_V,_E,_R,DASH,0x76,
- _P,_O,_P,_U,_L,_A,_T,_I,_O,_N,0x76,
- _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
- _T,_W,_O,CLEAR,_O,_R,CLEAR,_T,_H,_R,_E,_E,0x76,
- _N,_E,_I,_G,_H,_B,_O,_U,_R,_S,CLEAR,_H,_A,_P,_P,_I,_L,_Y,
- CLEAR,_C,_O,DASH,_E,_X,_I,_S,_T,_S,0x76,
- _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
- _T,_H,_R,_E,_E,CLEAR,_N,_E,_I,_G,_H,_B,_O,_U,_R,_S,0x76,
- _W,_I,_L,_L,CLEAR,_M,_U,_L,_T,_I,_P,_L,_Y,0x76,0x76,
- _H,_O,_W,CLEAR,_M,_A,_N,_Y,CLEAR,_S,_T,_E,_P,_S,CLEAR,
- _W,_O,_U,_L,_D,CLEAR,_Y,_O,_U,CLEAR,_L,_I,_K,_E,0x76,
- _T,_O,CLEAR,_S,_I,_M,_U,_L,_A,_T,_E,QM,CLEAR,INVERSE(_J),CLEAR,
- _F,_O,_R,CLEAR,_L,_E,_S,_S,COMMA,CLEAR,INVERSE(_K),CLEAR,
- _F,_O,_R,0x76,_M,_O,_R,_E,DOT,0x76,0x76,0x76,_G,_R,_I,_D,
- CLEAR,_S,_I,_Z,_E,CLEAR,_I,_S,COLON,0x76,_P,_R,_E,_S,_S,
- CLEAR,INVERSE(_N),CLEAR,_T,_O,CLEAR,_C,_H,_A,_N,_G,_E,CLEAR,
- _G,_R,_I,_D,CLEAR,_W,_I,_D,_T,_H,CLEAR,_A,_N,_D,0x76,
- INVERSE(_M),CLEAR,_T,_O,CLEAR,_C,_H,_A,_N,_G,_E,CLEAR,
- _G,_R,_I,_D,CLEAR,_H,_E,_I,_G,_H,_T,0x76,0x76,_P,_R,_E,_S,_S,
- CLEAR,INVERSE(_N),INVERSE(_E),INVERSE(_W),CLEAR,INVERSE(_L),
- INVERSE(_I),INVERSE(_N),INVERSE(_E),CLEAR,_W,_H,_E,_N,CLEAR,
- _D,_O,_N,_E,DOT,EOS
- };
- unsigned char stepNo[]=
- {
- _S,_T,_E,_P,CLEAR,_N,_U,_M,_B,_E,_R,COLON,CLEAR,EOS
- };
- unsigned char endGame[]=
- {
- _P,_R,_E,_S,_S,CLEAR,_A,_N,_Y,CLEAR,_K,_E,_Y,EOS
- };
- unsigned char playAgain[]=
- {
- _P,_R,_E,_S,_S,CLEAR,_Y,CLEAR,_T,_O,CLEAR,_P,_L,_A,_Y,
- CLEAR,_A,_G,_A,_I,_N,EOS
- };
- unsigned char grid[MAXWIDTH*MAXHEIGHT+1];
- ///
- void main()
- {
- signed short steps=0;
- unsigned char res = _N;
- unsigned char changeGrid = 0;
- zx_fast();
- printf("%c",12);
- srand(RAND_MAX);
- clearGrid();
- printat(SCRLOC(0,0));
- while(title[steps]!=EOS)
- {
- print(title[steps]);
- steps++;
- }
- steps=0;
- while(instructions[steps]!=EOS)
- {
- print(instructions[steps]);
- steps++;
- }
- steps = MINSTEPS;
- zx_slow();
- while((res=in_Inkey())!=13)
- {
- printat(SCRLOC(0,15));
- printNumber(steps);
- printat(SCRLOC(14,17));
- printNumber(x);
- print(_X);
- print(CLEAR);
- printNumber(y);
- if(res=='J' && steps>MINSTEPS)
- {
- steps--;
- }
- if(res=='K' && steps<MAXSTEPS)
- {
- steps++;
- }
- if(res=='N')
- {
- x++;
- }
- if(res=='M')
- {
- y++;
- }
- if(x>MAXWIDTH)
- {
- x=MINWIDTH;
- }
- if(y>MAXHEIGHT)
- {
- y=MINHEIGHT;
- }
- pause(254);
- }
- printf("%c",12);
- fillArray();
- for(c=0; c<steps;c++)
- {
- printArray(c+1);
- checkNeighbour();
- }
- steps=0;
- while(playAgain[steps]!=EOS)
- {
- print(INVERSE(playAgain[steps]));
- steps++;
- }
- while(!(res=in_Inkey()))
- {
- }
- if(res=='Y')
- {
- main();
- }
- pause(255);
- }
- /// Clears whole grid regardless of current size:
- void clearGrid()
- {
- for(i=0; i<MAXHEIGHT*MAXHEIGHT; i++)
- {
- grid[i]=CLEAR;
- }
- }
- /// Populates the current grid according to size:
- void fillArray()
- {
- unsigned short number=0;
- unsigned char random=0;
- //fill the array with random junk, from 0 to 1
- for(i=1;i<y-1;i++)
- {
- for(j=1;j<x-1;j++)
- {
- random=rand()%24;
- if(random==3 || random==(char)x/2 || random==(char)y/2 || random==14 || random==23)
- {
- grid[i*x+j]=ZERO;
- }
- else
- {
- grid[i*x+j]=CLEAR;
- }
- }
- }
- }
- /// Will output a number to the screen:
- void printNumber(signed short num)
- {
- signed short remainder=num%10;
- signed short checker=num;
- unsigned char tenth=0;
- unsigned char thous=0;
- unsigned char hundr=0;
- unsigned char tens=0;
- while(num>9999)
- {
- print(num/10000+ZERO);
- num=num%10000;
- tenth=1;
- }
- if(!(num%10000) && !tenth && checker!=num)
- {
- print(ZERO);
- }
- while(num>999)
- {
- print(num/1000+ZERO);
- num=num%1000;
- thous=1;
- }
- if((num%1000==00 || num/1000<=999) && !thous && checker!=num)
- {
- print(ZERO);
- }
- while(num>99)
- {
- print(num/100+ZERO);
- num=num%100;
- hundr=1;
- }
- if((num%100==0 || num/100<=99) && !hundr && checker!=num)
- {
- print(ZERO);
- }
- while(num>9)
- {
- print(num/10+ZERO);
- num=DIVBYTEN(num);
- tens=1;
- }
- if(num<=9 && num>=0 && !tens && checker!=num)
- {
- print(ZERO);
- }
- print(remainder+ZERO);
- print(CLEAR);
- }
- /// This will display the current grid:
- void printArray(signed short stepNumber)
- {
- unsigned short number=0;
- unsigned short sizeOfArray=x*y;
- printat(SCRLOC(0,0));
- while(stepNo[number]!=EOS)
- {
- print(stepNo[number]);
- number++;
- }
- printNumber(stepNumber);
- print(0x76);
- number=0;
- while(number<=sizeOfArray)
- {
- if(number%x==0 && number)
- {
- print(0x76);
- }
- print(grid[number]);
- number++;
- }
- }
- /// This will check each cell for neighbours:
- void checkNeighbour()
- {
- char cellHasNeighbour=0;
- for(i=1;i<y-1;i++)
- {
- for(j=1;j<x-1;j++)
- {
- cellHasNeighbour=0;
- if(grid[(i-1)*x+j])
- {
- cellHasNeighbour++;
- }
- if(grid[(i-1)*x+(j-1)])
- {
- cellHasNeighbour++;
- }
- if(grid[(i-1)*x+(j+1)])
- {
- cellHasNeighbour++;
- }
- if(grid[(i+1)*(x+j)])
- {
- cellHasNeighbour++;
- }
- if(grid[(i+1)*x+(j+1)])
- {
- cellHasNeighbour++;
- }
- if(grid[(i+1)*x+(j-1)])
- {
- cellHasNeighbour++;
- }
- if(grid[i*x+(j-1)])
- {
- cellHasNeighbour++;
- }
- if(grid[i*x+(j+1)])
- {
- cellHasNeighbour++;
- }
- if(grid[i*x+j]==ZERO && cellHasNeighbour!=3 && cellHasNeighbour!=2)
- {
- grid[i*x+j]=CLEAR;
- }
- if(grid[i*x+j]==CLEAR && cellHasNeighbour==3)
- {
- grid[i*x+j]=ZERO;
- }
- cellHasNeighbour=0;
- }
- }
- }
- /// Outputs character:
- void print(short ch)
- {
- #asm
- EXX
- LD HL,$0002
- ADD HL,SP
- LD A,(HL)
- RST PRINT
- EXX
- #endasm
- }
- /// Moves to cursor position:
- void printat(short xy)
- {
- #asm
- EXX
- LD HL,$0002
- ADD HL,SP
- LD B,(HL)
- INC L
- LD C,(HL)
- CALL PRINTAT
- EXX
- #endasm
- }
- /// Slight delay:
- void pause(char z)
- {
- while(z)
- {
- #asm
- NOP
- #endasm
- z--;
- }
- }
- // Compile with:
- // zcc +zx81 -startup=2 -create-app -DTEXT -o GOL gameOfLife.c
- // (C) 2013 Donkeysoft
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement