lnusp.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // lnusp.c
  2. // lnusp interpreter
  3. // by Marinus Oosters
  4. /* I assumed the following:
  5. * - Line format is three bytes which form a number, then one byte that is
  6. * ignored, then the program code, starting at index 1.
  7. * NNN?code.code.code.code.code.....
  8. * - Array offsets are one-based.
  9. * - The data space and program space are separate
  10. * - Anything that is not a command, is ignored.
  11. * - If the program pointer hits the north at one of the
  12. * special places (x=8, x=24, x=41) that subroutine will be
  13. * executed before the direction is reversed.
  14. * - If the program pointer exits the program space and no subroutine
  15. * is at that place, this is an error.
  16. *
  17. * Modified a bit by Graue.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. unsigned char memory[8000][8000];
  23. char prgm[8000][8000];
  24. typedef enum {n,ne,e,se,s,sw,w,nw} direction;
  25. typedef struct {int x; int y; direction d;} vector;
  26. vector next(vector vv) {
  27. vector v=vv;
  28. switch(v.d) {
  29. case n: v.y--; break;
  30. case ne: v.y--; v.x++; break;
  31. case e: v.x++; break;
  32. case se: v.y++; v.x++; break;
  33. case s: v.y++; break;
  34. case sw: v.y++; v.x--; break;
  35. case w: v.x--; break;
  36. case nw: v.y--; v.x--; break;
  37. }
  38. return v;
  39. }
  40. vector reverse(vector vv) {
  41. vector v=vv;
  42. switch(v.d) {
  43. case n: v.d=s; break;
  44. case ne: v.d=sw; break;
  45. case e: v.d=w; break;
  46. case se: v.d=nw; break;
  47. case s: v.d=n; break;
  48. case sw: v.d=ne; break;
  49. case w: v.d=e; break;
  50. case nw: v.d=se; break;
  51. }
  52. return v;
  53. }
  54. vector l45(vector v) { // 45 degrees left
  55. v.d = (v.d - 1) % 8;
  56. return v;
  57. }
  58. vector r45(vector v) { // 45 degrees right
  59. v.d = (v.d + 1) % 8;
  60. return v;
  61. }
  62. char getpvalue(vector v) { return prgm[v.y][v.x]; }
  63. unsigned char getvalue(vector v) { return memory[v.y][v.x]; }
  64. void setvalue(vector v,unsigned char c) { memory[v.y][v.x] = c; }
  65. vector mp, ip;
  66. int main (int argc, char **argv) {
  67. FILE *f;
  68. char line[8004], *l=line;
  69. char c;
  70. int i,y=1;
  71. vector saved;
  72. // zero memory
  73. bzero(memory,sizeof(memory));
  74. bzero(prgm,sizeof(prgm));
  75. if (argc != 2) {
  76. fprintf(stderr,"Usage: %s sourcefile\n", argv[0]);
  77. exit(1);
  78. }
  79. if (!(f=fopen(argv[1],"r"))) {
  80. fprintf(stderr,"Error: can't open %s\n", argv[1]);
  81. exit(1);
  82. }
  83. bzero(line,8004);
  84. while (!feof(f)) {
  85. c=fgetc(f);
  86. if (c=='\n') {
  87. *l=0; l=line;
  88. line[3] = 0; // 0,1,2 = number; 4 and onwards = code
  89. for (i=0;i<atoi(line);i++) {
  90. strcpy(&prgm[y++][1],&line[4]);
  91. }
  92. } else *(l++)=c;
  93. }
  94. // initialize
  95. mp.x = ip.x = 1; // 1-based
  96. mp.y = ip.y = 1;
  97. mp.d = ip.d = se; // starts going south-east
  98. saved.x=-1; // -1: nothing is saved
  99. // interpret
  100. while (1) {
  101. switch(getpvalue(ip)) {
  102. case '+': setvalue(mp,(getvalue(mp)+1)%256); break;
  103. case '*': mp.d = ip.d; mp = next(mp); break;
  104. case '?': if (getvalue(mp)) ip = l45(ip); break;
  105. case '!': if (!getvalue(mp)) ip = l45(ip); break;
  106. case '@': if (ip.d==n) ip = r45(ip);
  107. else if (saved.x==-1) {
  108. saved=ip;
  109. ip.d=n;
  110. } else {
  111. ip=saved;
  112. saved.x=-1;
  113. }
  114. break;
  115. }
  116. ip = next(ip);
  117. if (ip.x<1) {
  118. fprintf(stderr,"Instruction pointer left code area\n");
  119. exit(0);
  120. }
  121. if (ip.y<1) {
  122. switch(ip.x) {
  123. case 8: if (feof(stdin))
  124. setvalue(mp,0);
  125. else setvalue(mp,getchar());
  126. ip = reverse(ip);
  127. break;
  128. case 24: putchar(getvalue(mp));
  129. ip = reverse(ip);
  130. break;
  131. case 41: exit(0);
  132. default: fprintf(stderr,
  133. "Instruction pointer left code area.\n");
  134. exit(0);
  135. }
  136. }
  137. }
  138. return 0;
  139. }