Advertisement
Shaun_B

Game of Life v1.0.2a Sinclair ZX81 in C

Apr 30th, 2013
474
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.99 KB | None | 0 0
  1. /**
  2.  * This is a demonstration of the old Game of Life algorithm
  3.  * which was a popular programming experiment back in the late
  4.  * 1970s and early 1980s. The idea is that each simple cell can
  5.  * only live and multiply under certain circumstances, as stated
  6.  * on the opening screen of the programme.
  7.  *
  8.  * @Author:     Shaun B
  9.  * @Version:    1.0.2a - 2013-04-30
  10.  * @Todo:       Probably could do with speeding up, using ROM
  11.  *              to out the char and track the cursor, there is
  12.  *              definitely a quicker way, but it was written to
  13.  *              calculate off-sets of a flat array so it behaves
  14.  *              like a 2D array. Quality.
  15.  *
  16.  **/
  17.  
  18. /// Included libraries:
  19. #include <zx81.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <input.h>
  23.  
  24. /// Pre-processor symbols:
  25. #define INVERSE(A)  (0x80 | A)
  26. #define SCRLOC(X,Y) (X<<8 | Y)
  27. #define DIVBYTEN(Z) ((Z>>3) - (Z>>1))
  28. #define PRINTAT     0x08f5
  29. #define PRINT       0x10
  30. #define MAXWIDTH    32
  31. #define MAXHEIGHT   20
  32. #define WIDTH       16
  33. #define HEIGHT      16
  34. #define MAXSTEPS    32767
  35. #define MINSTEPS    12
  36. #define MINWIDTH    9
  37. #define MINHEIGHT   9
  38. // ZX81 character set:
  39. #define CLEAR       0x00
  40. #define TL          0x01
  41. #define TR          0x02
  42. #define TOP         0x03
  43. #define BL          0x04
  44. #define LEFT        0x05
  45. #define CHECKER     0x06
  46. #define CORNER      0x07
  47. #define CHESSB      0x08
  48. #define CHESSBOT    0x09
  49. #define CHESSTOP    0x0a
  50. #define QUOTE       0x0b
  51. #define POUND       0x0c
  52. #define DOLLAR      0x0d
  53. #define COLON       0x0e
  54. #define QM          0x0f
  55. #define OBRACKET    0x10
  56. #define CBRACKET    0x11
  57. #define GRT         0x12
  58. #define LST         0x13
  59. #define EQUALS      0x14
  60. #define PLUS        0x15
  61. #define DASH        0x16
  62. #define STAR        0x17
  63. #define SLASH       0x18
  64. #define SEMI        0x19
  65. #define COMMA       0x1a
  66. #define DOT         0x1b
  67. #define ZERO        0x1c
  68. #define ONE         0x1d
  69. #define TWO         0x1e
  70. #define THREE       0x1f
  71. #define FOUR        0x20
  72. #define FIVE        0x21
  73. #define SIX         0x22
  74. #define SEVEN       0x23
  75. #define EIGHT       0x24
  76. #define NINE        0x25
  77. #define _A          0x26
  78. #define _B          0x27
  79. #define _C          0x28
  80. #define _D          0x29
  81. #define _E          0x2a
  82. #define _F          0x2b
  83. #define _G          0x2c
  84. #define _H          0x2d
  85. #define _I          0x2e
  86. #define _J          0x2f
  87. #define _K          0x30
  88. #define _L          0x31
  89. #define _M          0x32
  90. #define _N          0x33
  91. #define _O          0x34
  92. #define _P          0x35
  93. #define _Q          0x36
  94. #define _R          0x37
  95. #define _S          0x38
  96. #define _T          0x39
  97. #define _U          0x3a
  98. #define _V          0x3b
  99. #define _W          0x3c
  100. #define _X          0x3d
  101. #define _Y          0x3e
  102. #define _Z          0x3f
  103. #define EOS         0x40
  104.  
  105. /// Function prototypes:
  106. static void main(void);
  107. static void clearGrid(void);
  108. static void fillArray(void);
  109. static void printNumber(signed short num);
  110. static void printArray(signed short stepNumber);
  111. static void checkNeighbour(void);
  112. static void setSize(void);
  113. static void print(short ch);
  114. static void printat(short xy);
  115. static void pause(char z);
  116.  
  117. /// Global variables:
  118. /// Global variables:
  119. unsigned char choice=0;
  120. unsigned char x=WIDTH;
  121. unsigned char y=HEIGHT;
  122. unsigned char i=0;
  123. unsigned char j=0;
  124. unsigned char c=0;
  125. unsigned char title[]=
  126. {
  127.     CLEAR,CLEAR,CLEAR,CLEAR,INVERSE(_G),INVERSE(_A),INVERSE(_M),
  128.     INVERSE(_E),CLEAR,INVERSE(_O),INVERSE(_F),CLEAR,INVERSE(_L),
  129.     INVERSE(_I),INVERSE(_F),INVERSE(_E),CLEAR,INVERSE(_V),
  130.     INVERSE(ONE),INVERSE(DOT),INVERSE(ZERO),INVERSE(DOT),
  131.     INVERSE(TWO),CLEAR,INVERSE(_Z),INVERSE(_X),INVERSE(EIGHT),
  132.     INVERSE(ONE),0x76,0x76,EOS
  133. };
  134. unsigned char instructions[]=
  135. {
  136.     _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
  137.     ONE,CLEAR,_O,_R,CLEAR,ZERO,0x76,
  138.     _N,_E,_I,_G,_H,_B,_O,_U,_R,_S,CLEAR,_D,_I,_E,_S,CLEAR,
  139.     _F,_R,_O,_M,CLEAR,_L,_O,_N,_E,_L,_I,_N,_E,_S,_S,0x76,
  140.     _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
  141.     _F,_O,_U,_R,CLEAR,_O,_R,CLEAR,_M,_O,_R,_E,0x76,
  142.     _N,_E,_I,_G,_H,_B,_O,_U,_R,_S,CLEAR,_D,_I,_E,_S,CLEAR,
  143.     _F,_R,_O,_M,CLEAR,_O,_V,_E,_R,DASH,0x76,
  144.     _P,_O,_P,_U,_L,_A,_T,_I,_O,_N,0x76,
  145.     _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
  146.     _T,_W,_O,CLEAR,_O,_R,CLEAR,_T,_H,_R,_E,_E,0x76,
  147.     _N,_E,_I,_G,_H,_B,_O,_U,_R,_S,CLEAR,_H,_A,_P,_P,_I,_L,_Y,
  148.     CLEAR,_C,_O,DASH,_E,_X,_I,_S,_T,_S,0x76,
  149.     _E,_A,_C,_H,CLEAR,_C,_E,_L,_L,CLEAR,_W,_I,_T,_H,CLEAR,
  150.     _T,_H,_R,_E,_E,CLEAR,_N,_E,_I,_G,_H,_B,_O,_U,_R,_S,0x76,
  151.     _W,_I,_L,_L,CLEAR,_M,_U,_L,_T,_I,_P,_L,_Y,0x76,0x76,
  152.     _H,_O,_W,CLEAR,_M,_A,_N,_Y,CLEAR,_S,_T,_E,_P,_S,CLEAR,
  153.     _W,_O,_U,_L,_D,CLEAR,_Y,_O,_U,CLEAR,_L,_I,_K,_E,0x76,
  154.     _T,_O,CLEAR,_S,_I,_M,_U,_L,_A,_T,_E,QM,CLEAR,INVERSE(_J),CLEAR,
  155.     _F,_O,_R,CLEAR,_L,_E,_S,_S,COMMA,CLEAR,INVERSE(_K),CLEAR,
  156.     _F,_O,_R,0x76,_M,_O,_R,_E,DOT,0x76,0x76,0x76,_G,_R,_I,_D,
  157.     CLEAR,_S,_I,_Z,_E,CLEAR,_I,_S,COLON,0x76,_P,_R,_E,_S,_S,
  158.     CLEAR,INVERSE(_N),CLEAR,_T,_O,CLEAR,_C,_H,_A,_N,_G,_E,CLEAR,
  159.     _G,_R,_I,_D,CLEAR,_W,_I,_D,_T,_H,CLEAR,_A,_N,_D,0x76,
  160.     INVERSE(_M),CLEAR,_T,_O,CLEAR,_C,_H,_A,_N,_G,_E,CLEAR,
  161.     _G,_R,_I,_D,CLEAR,_H,_E,_I,_G,_H,_T,0x76,0x76,_P,_R,_E,_S,_S,
  162.     CLEAR,INVERSE(_N),INVERSE(_E),INVERSE(_W),CLEAR,INVERSE(_L),
  163.     INVERSE(_I),INVERSE(_N),INVERSE(_E),CLEAR,_W,_H,_E,_N,CLEAR,
  164.     _D,_O,_N,_E,DOT,EOS
  165. };
  166. unsigned char stepNo[]=
  167. {
  168.     _S,_T,_E,_P,CLEAR,_N,_U,_M,_B,_E,_R,COLON,CLEAR,EOS
  169. };
  170. unsigned char endGame[]=
  171. {
  172.     _P,_R,_E,_S,_S,CLEAR,_A,_N,_Y,CLEAR,_K,_E,_Y,EOS
  173. };
  174. unsigned char playAgain[]=
  175. {
  176.     _P,_R,_E,_S,_S,CLEAR,_Y,CLEAR,_T,_O,CLEAR,_P,_L,_A,_Y,
  177.     CLEAR,_A,_G,_A,_I,_N,EOS
  178. };
  179. unsigned char grid[MAXWIDTH*MAXHEIGHT+1];
  180.  
  181. ///
  182. void main()
  183. {
  184.     signed short steps=0;
  185.     unsigned char res = _N;
  186.     unsigned char changeGrid = 0;
  187.     zx_fast();
  188.     printf("%c",12);
  189.     srand(RAND_MAX);
  190.     clearGrid();
  191.     printat(SCRLOC(0,0));
  192.     while(title[steps]!=EOS)
  193.     {
  194.         print(title[steps]);
  195.         steps++;
  196.     }
  197.     steps=0;
  198.     while(instructions[steps]!=EOS)
  199.     {
  200.         print(instructions[steps]);
  201.         steps++;
  202.     }
  203.     steps = MINSTEPS;
  204.     zx_slow();
  205.     while((res=in_Inkey())!=13)
  206.     {
  207.         printat(SCRLOC(0,15));
  208.         printNumber(steps);
  209.         printat(SCRLOC(14,17));
  210.         printNumber(x);
  211.         print(_X);
  212.         print(CLEAR);
  213.         printNumber(y);
  214.         if(res=='J' && steps>MINSTEPS)
  215.         {
  216.             steps--;
  217.         }
  218.         if(res=='K' && steps<MAXSTEPS)
  219.         {
  220.             steps++;
  221.         }
  222.         if(res=='N')
  223.         {
  224.             x++;
  225.         }
  226.         if(res=='M')
  227.         {
  228.             y++;
  229.         }
  230.         if(x>MAXWIDTH)
  231.         {
  232.             x=MINWIDTH;
  233.         }
  234.         if(y>MAXHEIGHT)
  235.         {
  236.             y=MINHEIGHT;
  237.         }
  238.         pause(254);
  239.     }
  240.     printf("%c",12);
  241.     fillArray();
  242.     for(c=0; c<steps;c++)
  243.     {
  244.         printArray(c+1);
  245.         checkNeighbour();
  246.     }
  247.     steps=0;
  248.     while(playAgain[steps]!=EOS)
  249.     {
  250.         print(INVERSE(playAgain[steps]));
  251.         steps++;
  252.     }
  253.     while(!(res=in_Inkey()))
  254.     {
  255.     }
  256.     if(res=='Y')
  257.     {
  258.         main();
  259.     }
  260.     pause(255);
  261. }
  262.  
  263. /// Clears whole grid regardless of current size:
  264. void clearGrid()
  265. {
  266.     for(i=0; i<MAXHEIGHT*MAXHEIGHT; i++)
  267.     {
  268.         grid[i]=CLEAR;
  269.     }
  270. }
  271.  
  272. /// Populates the current grid according to size:
  273. void fillArray()
  274. {
  275.     unsigned short number=0;
  276.     unsigned char random=0;
  277.     //fill the array with random junk, from 0 to 1
  278.     for(i=1;i<y-1;i++)
  279.     {
  280.         for(j=1;j<x-1;j++)
  281.         {
  282.             random=rand()%24;
  283.             if(random==3 || random==(char)x/2 || random==(char)y/2 || random==14 || random==23)
  284.             {
  285.                 grid[i*x+j]=ZERO;
  286.             }
  287.             else
  288.             {
  289.                 grid[i*x+j]=CLEAR;
  290.             }
  291.         }
  292.     }
  293. }
  294.  
  295. /// Will output a number to the screen:
  296. void printNumber(signed short num)
  297. {
  298.     signed short remainder=num%10;
  299.     signed short checker=num;
  300.     unsigned char tenth=0;
  301.     unsigned char thous=0;
  302.     unsigned char hundr=0;
  303.     unsigned char tens=0;
  304.     while(num>9999)
  305.     {
  306.         print(num/10000+ZERO);
  307.         num=num%10000;
  308.         tenth=1;
  309.     }
  310.     if(!(num%10000) && !tenth && checker!=num)
  311.     {
  312.         print(ZERO);
  313.     }
  314.     while(num>999)
  315.     {
  316.         print(num/1000+ZERO);
  317.         num=num%1000;
  318.         thous=1;
  319.     }
  320.     if((num%1000==00 || num/1000<=999) && !thous && checker!=num)
  321.     {
  322.         print(ZERO);
  323.     }
  324.     while(num>99)
  325.     {
  326.         print(num/100+ZERO);
  327.         num=num%100;
  328.         hundr=1;
  329.     }
  330.     if((num%100==0 || num/100<=99) && !hundr && checker!=num)
  331.     {
  332.         print(ZERO);
  333.     }
  334.     while(num>9)
  335.     {
  336.         print(num/10+ZERO);
  337.         num=DIVBYTEN(num);
  338.         tens=1;
  339.     }
  340.     if(num<=9 && num>=0 && !tens && checker!=num)
  341.     {
  342.         print(ZERO);
  343.     }
  344.     print(remainder+ZERO);
  345.     print(CLEAR);
  346. }
  347.  
  348. /// This will display the current grid:
  349. void printArray(signed short stepNumber)
  350. {
  351.     unsigned short number=0;
  352.     unsigned short sizeOfArray=x*y;
  353.     printat(SCRLOC(0,0));
  354.     while(stepNo[number]!=EOS)
  355.     {
  356.         print(stepNo[number]);
  357.         number++;
  358.     }
  359.     printNumber(stepNumber);
  360.     print(0x76);
  361.     number=0;
  362.     while(number<=sizeOfArray)
  363.     {
  364.         if(number%x==0 && number)
  365.         {
  366.             print(0x76);
  367.         }
  368.         print(grid[number]);
  369.         number++;
  370.     }
  371. }
  372.  
  373. /// This will check each cell for neighbours:
  374. void checkNeighbour()
  375. {
  376.     char cellHasNeighbour=0;
  377.     for(i=1;i<y-1;i++)
  378.     {
  379.         for(j=1;j<x-1;j++)
  380.         {
  381.             cellHasNeighbour=0;
  382.             if(grid[(i-1)*x+j])
  383.             {
  384.                 cellHasNeighbour++;
  385.             }
  386.             if(grid[(i-1)*x+(j-1)])
  387.             {
  388.                 cellHasNeighbour++;
  389.             }
  390.             if(grid[(i-1)*x+(j+1)])
  391.             {
  392.                 cellHasNeighbour++;
  393.             }
  394.             if(grid[(i+1)*(x+j)])
  395.             {
  396.                 cellHasNeighbour++;
  397.             }
  398.             if(grid[(i+1)*x+(j+1)])
  399.             {
  400.                 cellHasNeighbour++;
  401.             }
  402.             if(grid[(i+1)*x+(j-1)])
  403.             {
  404.                 cellHasNeighbour++;
  405.             }
  406.             if(grid[i*x+(j-1)])
  407.             {
  408.                 cellHasNeighbour++;
  409.             }
  410.             if(grid[i*x+(j+1)])
  411.             {
  412.                 cellHasNeighbour++;
  413.             }
  414.             if(grid[i*x+j]==ZERO && cellHasNeighbour!=3 && cellHasNeighbour!=2)
  415.             {
  416.                 grid[i*x+j]=CLEAR;
  417.             }
  418.             if(grid[i*x+j]==CLEAR && cellHasNeighbour==3)
  419.             {
  420.                 grid[i*x+j]=ZERO;
  421.             }
  422.             cellHasNeighbour=0;
  423.         }
  424.     }
  425. }
  426.  
  427. /// Outputs character:
  428. void print(short ch)
  429. {
  430.     #asm
  431.     EXX
  432.     LD      HL,$0002
  433.     ADD     HL,SP
  434.     LD      A,(HL)
  435.     RST     PRINT
  436.     EXX
  437.     #endasm
  438. }
  439.  
  440. /// Moves to cursor position:
  441. void printat(short xy)
  442. {
  443.     #asm
  444.     EXX
  445.     LD      HL,$0002
  446.     ADD     HL,SP
  447.     LD      B,(HL)
  448.     INC     L
  449.     LD      C,(HL)
  450.     CALL    PRINTAT
  451.     EXX
  452.     #endasm
  453. }
  454.  
  455. /// Slight delay:
  456. void pause(char z)
  457. {
  458.     while(z)
  459.     {
  460.         #asm
  461.         NOP
  462.         #endasm
  463.         z--;
  464.     }
  465. }
  466.  
  467. // Compile with:
  468. // zcc +zx81 -startup=2 -create-app -DTEXT -o GOL gameOfLife.c
  469. // (C) 2013 Donkeysoft
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement