Initial import of Wierd distribution version 1.0 revision 2004.0302.
Cat's Eye Technologies
12 years ago
0 | There are two versions of this program: | |
1 | asciiadd.w: reads two characters, adds their ASCII values, and prints them out | |
2 | add.w: like above, but treats 0 as origin, so 1+2 is 3 rather than c | |
3 | ||
4 | Note that add.w uses the 0 in the top-left corner (which is operationally | |
5 | equivalent to the star used elsewhere) for the origin. This character can be | |
6 | changed to an arbitrary one, but 0 has been chosen because it gives the most | |
7 | intuitive effect. | |
8 | ||
9 | See cat.doc for general Wierd notes. |
0 | There are several versions of this program: | |
1 | cat1.w: reads one character and write it out, no check for EOF | |
2 | cat2.w: pumps input to output, no check for EOF (makes use of the fact that | |
3 | "conditionals" without any stack just continue going, although it | |
4 | would be more logical to terminate the program with an error message) | |
5 | cat3.w: reads one character, and if it isn't EOF, dump it out again | |
6 | cat4.w: pumps input to output until EOF is reached | |
7 | ||
8 | Versions 3 and 4 implicitly assume that EOF is -1. Due to how hard it is to | |
9 | change a Wierd program once it has been wired, I, with this very sentence, | |
10 | define that Wierd programs will see EOF as -1, even on computers that normally | |
11 | use a different method. | |
12 | ||
13 | Versions 3 and 4 make use of the getput operator, which selects which | |
14 | operatation to perform opposite from the specifications. Since neither I nor | |
15 | anybody else (like the writer of hello.w) wishes to change our programs, I | |
16 | recommend leaving the interpreter alone and changing the specifications. Also, | |
17 | the angles work the opposite way (the first example in the specifications is | |
18 | treated by the interpreter as 315 degrees). Again, I recommend changing the | |
19 | specifications. | |
20 | ||
21 | The only true use of conditionals is in the EOF test candle (or if you prefer, | |
22 | dynamite) of versions 3 and 4, although fake ones appear in versions 2 and 4 | |
23 | with the top-of-stack known to be zero just to turn the execution around. | |
24 | ||
25 | It is also interesting to note that the loop to continue reading after the | |
26 | first character seems like a big change but takes barely any space (although it | |
27 | does cheat by temporarily creating a new thread which soon dies out), while | |
28 | testing for EOF seems like a small change (after all, only one out of 256 input | |
29 | characters will be affected) but takes a very long wire, primarily because the | |
30 | input character is needed twice - once to test for EOF, once to print it out - | |
31 | and since there is no stack-duplication operator (not that there is any room | |
32 | for it, though gap-sparking could be made to have a side effect) and so I must | |
33 | simulate it by putting the character in (1,1) (those coordinates have been | |
34 | chosen because they are the easiest to push on the stack), then getting it | |
35 | twice. | |
36 | ||
37 | In cat4.w, the doomed thread (the one which appears when, quite literally, | |
38 | looping, and soon vanishes again) might stumble across this character, but | |
39 | Wierd has been designed in such a way that this can, at the worst, kill the | |
40 | thread off one cycle earlier. This proves that it is more robust than normal | |
41 | languages. In fact, the ONLY error condition possible in Wierd is if the | |
42 | lop-left character is a space (although, as stated above, errors SHOULD also | |
43 | appear for insufficient stack), and therefore Wierd is useful to teach | |
44 | beginning programmers without getting them frustated about pages full of error | |
45 | messages. Now if you're talking about bugs that aren't caught by the language | |
46 | but just have the wrong effect, THOSE are easy. | |
47 | ||
48 | But although cat4.w is large, it's not a bad as hello.w. One starts | |
49 | understanding why many programs use external data files. They not only | |
50 | increases modifiability (for example, the program does not have to be changed | |
51 | if you choose to use a different languange for the output), but also | |
52 | significantly decrease program size. | |
53 | ||
54 | This gap jumping is annoying. I never yet ran into any need for it (if there | |
55 | is nothing around that the program can go to instead, why not just fill the gap | |
56 | with stars?), but sometimes the interpreter tries to gap jump when I want it to | |
57 | kill the thread (which forces me to make the program LARGER to add space so no | |
58 | gap jump occurs, which is the opposite of what it was meant to do), and worse, | |
59 | I cannot see how it chooses when and where to jump. I recommend that the whole | |
60 | misfeature be removed. By the way, according the the manual, "programs beyond | |
61 | a certain complexity might simply be impossible to write, and would at least be | |
62 | extremely impractical". If they are impossible, gap jumping will not help (see | |
63 | above question). If practicality is an issue, I should be programming C, not | |
64 | Wierd. | |
65 | ||
66 | A more severe problem is that check-for-zero is the only available conditional. | |
67 | This means that if a program wants to check, for exameple, if the top of the | |
68 | stack is less than zero, then all 32768 options must be scanned. Changing this | |
69 | would imply having to change existing programs, but the problem is severe | |
70 | enough that this is a necessary evil. The earlier, the better (before even | |
71 | more programs use the outdated version). | |
72 | ||
73 | Although I do not do so myself, it is possible to include in-program comments | |
74 | by including text in the program, either as the wire (with underscores | |
75 | replacing spaces) or at a nonreachable distance from the program. | |
76 | ||
77 | Finally, Wierd programs (or rather wires) are a good example of what sould NOT | |
78 | be made with a text editor or anything remotely similar to it. In fact, it | |
79 | requires a special "wire editor" which can, as one of its basic operations, | |
80 | stretch wires, taking any knotted wires along, and as another, cutting off | |
81 | wires for later use and then place them again in a possibly rotated form. It | |
82 | is also useful if it would draw the angles next to the turns. Sometime in the | |
83 | future, when I have a lot of free time and feel excessively insane, I might try | |
84 | it. Don't hold your breath, though. |
0 | This program prints sequential ASCII characters, starting with the character in | |
1 | (1,1) and ending with the character in (2,2). Currently, it starts with 0 and | |
2 | ends with 9, so it counts through all digits. A not-so-well-formatted table of | |
3 | all printable ASCII characters may be obtained by starting with ! and ending | |
4 | with ~. The former ascii.w (not by me) also tries to print non-printable | |
5 | characters, and doesn't automatically stop (beep beep beep beep beep beep beep | |
6 | beep beep beep beep beep beep ad nauseum), so my version is fully superior. | |
7 | Space may not be used as endpoint (because the endpoints must be parsed as code | |
8 | once), but it may appear as intermediate value. | |
9 | ||
10 | The basic operation is: | |
11 | 0. Get the current character and place it on the stack. | |
12 | 1. Write the top-of-stack (the current character) to the terminal. | |
13 | 2. Get the current character, which was lost from the stack in step 1, again. | |
14 | 3. Get the termination character and place it on the stack. | |
15 | 4. Subtract the two values on the stack. | |
16 | 5. If the result of step 4 was zero (the last character has just been printed), | |
17 | quit the program. Otherwise, continue to step 6. | |
18 | 6. The stack is, once again, empty, so push the current character. | |
19 | 7. Increment the top of stack by dancing "left, left, right, left, right, | |
20 | right", where all turns are 45 degrees. | |
21 | 8. Put the top of stack in the current character position. | |
22 | 9. With the stack empty again, go back to step 0 and repeat the whole process. | |
23 | ||
24 | The wire has many crossings, although all but one are harmless "bridges" which | |
25 | do not change direction and just shrink the wire a bit by avoiding padding. | |
26 | ||
27 | To do: write a newline when done (this is not as easy in Wierd as it sounds, | |
28 | because a newline cannot be entered as starting element for a cell), ask the | |
29 | user to enter the start and end characters (inputting and remembering is not | |
30 | that hard, but the nature of Wierd is such that adding anything at the | |
31 | beginning requires a lot of work to get the rest right, see notes in cat.doc | |
32 | about a Wierd editor). | |
33 | ||
34 | See cat.doc for general language notes. In contrast to what is said there, | |
35 | this wire does have comments. Not many, but the important actions are probably | |
36 | somewhere near where the comments say they are. |
0 | This is not a full program (although it can be run as such), but rather a | |
1 | reusable subroutine. Therefore, input is taken directly from memory, and output | |
2 | is stored back in memory and on the stack. There is no user interaction. | |
3 | ||
4 | Input: Numerator in (1,1) | |
5 | Denominator is hard-coded 2 | |
6 | Output: Quotient in (1,1) | |
7 | Remainder pushed on the stack | |
8 | Nothing else cluttered | |
9 | ||
10 | The algorithm takes O(numerator) time. There might exist a faster algorithm but | |
11 | I don't know it. |
0 | Just to illustrate exactly how sick I am, this took about three hours, | |
1 | most of which was fidgeting with the editor to make the geometry work. | |
2 | ||
3 | OK, I cheated a bit by: | |
4 | -- putting the text in the program | |
5 | -- using the fact that functions with an empty stack are | |
6 | essentially nops | |
7 | And I didn't use anything nifty--no multithreading, genuine conditionals, | |
8 | or anything of the like. Just brute force. I did, however, when I was | |
9 | running out of space, "put" the coordinates in memory so I could just | |
10 | "get" them later. | |
11 | ||
12 | Anyway, I found at least one not-quite-as-advertised "feature" in the | |
13 | interpreter. The main one is that a zero on top of the stack does a put | |
14 | of put and get, instead of the expected get, and a non-zero does get | |
15 | instead of put. Since I was doing more getting than putting in the | |
16 | program, I was actually kind of happy, but that means the spec and my | |
17 | comments are wrong (unless you *really* want to declare the least-trivial | |
18 | piece of Wierd code written to date *and* the only currently implemented | |
19 | interpreter non-standard...). The others are really obscure things that I | |
20 | can't figure out how to fix (the gap-jumping doesn't seem to quite work as | |
21 | I understand it). | |
22 | ||
23 | Well, I could probably strip out another couple of bytes here and there, | |
24 | but I just don't have the stomach for it today... | |
25 | ||
26 | Oh, Ben: If you're going to try a 99-Bottles program, I'd suggest | |
27 | expanding the playing field, since this program clocked in at just under | |
28 | 128x128... | |
29 | ||
30 | Now I'm going to bang my head against a softer object for a while so I | |
31 | don't notice the pain... | |
32 | ||
33 | --John | |
34 | ||
35 | P.S. Anybody besides me see the portrait of George Washington in the | |
36 | program? No? I must be hallucinating, then...Oh, well... |
0 | loop1.w is an infinite loop, which I have tried to write with minimal size (with | |
1 | the restraints that any garbage put on the stack must be taken off again, but | |
2 | that no popping intructions may be performed when there is still data on the | |
3 | stack). It seems at first that the first row and column can be ommited, but | |
4 | this doesn't work, and I suspect broken gap jumping to be the cause. | |
5 | ||
6 | loop2.w is also an infinite loop, but with the extra restraint that no threads | |
7 | may be started. Notice how the horizontal line at the bottom can be entered by | |
8 | two parallel paths. The leftmost path is used the first time, afterwards the | |
9 | rightmost path is used. Both have the same angle, therefore the same effect. | |
10 | ||
11 | For more information on this broken gap jumping, and the language in general, | |
12 | see cat.doc. |
0 | This program takes the number at (1,1) (input as the ASCII code of a character) | |
1 | and prints it in binary (I would do decimal but that would require a divide by | |
2 | ten subroutine), using the halving subroutine in half.w. Since it takes the | |
3 | number direct;y from memory, this proram is not quite suitable for the end-user, | |
4 | but rather it can be used as a subroutine in a yet larger program. | |
5 | ||
6 | The algorithm takes O(n) time, most of which is spent in the halving subroutine. |
0 | Note: coordinates (x,y) here mean that y is the higher-on-stack (the row) and x | |
1 | is below it (the column). The "stack" position is, of course, for purposes of | |
2 | getput. | |
3 | ||
4 | (1,1) holds the end-of-line character. | |
5 | (1,2) holds the current x coordinate. | |
6 | (2,1) holds the current y coordinate. | |
7 | (2,2) holds the beginnning-of-last-line-of-file character. | |
8 | ||
9 | This program is literally spaghetti code. It basically works by getting itself | |
10 | with 135 degree turns, but it uses a few kludges to work around the data in the | |
11 | top-left. Warning: trying to read the code may cause significant loss of | |
12 | sanity. Oh wait a moment, you didn't have any in the first place. Ok, go | |
13 | ahead, read the code, but don't blame me. | |
14 | ||
15 | Algorithm: | |
16 | 1. Get (1,1) and output (the first line must consist of just one character). | |
17 | 2. Push '\n'=10 (with "left, left, left, right, left, right, left, right, | |
18 | left, right, left, right, left, right, left, right, left, right, left, | |
19 | right, left, right, right") and output. | |
20 | 3. Put 3 in (2,1). | |
21 | 4. Put 1 in (1,2). | |
22 | 5. Get (1,3), which was equal to (2,1) at startup, and output. | |
23 | 6. Get (2,2) and output (the second line may have only have two characters). | |
24 | 7. Push '\n'=10 again (I didn't save it in step 2) and output. | |
25 | 8. Get (1,2). | |
26 | 9. Get (2,1). | |
27 | 10. Get the character specified by the two coordinates at the top of the stack. | |
28 | 11. Output it. | |
29 | 12. Get ((1,2),(2,1)) again. | |
30 | 13. Get (1,1) and compare. | |
31 | 14. If equal, go to step 19, otherwise continue with step 15. | |
32 | 15. Get (1,2). | |
33 | 16. Increment. | |
34 | 17. Put it back. | |
35 | 18. Return to step 8 and repeat the whole process. | |
36 | 19. This is a no-op step to remind you that you can only get here from the | |
37 | conditional in step 14, not from step 18. | |
38 | 20. Put 1 in (1,2). | |
39 | 21. Push '\n'=10 (yes, I should save it somewhere, but place is limited, | |
40 | particularly in this quine where special locations need special treatment) | |
41 | and output. | |
42 | 22. Get (1,(2,1)). Note that this is the first character of the just-finished | |
43 | line. | |
44 | 23. Get (2,2) and compare. | |
45 | 24. If equal, quit the program. If unequal, continue to step 25. | |
46 | 25. Get (2,1). | |
47 | 26. Increment. | |
48 | 27. Put it back. | |
49 | 28. Return to step 8. | |
50 | And that's making it sound simpler than it really is. | |
51 | ||
52 | As it happens, the Wierd logo is 42 characters wide. Also, the asterisk, which | |
53 | is the traditional wire character (although it is not treated specially by the | |
54 | computer), has ASCII code 42. Is Wierd the answer to life, the universe, and | |
55 | everything (or to anything, for that matter)? |
0 | Special data: | |
1 | (1,1): The number so far (starts at 0). | |
2 | (2,2): The negative of the bit to be set (starts at -1). | |
3 | ||
4 | (2,2) is doubled each time, and tested for zero. This is an overflow trick that | |
5 | only works on binary computers, and if Wierd is ever ported to ternary | |
6 | computers, this program will run indefinitely or at least much longer than it | |
7 | should. | |
8 | ||
9 | In detail: | |
10 | 1. Put 0 in (1,1). | |
11 | 2. Put -1 in (2,2). | |
12 | 3. Get (2,2). | |
13 | 4. Push zero (dance "left left right") and subtract. This is necessary because | |
14 | a condition can only follow a 45 or 315 turn (there needs to be space for | |
15 | turning back). Following a 45 turn is quite useless though... | |
16 | 5. Test. If zero, go to step 17. Otherwise, continue to step 6. | |
17 | 6. Use a 45/315 split to randomly chose whether or not the bit is to be | |
18 | included in the number. Depending on the result, either continue to step 7 | |
19 | or jump to step 11. | |
20 | 7. Get (1,1). | |
21 | 8. Get (2,2). | |
22 | 9. Subtract (see why (2,2) is negated now?). | |
23 | 10. Put the result back in (1,1). | |
24 | 11. Get (2,2). | |
25 | 12. Push a zero through the "left left right" dance. | |
26 | 13. Get (2,2) again. | |
27 | 14. Subtract twice. | |
28 | 15. Put the result in (2,2). | |
29 | 16. Go back to step 3. | |
30 | 17. Get (3,3) and put in (2,2) (for output subroutine). | |
31 | 18. Output as a binary number, using output.w. | |
32 | 19. Done! | |
33 | ||
34 | Since the output routine is O(n), you should modify the interpreter to use a | |
35 | smaller data type (short or even char) if you want the program to terminate this | |
36 | year. Of course, since outputted number is random, you just might be lucky and | |
37 | get a very small number which can be printed in less than a second. The random | |
38 | number generation itself is quite fast. |
0 | Specification for the Wierd Programming Language--A MicroFunge | |
1 | ||
2 | First, a Riddle: | |
3 | Q: What do you get when you put three marginally-sane programmers on a | |
4 | mailing list with the Befunge and BrainF*** programming languages? | |
5 | A: You get BeF***, and then they get Wierd. | |
6 | No, it's not really funny unless you already know what we're talking | |
7 | about. So let's get you up to speed. | |
8 | ||
9 | History: | |
10 | The now-defunct Befunge Mailing List once questioned if Befunge was too | |
11 | "top-heavy" a language--that is, if its instruction set was needlessly | |
12 | large. This, as one might expect (especially one reading this | |
13 | specification), quickly degenerated into an argument of "my language is | |
14 | smaller than yours." Ben Olmstead managed to trim down Befunge to a | |
15 | lean seven instructions, dubbing the creation "BeF***". | |
16 | Not to be outdone, it was quickly suggested by John Colagioia that | |
17 | instructions, per se, be eliminated in favor of the "visual programming" | |
18 | aspect of Befunge: The angles made by sequences of instructions. Such | |
19 | a language, of course, would have a single "instruction" from the | |
20 | syntactic standpoint, although it surely cheats by horribly abusing | |
21 | the concept of Euclidean geometry. | |
22 | Chris Pressey then jumped on it, created the angle-to-instruction | |
23 | mapping, and christened the entire mess "Wierd"--a cross between the | |
24 | words "weird" (which the language seemed to be) and "wired" (which | |
25 | would describe the appearance of programs written in the language). | |
26 | ||
27 | The Basics: | |
28 | Wierd, like Befunge, is a two-dimensional language with a rectalinear | |
29 | grid of instructions which manipulate a system stack area. Where | |
30 | Befunge has discrete, textual instructions, however, Wierd has a more | |
31 | implicit instruction set, each instruction denoted, not by a symbol, but | |
32 | by a configuration of symbols relative to the current direction of the | |
33 | instruction pointer: the angle of deviation from "straight ahead" from | |
34 | the IP's perpsective. That is, reading from left to right, the | |
35 | following program contains a single instruction: | |
36 | ****** | |
37 | * | |
38 | * | |
39 | * | |
40 | and the instruction is "read" as a 45-degree angle to the right. | |
41 | ||
42 | The Details: | |
43 | A Wierd source file can be any file, as the language only distinguishes | |
44 | between two symbols: Whitespace and everything else. A chain of non- | |
45 | whitespace symbols makes a Wierd program. | |
46 | Execution begins with the first character of the file (typically | |
47 | considered to be the "upper left" of the program), and the initial | |
48 | direction of the Instruction Pointer is down and to the right. This was | |
49 | chosen to allow the programmer to get away from the corner as | |
50 | efficiently as possible, which reduces the risk of the program becoming | |
51 | trapped. | |
52 | Newlines are defined in a system-dependant manner, though it can be | |
53 | safely assumed on most systems that a carriage return and/or line feed | |
54 | character delineates the end of each line and begins the next. | |
55 | Execution then passes from character to character, in the specified | |
56 | direction until a turn needs to be made. | |
57 | ||
58 | Inertia: | |
59 | Like water, the Wierd IP takes the path of least resistance when | |
60 | confronted with a choice. If the Wierd program branches, the IP will | |
61 | always choose the path which is closest to the direction it is already | |
62 | travelling. Therefore, the following code (assuming the IP starts at | |
63 | the left, and travels to the right, like the above): | |
64 | *********** | |
65 | * | |
66 | * | |
67 | * | |
68 | will stay on the top line, and never travel down the branch shown. | |
69 | Should the IP be faced with two equally-likely choices, the branch | |
70 | chosen by the interpreter is undefined, except for one condition which | |
71 | will be treated later. | |
72 | ||
73 | (Though, as an implementation note, it should be pointed out that the | |
74 | only existing interpreter at this time chooses the left-hand path. | |
75 | Note that Wierd was not intended to be left-handed, specifically; this | |
76 | is just how the coin showed during the design phase--literally). | |
77 | ||
78 | Gap-Jumping: | |
79 | While the above is suitable for a fully-featured programming language, | |
80 | it was quickly realized that programmers could easily (possibly | |
81 | certainly) "paint themselves into a corner," where programs beyond a | |
82 | certain complexity might simply be impossible to write, and would at | |
83 | least be extremely impractical. | |
84 | Therefore, in keeping with the pseudo-electronic motif, the Instruction | |
85 | Pointer was given the ability to launch itself over a limited distance | |
86 | of unused ("empty") programspace to attach to a new program segment. | |
87 | This jumping, to keep it only used in emergency situations, is only | |
88 | usable over a maximum distance of two cells in the program grid. | |
89 | Gap-Jumping follows the same rules as typical movement, regarding | |
90 | Inertia. That is, the IP will choose paths to jump into by how much of | |
91 | a change of direction is required to reach it. | |
92 | Note that jumping a gap into an isolated instruction, like in the | |
93 | following code segment: | |
94 | ***** * | |
95 | is considered an error. | |
96 | ||
97 | The Instructions: | |
98 | The Wierd instruction set is based on that of Befunge, though reduced to | |
99 | a nearly-absurd minimalism, and with a certain amount of "stack abuse," | |
100 | in addition to the abuses already heaped upon the program's geometry. | |
101 | While the People for the Ethical Treatment of Data Structures threatened | |
102 | to protest, they quickly realized that their acronym was not easily | |
103 | pronounced, and retreated to debate the merits of a new name before | |
104 | further business could be discussed. | |
105 | The instructions, listed by angle, are: | |
106 | 0 degrees NO: No operation, continue as normal. | |
107 | 45 degrees P1: Push a data value of 1 onto the stack. | |
108 | 90 degrees IF: Pop the stack. If the value is zero, continue | |
109 | executing as normal. If the value is nonzero, | |
110 | however, reverse direction. | |
111 | 135 degrees GP: Pop the stack. If the value is zero, pops the next | |
112 | two items from the stack, retrieves (gets) the | |
113 | value stored at the coordinates specified by these | |
114 | values (x, then y), and push it onto the stack. If | |
115 | the first value was nonzero, however, takes the | |
116 | value stored below the coordinates on the stack, | |
117 | and stores (puts) it at the coordinates. | |
118 | 180 degrees QU: Jump the gap, if possible. Otherwise, terminate. | |
119 | 225 degrees IO: Pop the stack. If the value is zero, read a | |
120 | character from input, pushing it onto the stack. | |
121 | If the value was nonzero, pop the stack, and print | |
122 | the value to output as a character. | |
123 | 270 degrees IF: See 90 degrees. Included for flexibility. | |
124 | 315 degrees SB: Subtract the top of the stack from the value | |
125 | beneath it, popping both values, and pushing the | |
126 | result. | |
127 | Note that pushing a 1 is the only form of direct data specification | |
128 | available to the programmer, and subtraction is the only available | |
129 | arithmetic operation. | |
130 | ||
131 | Concurrency: | |
132 | The exception mentioned above to the "always choose a single path" rule | |
133 | is when the two likeliest paths are at angles of both 90 and 270 | |
134 | degrees--both forms of conditional. In such a case, rather than | |
135 | choosing one or the other, both paths are chosen, and the IP is cloned | |
136 | (including stack) to cover the other path. | |
137 |
0 | 0 ****** | |
1 | * * * | |
2 | * * * | |
3 | * * * | |
4 | ************* * | |
5 | * | |
6 | ****** * | |
7 | * * * | |
8 | * * * | |
9 | * * * | |
10 | ***** * * | |
11 | * * * | |
12 | * * * | |
13 | * * * | |
14 | * * * | |
15 | * * * | |
16 | * * * | |
17 | * * * | |
18 | **** * * | |
19 | * * * | |
20 | * * * | |
21 | * * **** | |
22 | * * * | |
23 | * * | |
24 | * * | |
25 | ********* | |
26 |
0 | * ***************** | |
1 | * * * | |
2 | * * ** * | |
3 | * * * * * | |
4 | * * * * * | |
5 | * * * * * | |
6 | * * * * * | |
7 | * * * * * | |
8 | * * *************** | |
9 | * * * | |
10 | * * * | |
11 | * * * | |
12 | * * * | |
13 | * ********** * | |
14 | * * * * *********** * | |
15 | * * * * * * * * | |
16 | * * ** * * * ****** * ** | |
17 | * * * * ** * * * * ** | |
18 | * *** ** * ** * * * | |
19 | * * * * * * * | |
20 | * * * * * * | |
21 | * **** ***** * * | |
22 | ** * * | |
23 | **** |
0 | * ****** | |
1 | * * * | |
2 | * * * | |
3 | * * * | |
4 | ************* * | |
5 | * | |
6 | * | |
7 | ************** | |
8 | * * | |
9 | * * | |
10 | * * | |
11 | * * | |
12 | * * | |
13 | * * | |
14 | * * | |
15 | * * | |
16 | * * | |
17 | * * | |
18 | * * | |
19 | * * | |
20 | * * | |
21 | * **** | |
22 | * * | |
23 | * * | |
24 | * * | |
25 | ********* | |
26 |
0 | * ****** * | |
1 | * * * * * | |
2 | * * * * * | |
3 | ********** * * * | |
4 | * ** * | |
5 | * * * | |
6 | * * * | |
7 | * * * | |
8 | * * * | |
9 | * * * | |
10 | * * * | |
11 | * * * | |
12 | ******************************************** | |
13 | * * * * | |
14 | * * * * | |
15 | * * * * | |
16 | * * * * | |
17 | * * * * | |
18 | * * * * | |
19 | * * * * | |
20 | * * * * | |
21 | * * * * | |
22 | **************** * * * | |
23 | * * * * * * | |
24 | * * * * * * | |
25 | * * * * * ***** | |
26 | * * **** * * * | |
27 | * * * * * * | |
28 | * * * * * | |
29 | * **** * * * | |
30 | * * * * | |
31 | * * * * | |
32 | * * ************************ | |
33 | * * | |
34 | * * | |
35 | * * | |
36 | * * | |
37 | * * | |
38 | * * | |
39 | * * | |
40 | * * | |
41 | * * | |
42 | * * | |
43 | * * | |
44 | * * | |
45 | * * | |
46 | * * | |
47 | * * | |
48 | * * | |
49 | * * | |
50 | * * | |
51 | * * | |
52 | * * | |
53 | * * | |
54 | * * | |
55 | * * | |
56 | ** | |
57 | * | |
58 |
0 | * | |
1 | * | |
2 | * | |
3 | * | |
4 | * | |
5 | * | |
6 | * | |
7 | * | |
8 | * | |
9 | * | |
10 | * | |
11 | * ****** * | |
12 | * * * * * * | |
13 | * * * * * * | |
14 | * ********** * * * | |
15 | * * ** * | |
16 | * * * * | |
17 | * * * * | |
18 | * * * * | |
19 | * * * * | |
20 | * * * * | |
21 | * * * * | |
22 | * * * * | |
23 | * ****************************************** | |
24 | * * * * * * | |
25 | * * * * * * | |
26 | * * * * * * | |
27 | * * * * * * | |
28 | * * * * * * | |
29 | * ** * * * * | |
30 | * * * * * * | |
31 | * * * * * * | |
32 | * * * * * | |
33 | **************** * * * | |
34 | * * * * * * | |
35 | * * * * * * | |
36 | * * * * * ***** | |
37 | * * **** * * * | |
38 | * * * * * * | |
39 | * * * * * | |
40 | * **** * * * | |
41 | * * * * | |
42 | * * * * | |
43 | * * ************************ | |
44 | * * | |
45 | * * | |
46 | * * | |
47 | * * | |
48 | * * | |
49 | * * | |
50 | * * | |
51 | * * | |
52 | * * | |
53 | * * | |
54 | * * | |
55 | * * | |
56 | * * | |
57 | * * | |
58 | * * | |
59 | * * | |
60 | * * | |
61 | * * | |
62 | * * | |
63 | * * | |
64 | * * | |
65 | * * | |
66 | * * | |
67 | ** | |
68 | * | |
69 |
0 | 0 | |
1 | 9 | |
2 | * | |
3 | * | |
4 | * | |
5 | * PUT | |
6 | * | |
7 | * * | |
8 | * ** | |
9 | * * * | |
10 | * * * | |
11 | * * * | |
12 | * * * | |
13 | * ********************************** | |
14 | * * * | |
15 | * *** * | |
16 | * * * | |
17 | * * * | |
18 | * * * | |
19 | * * * | |
20 | * ************** * | |
21 | * * * * * * | |
22 | * * * * * * | |
23 | * * * * * | |
24 | * * * * * *** * | |
25 | * * * * GET ********** *** * * | |
26 | * * * END * * *** * * | |
27 | * * * * ** *** * | |
28 | * * * * * *** * | |
29 | * * *** * * * * | |
30 | * * * * * * * | |
31 | * * * ADD ONE * * * * | |
32 | * * * * DONE? * * * | |
33 | * * * * * * * | |
34 | * * * * * * * | |
35 | * * * *************** * * | |
36 | * * * * * GET * * | |
37 | * * * * ** * * | |
38 | * * * * * * * * | |
39 | * ********* * * * * * | |
40 | * * * * * * | |
41 | * GET AGAIN * * * * * | |
42 | *** * * * * | |
43 | * * * * * * | |
44 | * * *** * * | |
45 | * * * * | |
46 | * *** * * * | |
47 | * * ** * * | |
48 | * * * * * | |
49 | * * * * | |
50 | * * WRITE * * | |
51 | * * * * | |
52 | * * * * | |
53 | * * * * | |
54 | * * * * | |
55 | * * * * | |
56 | * * * * | |
57 | * * * * | |
58 | * *** * * * | |
59 | * * * * * * | |
60 | *** * ** * | |
61 | * * * | |
62 | * * | |
63 | * GET AGAIN * | |
64 | * * | |
65 | * ************************** | |
66 | * * | |
67 | * * | |
68 | * * | |
69 | * * | |
70 | * * | |
71 | * | |
72 |
0 | + * | |
1 | * ** | |
2 | * * * | |
3 | * * * ** | |
4 | * **************************** * | |
5 | * * * * * | |
6 | * * * * * | |
7 | * * * * * | |
8 | * **RESTART*** * | |
9 | * * * * | |
10 | * **LOOP** * | |
11 | ** * * * | |
12 | * ** * * | |
13 | ** * ** ** * | |
14 | * ***** * * * * * | |
15 | * * * * * * * | |
16 | * * * *********** **** * | |
17 | ********** * * * * | |
18 | * * * * * ** | |
19 | * * ******* * * * | |
20 | ** * * * * *********** * | |
21 | ** * * ** * * * * * | |
22 | *** ** * * * * * * * | |
23 | * * * *********** * * * * | |
24 | * **DEHSINIF** * * ** * | |
25 | * * * F * * | |
26 | * * * I * ********* | |
27 | * ** * N ** | |
28 | * ** I | |
29 | * * S | |
30 | * H | |
31 | * **E***** | |
32 | *** * D * | |
33 | * * * * | |
34 | ********* * * * | |
35 | * * * ** ** | |
36 | * * * * | |
37 | * * * * | |
38 | * * * * | |
39 | * * * | |
40 | * * | |
41 | * * ** | |
42 | ******************* * | |
43 | ** | |
44 | * | |
45 | * * | |
46 | * * * | |
47 | * * * | |
48 | * * D | |
49 | ** O | |
50 | N | |
51 | E | |
52 | ! | |
53 | * | |
54 | * | |
55 |
0 | H ************************ ****************** ********** | |
1 | e * * * * * * * | |
2 | l * *** * ** * * * * * | |
3 | ! o * *** * * * * * * * * * | |
4 | , * * * ** * * * * * * * * | |
5 | W * * * * * * * * * * * ** * | |
6 | r * * * * * * ************ * * * * * * * | |
7 | d * * * * * * * * ****** * * * * * | |
8 | * * * * * ** ** * * * * * * * | |
9 | * ** * * * * * * * ** * * | |
10 | * * * * * * ** ** * * * * * | |
11 | * * * * * ** ** * ** * * * * | |
12 | ******************** * * * ** * ** **** *** * | |
13 | * ** * * ** * ** * | |
14 | * ** * * * ** * ** * | |
15 | * ** * ** * ** ** * ** * | |
16 | ***** * ** * * ** ** ** * | |
17 | ** * * ** * | |
18 | * * * | |
19 | ************************************************************* * ***************************** | |
20 | * * * | |
21 | * *** * * | |
22 | * * * * * * | |
23 | * ** * * * * | |
24 | * * * * ** ****** * ********************* | |
25 | * * * * * * * * * | |
26 | * * * * * * * * * | |
27 | * * * * ** * * * * | |
28 | * * * * ** * * * * | |
29 | * * * ***** ** * * * * | |
30 | * * ** * ** ** * * * * | |
31 | * * ** * ** ** ***** * * * | |
32 | * * ** * * ** * * * | |
33 | * * ** ** * * ** * ** * | |
34 | * * * ** ***** ** ** * ** * | |
35 | * * * ** ** * * * | |
36 | * * ** ** * * * | |
37 | ** * ** * ** * | |
38 | * * * * * | |
39 | * * ************************************************************* * * * | |
40 | ** * * * * * * | |
41 | ** * * * * * * * | |
42 | * * * ************************* ** * * * * | |
43 | * * * * * * * * * * * | |
44 | *** * * * * * * * * * * ************** * | |
45 | * * * * ** * * * * * ** ** * * | |
46 | * * * * * * *** * * * * ** ** ******* * | |
47 | ** * * * ** * * * * ** * * | |
48 | * * * * * * * * ** * * | |
49 | * * * * * * * ** * * | |
50 | * * * * * * * ** * * | |
51 | * * * * * * * * ** * * | |
52 | * * * * * ** * * ** * * | |
53 | * * * * * * * * * * * * | |
54 | * * * * * * * * * * * * | |
55 | * * * * ** * * * * * * | |
56 | * * * * * * * * * * * | |
57 | * * * * * * * ** * | |
58 | * * * * * * * * * | |
59 | * * * * * * * * | |
60 | * * * ***** * * * | |
61 | * * * * * * | |
62 | * * * * * * | |
63 | * ** * * * | |
64 | * * * * * | |
65 | * * * * | |
66 | ***************************** * * | |
67 | * * | |
68 | *********************************************************************************************** * | |
69 | * * | |
70 | * * | |
71 | * ** * | |
72 | * ** ** * | |
73 | * ** * * | |
74 | * ** * * | |
75 | * ** * * | |
76 | * ** * * | |
77 | * ** * ****** * | |
78 | * **** ** * * * ****************** | |
79 | * * * ** ** ** * * | |
80 | * * * ** ** * ** * | |
81 | * * * * * * | |
82 | * * * * * * | |
83 | * ***** * * * * | |
84 | * * * * * * | |
85 | * * ** * * | |
86 | * * * * * | |
87 | * * * * | |
88 | ******* * * | |
89 | ** ** * | |
90 | ** ** * * | |
91 | ** ** * ** | |
92 | ************************ ** ** * * * | |
93 | * ** * * * | |
94 | * * * * * | |
95 | * ** * * * | |
96 | * * * * * * | |
97 | * * * * * * | |
98 | * * * ** * | |
99 | * * ** * * | |
100 | * * ** * | |
101 | * * ** * | |
102 | ** ** * | |
103 | * ** ****************************** | |
104 | ** ** ** | |
105 | ** ** ** | |
106 | ** ** ** | |
107 | ** * ** | |
108 | * ** | |
109 | * ** | |
110 | * ** | |
111 | * ** ** ** | |
112 | *************** ** ** | |
113 | ** | |
114 | ||
115 | * ** ** ** | |
116 | ||
117 | *************** ** ** | |
118 | ||
119 |
0 | * | |
1 | * | |
2 | * | |
3 | * | |
4 | * * ** | |
5 | * ** * | |
6 | ** ** | |
7 | * * | |
8 | * * | |
9 | * * | |
10 | * * | |
11 | * ** | |
12 | * * | |
13 | * ** * | |
14 | ** * | |
15 |
0 | * * | |
1 | * * * | |
2 | * * *** | |
3 | * * * | |
4 | * * * | |
5 | * * * | |
6 | * * * | |
7 | * * * | |
8 | * *** * | |
9 | * * * | |
10 | * * * | |
11 | * * * | |
12 | * * * | |
13 | * * * | |
14 | * * * | |
15 | * * * | |
16 | * * * | |
17 | * * *** | |
18 | * * * | |
19 | ******* | |
20 |
0 | & * | |
1 | 0 * * | |
2 | * * * | |
3 | * ** * | |
4 | ** * | |
5 | * **************************** | |
6 | * *********** * | |
7 | * * * | |
8 | ** * * | |
9 | * ** * | |
10 | *H * * * | |
11 | * A * * ** * | |
12 | * L **************************** * * | |
13 | * F * * * * * | |
14 | N * * * * * * | |
15 | E * * * * * * | |
16 | X * **RESTART*** * * | |
17 | T * * * * * | |
18 | * * * **LOOP** * * | |
19 | * * ***** * * * * | |
20 | * * * ** * * * | |
21 | * ** ** * ** ** * * | |
22 | * * * ***** * * * * * * | |
23 | * * * * * * * * * * | |
24 | ** * * * * *********** **** * * | |
25 | * ********** * * * * * | |
26 | * * * * * ** * | |
27 | * * ******* * * * * | |
28 | ** * * * * *********** * * | |
29 | ** * * ** * * * * * * | |
30 | *** ** * * * * * * * * | |
31 | * * * *********** * * * * * | |
32 | * **DEHSINIF** * * ** * * | |
33 | * * * F * * * | |
34 | * * * I * ********* * | |
35 | * ** * N ** * | |
36 | * ** I * | |
37 | * * S * | |
38 | * H * | |
39 | * **E***** * | |
40 | *** * D * * | |
41 | * * * * * | |
42 | ********* * * * * | |
43 | * * * ** ** * | |
44 | * * * * * | |
45 | * * * * * | |
46 | * * * * * | |
47 | * * * * | |
48 | * * * | |
49 | * * ** * * | |
50 | ******************* * ** * | |
51 | ** * * * | |
52 | * ** * * * * | |
53 | * ** * * * * ** * | |
54 | * ** * * * * ** * | |
55 | * * * * * * * * | |
56 | *** * * * ** * * * | |
57 | * * ** * * * * | |
58 | * **** H * * * | |
59 | * * * * A* * * | |
60 | * * **OREZ** L * * | |
61 | ****PRINT* * * * * *V * * | |
62 | * * * * * * E * * | |
63 | * * ** * ** * D ** * | |
64 | * * ** * ** * ** * | |
65 | ************* * * * * * | |
66 | * * * * * * * * * | |
67 | * * * * D * **IICSA** * | |
68 | ** * * O * * * * | |
69 | * ***** N * * * * | |
70 | E * ** * | |
71 | * * * * | |
72 | ( * * | |
73 | P ** * | |
74 | R * * | |
75 | I * * | |
76 | N * * | |
77 | T * * | |
78 | * * * | |
79 | N * * | |
80 | E ***************** | |
81 | W | |
82 | L ** | |
83 | I ** **** | |
84 | N ** * | |
85 | E ** * | |
86 | ) ** * | |
87 | * ** * | |
88 | * ** | |
89 | * ** | |
90 | * ** | |
91 | * ** | |
92 | ** | |
93 |
0 | DONOTWierd * | |
1 | DO,1<- # 0 09 | |
2 | DO,1SUB#1 <- # 01 10 | |
3 | PLEASEDO,1SUB # 2 <- #0 3 2 | |
4 | DO,1SUB # 3 <- #0 7 2 | |
5 | DO ,1SUB#004<-#0 0 0 0 000000136 | |
6 | DO,1SUB#5 <- # 0 0 0 8 8 | |
7 | PLEASEDO,1SUB # 06 <- # 0 1 3 6 | |
8 | DO , 1SUB#7 <- # 000 0 6 4 | |
9 | DO ,01 SUB #8 <- # 0 0 0 0 0 80 | |
10 | DO ,1 SUB # 00 0 0 0 0 9 <-#2 26 | |
11 | PLEASE READ OUT ,0 0 0 0 0 000000000000000 0 0 01 | |
12 | PLEASEGIVEUPDONOTBOTHERME * * * P * * * * * ** | |
13 | DONOT * * * * * O* * * * * * ** | |
14 | DONOT ** * * * O ** * * ** * * ** | |
15 | DONOT ** * * *L * * ** * * * ** | |
16 | PLEASEDONOT * * * * * ** * ** * * ** | |
17 | DONOT * * * * N* * * * * * * ** | |
18 | DONOT * * * * I ** ** * * * ** | |
19 | DONOT * * * * A * * * * * * | |
20 | PLEASEDO NOT * * * M ** ** * * * * | |
21 | DONOT * * * * * * * * * ** ** * | |
22 | DONOT * * * * * * ** * ** * * ***************** | |
23 | DONOT * * * * * * * ********* * ** * | |
24 | PLEASEDONOT **** * * ** ** * | |
25 | DONOT * ** * * * * * | |
26 | DONOT ** * * * * * * | |
27 | DONOT * ** * * * | |
28 | PLEASEDONOT * * * * * | |
29 | DONOT *********** * * * | |
30 | DONOT * * * * * * | |
31 | DONOT * * * * * | |
32 | PLEASEDONOT * * * * * * | |
33 | DONOT * * * * * | |
34 | DONUT * * * * * * | |
35 | DONOT * * * * * * | |
36 | PLEASEDONOY * * * * * * | |
37 | DONOT * * * * * * | |
38 | DONOT * * * * * * | |
39 | DONOT * * * * * W | |
40 | PLEASEDONOT * * * * * R | |
41 | DONOT * ** * * I | |
42 | DONOT * * * *T | |
43 | DONOT * * E | |
44 | DONOT * * | |
45 | OKAY,DOIFYOUPLEASE! | |
46 | ICHANGEDMYMINDDON'T | |
47 | DONOTDOTHAT ** | |
48 | PLEASESTOP * | |
49 |
0 | ! | |
1 | @ | |
2 | * ! | |
3 | * *! | |
4 | * * ! | |
5 | * * ! | |
6 | * * * ! | |
7 | * * * ! | |
8 | * *** * ! | |
9 | ** * * ! | |
10 | * ** ** * **! | |
11 | * * ** **** * * ! | |
12 | * ** * * ** ! | |
13 | * ** * * * * ! | |
14 | * ** * * * * *** * ! | |
15 | * ** * * * * * * * * ! | |
16 | * ** * * * * * * * * * ! | |
17 | * ** * * * ** * * * * * *! | |
18 | ** * * * *** * * * * * * * ! | |
19 | * * * * * * * * * * ! | |
20 | *** * ** * * * * * * ! | |
21 | * * * * * * * * ! | |
22 | * * * * * * * * * ! | |
23 | * * * * * ** *** * * * ! | |
24 | * * * * * * ** * * * * ! | |
25 | * * * * * * **** * * * ! | |
26 | * ** * * * * * * **************************! | |
27 | * * * * * * * * * * ! | |
28 | * * * * * * * * * * ! | |
29 | * * * * * * * * * * ! | |
30 | * * * * * * * * * ********************** ! | |
31 | * * * * * * * * * * * ! | |
32 | * * ***** *** * * * * * * * ** ! | |
33 | * * * ** * * * * * * * ! | |
34 | * * * * * * * * * * **** * * * ! | |
35 | * * * * * * * * * * * * * ** * ! | |
36 | * * * * ** * * * * * * ********* * * ! | |
37 | * * * * ** * * * ** * * * * ** ! | |
38 | * * * ** ** * * * * * * * * * ! | |
39 | * ** * * * * * * * * * * * ! | |
40 | * * * * * * * ** * * * ! | |
41 | ********************************************************* * * * * ** * * * * ! | |
42 | * * * * * * * * * * ! | |
43 | __ ___________________ _____ * * * * * * * * * * ! | |
44 | \ \ / __ __ ___ _ \ | __ \ * * * *RESTART* ** * * * ! | |
45 | \ \ /\ / / | | | |_ | |_) \| | \ \ * * * * * * ** * * ! | |
46 | \ \/ \/ / | | | _| | _ /| | ) ) * * * **RESTART* ** * * * * ! | |
47 | \ /\ / __| |__| |___| | \ \| |__/ / * * * * * * * * * * ** ! | |
48 | \/ \/ |_______________| \_______/ * **************** ****MAIN*LOOP**** * * * * * ! | |
49 | ____ _ _____________ ____ ** * * * ** * ** * ! | |
50 | / __ \ | | | __ __ \ | __| ** * * * ** ** * * ! | |
51 | / / \ \ | | | | | | | |\ \ | |_ * * * ** ** * ! | |
52 | ( ( ) )| | | | | | | | \ \ | _| * * * * * * * ! | |
53 | \ \__/ \| |_| |__| |__| | \ \| |__ ** * * ****YAW*SIHT****** * ! | |
54 | \____/\_________________| \______| * * * * * * * * ! | |
55 | ********WON*1=X**** ** * ***** ** * ! | |
56 | ____ ____ ___ ___ ___ * * * * * * * ! | |
57 | / __ \ / _ \ / _ \ / _ \ / | * * ** * * * * * ! | |
58 | / / \ \ (_/ ) / / / \ \ / / \ \ (_/| | * * E * * * * * ! | |
59 | ( ( ) / / ( ( ) )( ( ) ) | | * *O * ** * * * * ! | |
60 | \ \__/ / / /__ \ \_/ / \ \_/ / __| |__ * L * * * * * * ! | |
61 | \____/ /_____| \___/ \___/ |_______| * ** * * * * * * ! | |
62 | __ ____ ___ ___ ____ * * * * * * *********** ! | |
63 | / \ / _ \ / _ \ / _ \ / _ \ * * * * * * * ! | |
64 | ( () ) _ (_/ ) / / / \ \ / / \ \ (_/ ) / * * * * * * * ! | |
65 | ) _ \/ ) / / ( ( ) )( ( ) ) / / * * ** **** * ** ***** ! | |
66 | ( (_) ( / /__ \ \_/ / \ \_/ / / /__ * * * * ** ** ! | |
67 | \___/\_) /_____| \___/ \___/ /_____| * * * ** ! | |
68 | __ ____________ ____ * * * ! | |
69 | | \ / __ __ | / __ \ * * * ! | |
70 | | \ / | | | | | / / \ \ * *** ! | |
71 | | |\ \/ /| | | | | | ( ( ) ) * ! | |
72 | | | \ / | |__| |__| |_____) \__/ / * ! | |
73 | |_| \/ |_______________________/ * ! | |
74 | __ ___ _ * ! | |
75 | \ \ /\ | \ | | * ! | |
76 | \ \ / \ | |\ \ | | * ! | |
77 | \ \/ /\ \| | \ \ | | * ! | |
78 | \ ____ \ | \ \| | * ! | |
79 | \/ \__| \___| * ! | |
80 | _ _ ___ _____ _______ *** ! | |
81 | | | | | /\ | \ | __ \ | ___ | * * ! | |
82 | | |__| | / \ | |\ \ | | \ \| |_ | | * ! | |
83 | | __ | / /\ \| | \ \ | | ) ) _| | | * * ! | |
84 | | | | |/ ____ \ | \ \| |__/ /| |___| |___ * * * * ! | |
85 | |_| |___/ \__| \_______/ |___________| * D * ** ! | |
86 | * O * * * ! | |
87 | SOURCE AND OUTPUT BOTH LICENCED BY THE GPL * * N ******* * * ! | |
88 | (DOESN'T FIT WITH ASCII ART) * ** E * * * * ! | |
89 | * * * ******* * * ! | |
90 | ** * * * * * ! | |
91 | * * * N * * ! | |
92 | *** * O * * ! | |
93 | * * ** * T * ** ! | |
94 | * ** ** * * ! | |
95 | *** * Y * ! | |
96 | * E * ! | |
97 | * T * ! | |
98 | * ** ! | |
99 | * ! | |
100 | * ! | |
101 | * ! | |
102 | * ! | |
103 | * *! | |
104 | ** * *! | |
105 | ** ** ! | |
106 | * ! | |
107 | * ****************************! | |
108 | @ *! | |
109 | ||
110 | ||
111 |
0 | * ** * | |
1 | * * ** * ** | |
2 | 0 ** **** ** * * * | |
3 | * * ** * * ** ** * * | |
4 | * * * ** * ** * * | |
5 | * * * * * * ** * * | |
6 | * * ** * * * * * * | |
7 | **** * * * * * * | |
8 | * * * * * * * | |
9 | * * * * * * * | |
10 | * * * * * * * | |
11 | ** * * * * * | |
12 | * * * * * * | |
13 | ** * * * ****** | |
14 | * * * * * * * | |
15 | * * * * * * * * * | |
16 | * * ** * * * * * * | |
17 | * * * * * * ****** * | |
18 | * * * * ** * | |
19 | * ** * * N ******** * | |
20 | * ** * * ******E******* * * * | |
21 | M ** * S * ** * ** * * | |
22 | A * O ** * * * * * | |
23 | I * H * * * * | |
24 | N * C * * * * | |
25 | * * * * * * * * | |
26 | L * R ** ** * * * | |
27 | O * E * * * ** * | |
28 | O * B * * * ** * * | |
29 | P * M * ** * * *** * | |
30 | * * U * ** * * * * | |
31 | ** N * * * * * * | |
32 | * * * * * * * * | |
33 | * * ** * * * * * * | |
34 | ** **** * * * * * * * | |
35 | ** * * * * * * * * | |
36 | * **** * * * * * * * | |
37 | * ** * **** * * ** * * | |
38 | ** * * * * * * | |
39 | ***************** * * | |
40 | * * * ** * | |
41 | * * * * * | |
42 | * * * * * | |
43 | * * * * | |
44 | * * ** * * | |
45 | * * **************** * | |
46 | * ** * | |
47 | * * * | |
48 | ****** * * | |
49 | * * * * * | |
50 | * ** * * | |
51 | * *** * | |
52 | * * * | |
53 | * ** * * | |
54 | * **** * * * | |
55 | * * * * * | |
56 | * * * * * | |
57 | ** * * * * | |
58 | ** * *** * | |
59 | * * ** * | |
60 | * * * | |
61 | ** * | |
62 | * * | |
63 | * * | |
64 | * * * | |
65 | * * * | |
66 | * ** * | |
67 | ** * | |
68 | * **************************** | |
69 | * *********** * | |
70 | * * * | |
71 | ** * * | |
72 | * ** * | |
73 | *H * * * | |
74 | * A * * ** * | |
75 | * L **************************** * * | |
76 | * F * * * * * | |
77 | N * * * * * * | |
78 | E * * * * * * | |
79 | X * **RESTART*** * * | |
80 | T * * * * * | |
81 | * * * **LOOP** * * | |
82 | * * ***** * * * * | |
83 | * * * ** * * * | |
84 | * ** ** * ** ** * * | |
85 | * * * ***** * * * * * * | |
86 | * * * * * * * * * * | |
87 | ** * * * * *********** **** * * | |
88 | * ********** * * * * * | |
89 | * * * * * ** * | |
90 | * * ******* * * * * | |
91 | ** * * * * *********** * * | |
92 | ** * * ** * * * * * * | |
93 | *** ** * * * * * * * * | |
94 | * * * *********** * * * * * | |
95 | * **DEHSINIF** * * ** * * | |
96 | * * * F * * * | |
97 | * * * I * ********* * | |
98 | * ** * N ** * | |
99 | * ** I * | |
100 | * * S * | |
101 | * H * | |
102 | * **E***** * | |
103 | *** * D * * | |
104 | * * * * * | |
105 | ********* * * * * | |
106 | * * * ** ** * | |
107 | * * * * * | |
108 | * * * * * | |
109 | * * * * * | |
110 | * * * * | |
111 | * * * | |
112 | * * ** * * | |
113 | ******************* * ** * | |
114 | ** * * * | |
115 | * ** * * * * | |
116 | * ** * * * * ** * | |
117 | * ** * * * * ** * | |
118 | * * * * * * * * | |
119 | *** * * * ** * * * | |
120 | * * ** * * * * | |
121 | * **** H * * * | |
122 | * * * * A* * * | |
123 | * * **OREZ** L * * | |
124 | ****PRINT* * * * * *V * * | |
125 | * * * * * * E * * | |
126 | * * ** * ** * D ** * | |
127 | * * ** * ** * ** * | |
128 | ************* * * * * * | |
129 | * * * * * * * * * | |
130 | * * * * D * **IICSA** * | |
131 | ** * * O * * * * | |
132 | * ***** N * * * * | |
133 | E * ** * | |
134 | * * * * | |
135 | ( * * | |
136 | P ** * | |
137 | R * * | |
138 | I * * | |
139 | N * * | |
140 | T * * | |
141 | * * * | |
142 | N * * | |
143 | E ***************** | |
144 | W | |
145 | L ** | |
146 | I ** **** | |
147 | N ** * | |
148 | E ** * | |
149 | ) ** * | |
150 | * ** * | |
151 | * ** | |
152 | * ** | |
153 | * ** | |
154 | * ** | |
155 | ** | |
156 |
0 | #include <stdio.h> | |
1 | #include <stdlib.h> | |
2 | #include <string.h> | |
3 | #include <time.h> | |
4 | #include <unistd.h> | |
5 | #include <getopt.h> | |
6 | ||
7 | typedef struct stack | |
8 | { | |
9 | int value; | |
10 | struct stack *below; | |
11 | } stack; | |
12 | ||
13 | typedef struct thread | |
14 | { | |
15 | int id; | |
16 | int x, y, dx, dy; | |
17 | stack *stack_head; | |
18 | struct thread *next, *prev; | |
19 | } thread; | |
20 | ||
21 | int size = 256; | |
22 | int debug = 0; | |
23 | int **world; | |
24 | thread *current_thread; | |
25 | int threads = 0; | |
26 | ||
27 | void push(int value) | |
28 | { | |
29 | stack *new; | |
30 | ||
31 | new = malloc(sizeof(*new)); | |
32 | new->value = value; | |
33 | new->below = current_thread->stack_head; | |
34 | current_thread->stack_head = new; | |
35 | } | |
36 | ||
37 | int pop(void) | |
38 | { | |
39 | stack *old; | |
40 | int value; | |
41 | ||
42 | old = current_thread->stack_head; | |
43 | if(old == NULL) | |
44 | { | |
45 | fprintf(stderr, "Insufficient stack!\n"); | |
46 | exit(1); | |
47 | } | |
48 | value = old->value; | |
49 | current_thread->stack_head = old->below; | |
50 | free(old); | |
51 | return value; | |
52 | } | |
53 | ||
54 | void copy_stack(thread *dst, thread *src) | |
55 | { | |
56 | stack *dst_loc, *prev_dst_loc = NULL, *src_loc; | |
57 | ||
58 | if(src->stack_head == NULL) | |
59 | { | |
60 | dst->stack_head = NULL; | |
61 | return; | |
62 | } | |
63 | for(src_loc = src->stack_head; src_loc != NULL; src_loc = src_loc->below) | |
64 | { | |
65 | dst_loc = malloc(sizeof(*dst_loc)); | |
66 | dst_loc->value = src_loc->value; | |
67 | dst_loc->below = NULL; | |
68 | if(prev_dst_loc == NULL) dst->stack_head = dst_loc; else prev_dst_loc->below = dst_loc; | |
69 | prev_dst_loc = dst_loc; | |
70 | } | |
71 | } | |
72 | ||
73 | void new_thread(void) | |
74 | { | |
75 | thread *new; | |
76 | ||
77 | new = malloc(sizeof(*new)); | |
78 | new->id = threads++; | |
79 | new->x = current_thread->x; | |
80 | new->y = current_thread->y; | |
81 | new->dx = -current_thread->dx; | |
82 | new->dy = -current_thread->dy; | |
83 | copy_stack(new, current_thread); | |
84 | new->next = current_thread->next; | |
85 | new->prev = current_thread; | |
86 | current_thread->next->prev = new; | |
87 | current_thread->next = new; | |
88 | } | |
89 | ||
90 | void kill_thread(void) | |
91 | { | |
92 | thread *old; | |
93 | ||
94 | old = current_thread; | |
95 | while(old->stack_head != NULL) pop(); | |
96 | if(old->next == old) exit(0); | |
97 | old->prev->next = old->next; | |
98 | old->next->prev = old->prev; | |
99 | current_thread = old->next; | |
100 | free(old); | |
101 | } | |
102 | ||
103 | void turn_dxdy(int *dx, int *dy, int direction) | |
104 | { | |
105 | int old_dx, old_dy; | |
106 | ||
107 | direction %= 8; | |
108 | if(direction < 0) direction += 8; | |
109 | while(direction-- > 0) | |
110 | { | |
111 | old_dx = *dx; | |
112 | old_dy = *dy; | |
113 | *dx = old_dy + old_dx; | |
114 | *dy = old_dy - old_dx; | |
115 | if(abs(*dx) == 2) *dx /= 2; | |
116 | if(abs(*dy) == 2) *dy /= 2; | |
117 | } | |
118 | } | |
119 | ||
120 | int can_turn(int direction) | |
121 | { | |
122 | int dx = current_thread->dx, dy = current_thread->dy; | |
123 | ||
124 | turn_dxdy(&dx, &dy, direction); | |
125 | return world[current_thread->x + dx][current_thread->y + dy] != ' '; | |
126 | } | |
127 | ||
128 | void turn(int direction) | |
129 | { | |
130 | turn_dxdy(¤t_thread->dx, ¤t_thread->dy, direction); | |
131 | } | |
132 | ||
133 | void print_stack(void) | |
134 | { | |
135 | char str1[256], str2[256] = ""; | |
136 | stack *printing; | |
137 | ||
138 | fprintf(stderr, "The new stack is"); | |
139 | if(current_thread->stack_head == NULL) | |
140 | { | |
141 | fprintf(stderr, " empty.\n"); | |
142 | return; | |
143 | } | |
144 | for(printing = current_thread->stack_head; printing != NULL; printing = printing->below) | |
145 | { | |
146 | sprintf(str1, " [%d]%s", printing->value, str2); | |
147 | strcpy(str2, str1); | |
148 | } | |
149 | fputs(str2, stderr); | |
150 | fputc('\n', stderr); | |
151 | } | |
152 | ||
153 | void help(void) | |
154 | { | |
155 | fprintf(stderr, "Valid options:\n"); | |
156 | fprintf(stderr, "-help: Show this screen.\n"); | |
157 | fprintf(stderr, "-size <number>: Set the memory size.\n"); | |
158 | fprintf(stderr, "-debug: Print debugging information.\n"); | |
159 | fprintf(stderr, "There should also be a non-option argument naming the program to be run.\n"); | |
160 | exit(1); | |
161 | } | |
162 | ||
163 | int main(int argc, char **argv) | |
164 | { | |
165 | struct option options[] = {{"help", 0, NULL, '?'}, | |
166 | {"size", 1, NULL, 's'}, | |
167 | {"debug", 0, NULL, 'd'}}; | |
168 | int done = 0; | |
169 | char *ptr; | |
170 | int x, y; | |
171 | char *in_name = NULL; | |
172 | FILE *in_file; | |
173 | ||
174 | opterr = 0; | |
175 | while(!done) | |
176 | { | |
177 | switch(getopt_long_only(argc, argv, "-?", options, NULL)) | |
178 | { | |
179 | case 's': if(*optarg == '\0') help(); | |
180 | size = strtol(optarg, &ptr, 10); | |
181 | if(*ptr != '\0') help(); | |
182 | break; | |
183 | case 'd': if(debug) help(); | |
184 | debug = 1; | |
185 | break; | |
186 | case '?': help(); | |
187 | case 1: if(in_name != NULL) help(); | |
188 | in_name = strdup(optarg); | |
189 | break; | |
190 | case EOF: done = 1; | |
191 | break; | |
192 | } | |
193 | } | |
194 | if(in_name == NULL) help(); | |
195 | world = malloc(sizeof(*world) * size); | |
196 | for(x = 0; x < size; x++) | |
197 | { | |
198 | world[x] = malloc(sizeof(**world) * size); | |
199 | for(y = 0; y < size; y++) world[x][y] = ' '; | |
200 | } | |
201 | in_file = fopen(in_name, "r"); | |
202 | if(in_file == NULL) | |
203 | { | |
204 | perror(in_name); | |
205 | return 1; | |
206 | } | |
207 | y = 1; | |
208 | for(;;) | |
209 | { | |
210 | char ch; | |
211 | ||
212 | x = 1; | |
213 | for(;;) | |
214 | { | |
215 | ch = fgetc(in_file); | |
216 | if(ch == '\n' || ch == EOF) break; | |
217 | world[x++][y] = ch; | |
218 | } | |
219 | if(ch == EOF) break; | |
220 | y++; | |
221 | } | |
222 | fclose(in_file); | |
223 | if(world[1][1] == ' ') | |
224 | { | |
225 | fprintf(stderr, "Starting point for program is empty.\n"); | |
226 | return 1; | |
227 | } | |
228 | current_thread = malloc(sizeof(*current_thread)); | |
229 | current_thread->id = threads++; | |
230 | current_thread->x = current_thread->y = 1; | |
231 | current_thread->dx = current_thread->dy = 1; | |
232 | current_thread->stack_head = NULL; | |
233 | current_thread->next = current_thread->prev = current_thread; | |
234 | srandom(time(NULL)); | |
235 | for(;;) | |
236 | { | |
237 | int closest_right = 4, closest_left = 4; | |
238 | int which, x, y; | |
239 | ||
240 | if(debug) fprintf(stderr, "Thread %3d at (%3d,%3d) ", current_thread->id, current_thread->x, current_thread->y); | |
241 | if(can_turn(1)) closest_left = 1; else if(can_turn(2)) closest_left = 2; else if(can_turn(3)) closest_left = 3; | |
242 | if(can_turn(-1)) closest_right = 1; else if(can_turn(-2)) closest_right = 2; else if(can_turn(-3)) closest_right = 3; | |
243 | if(can_turn(0)) | |
244 | { | |
245 | if(debug) fprintf(stderr, "is happily marching along (0 degrees).\n"); | |
246 | } | |
247 | else if(closest_left == closest_right) | |
248 | { | |
249 | switch(closest_left) | |
250 | { | |
251 | case 1: if(debug) fprintf(stderr, "faces a difficult choice (45 or 315 degrees).\n"); | |
252 | if(random() & 1024) turn(1); else turn(-1); | |
253 | break; | |
254 | case 2: if(debug) fprintf(stderr, "spawns a new thread (90 and 270 degrees).\n"); | |
255 | turn(2); | |
256 | new_thread(); | |
257 | current_thread = current_thread->next; | |
258 | continue; | |
259 | case 3: if(debug) fprintf(stderr, "is confused (135 and 225 degrees).\n"); | |
260 | fprintf(stderr, "The programmer has not yet decided what a 135/225 T-junction should do!"); | |
261 | return 1; | |
262 | case 4: if(debug) fprintf(stderr, "bumps into a dead end (180 degrees).\n"); | |
263 | kill_thread(); | |
264 | continue; | |
265 | } | |
266 | } | |
267 | else if(closest_left < closest_right) | |
268 | { | |
269 | switch(closest_left) | |
270 | { | |
271 | case 1: if(debug) fprintf(stderr, "places a one on his stack (45 degrees).\n"); | |
272 | push(1); | |
273 | break; | |
274 | case 2: which = pop(); | |
275 | if(which) | |
276 | { | |
277 | if(debug) fprintf(stderr, "is afraid from the turn (90 degrees).\n"); | |
278 | turn(2); | |
279 | break; | |
280 | } | |
281 | if(debug) fprintf(stderr, "happily marches through the turn (90 degrees).\n"); | |
282 | break; | |
283 | case 3: which = pop(); | |
284 | y = pop(); | |
285 | x = pop(); | |
286 | if(which) | |
287 | { | |
288 | if(debug) fprintf(stderr, "gets a number for his stack (135 degrees).\n"); | |
289 | push(world[x][y]); | |
290 | } | |
291 | else | |
292 | { | |
293 | if(debug) fprintf(stderr, "puts a number in his stack down (135 degrees).\n"); | |
294 | world[x][y] = pop(); | |
295 | } | |
296 | break; | |
297 | } | |
298 | if(debug) print_stack(); | |
299 | turn(closest_left); | |
300 | } | |
301 | else | |
302 | { | |
303 | switch(closest_right) | |
304 | { | |
305 | case 1: if(debug) fprintf(stderr, "sits down to work out a subtraction (315 degrees).\n"); | |
306 | y = pop(); | |
307 | x = pop(); | |
308 | push(x - y); | |
309 | break; | |
310 | case 2: which = pop(); | |
311 | if(which) | |
312 | { | |
313 | if(debug) fprintf(stderr, "is afraid from the turn (270 degrees).\n"); | |
314 | turn(-2); | |
315 | break; | |
316 | } | |
317 | if(debug) fprintf(stderr, "happily marches through the turn (270 degrees).\n"); | |
318 | break; | |
319 | case 3: which = pop(); | |
320 | if(which) | |
321 | { | |
322 | which = pop(); | |
323 | if(debug) fprintf(stderr, "wishes you to know that \"%c\" (225 degrees).\n", which); | |
324 | if(!debug || !isatty(1)) putchar(which); | |
325 | } | |
326 | else | |
327 | { | |
328 | which = getchar(); | |
329 | if(debug) fprintf(stderr, "discovers that \"%c\" (225 degrees).\n", which); | |
330 | push(which); | |
331 | } | |
332 | break; | |
333 | } | |
334 | if(debug) print_stack(); | |
335 | turn(-closest_right); | |
336 | } | |
337 | current_thread->x += current_thread->dx; | |
338 | current_thread->y += current_thread->dy; | |
339 | current_thread = current_thread->next; | |
340 | } | |
341 | } | |
342 |
0 | /* | |
1 | * Wierd Interpreter: | |
2 | * | |
3 | * Wierd Language developed by Chris Pressey, August 1997 | |
4 | * Interpreter written 05 August 1997 by John Colagioia | |
5 | * | |
6 | * Deviations from the "Official" Wierd: | |
7 | * Direction: The IP will always try to continue in the same | |
8 | * direction (or as close as possible). When two | |
9 | * equally-likely possibilities exist, it will choose | |
10 | * the "leftmost" branch. | |
11 | * Conditionals: When the IP connects to a 90-degree angle, | |
12 | * it pops the stack. If the result is zero, it | |
13 | * continues as if nothing interesting happens. If | |
14 | * nonzero, it reverses the IP direction. | |
15 | * Gap-Sparking: If the IP has just "sparked into" a | |
16 | * location which is isolated, the program is | |
17 | * considered erroneous, as the IP direction is | |
18 | * undefined at that time. | |
19 | * | |
20 | * Revision History: | |
21 | * R#: Date: Inits: Reason: | |
22 | * 0 05aug97 jnc Origination | |
23 | * 1 06aug97 jnc Various Bugfixes, Revised Conditionals | |
24 | * 2 07aug97 jnc Added Multithreading, Revised Conditionals | |
25 | * 3 08aug97 jnc Added "Gap-Sparking" | |
26 | * 4 08aug97 jnc General Cleanup and Bugfixes | |
27 | * | |
28 | * To Do: | |
29 | * -- Heavier testing (requires writing Wierd code...). | |
30 | * -- Add a tty or graphical display routine. | |
31 | * | |
32 | */ | |
33 | ||
34 | /*** Preprocessor Directives ***/ | |
35 | /* Included header files */ | |
36 | #include <stdio.h> | |
37 | #include <stdlib.h> | |
38 | #include <malloc.h> | |
39 | /* Constants and Macros */ | |
40 | #define SIZE 128 | |
41 | ||
42 | /*** Data Structures ***/ | |
43 | struct iplist /* An instruction pointer */ | |
44 | { | |
45 | int ipid; /* A unique identifier */ | |
46 | int x; /* The current ordinate value */ | |
47 | int y; /* The current abscissa value */ | |
48 | int dx; /* The next change in x to be applied */ | |
49 | int dy; /* The next change in y to be applied */ | |
50 | int stack[SIZE]; /* A stack exclusive to this IP */ | |
51 | int s_top; /* A pointer to the stack top */ | |
52 | struct iplist *next; /* The next IP available */ | |
53 | }; | |
54 | ||
55 | /*** Function Prototypes (only for the function table below) ***/ | |
56 | int nop (struct iplist **); | |
57 | int push1 (struct iplist **); | |
58 | int subtract (struct iplist **); | |
59 | int condition (struct iplist **); | |
60 | int getput (struct iplist **); | |
61 | int inputoutput (struct iplist **); | |
62 | int terminus (struct iplist **); | |
63 | ||
64 | /*** more prototypes, because my compiler likes them - cap */ | |
65 | int turn45 (int * xdir, int * ydir); | |
66 | int getnextturn (int x, int y, int * dx, int * dy); | |
67 | ||
68 | /*** Global Variables ***/ | |
69 | char workspace[SIZE][SIZE]; /* The "Wierd memory space" */ | |
70 | int tmpx, tmpy, /* temporary deltas */ | |
71 | ipid = 0, ip_killed; /* IP identifier, kill flag */ | |
72 | struct iplist *list; /* The list of IPs */ | |
73 | int (*function[])(struct iplist **) = | |
74 | { /* Function table */ | |
75 | nop, /* 0 degrees */ | |
76 | push1, /* 45 degrees */ | |
77 | condition, /* 90 degrees */ | |
78 | getput, /* 135 degrees */ | |
79 | terminus, /* 180 degrees */ | |
80 | inputoutput, /* 225 degrees */ | |
81 | condition, /* 270 degrees */ | |
82 | subtract /* 315 degrees */ | |
83 | }; | |
84 | ||
85 | /*** Source code for Interpreter Functions ***/ | |
86 | ||
87 | /* Function main(): | |
88 | * Initializes data structures and environment, and iterates through | |
89 | * each IP until termination. Also handles most common errors. | |
90 | */ | |
91 | int main (int argc, char *argv[]) | |
92 | { | |
93 | int i, x, y; /* Temporary variables */ | |
94 | FILE *infile; /* Input file */ | |
95 | ||
96 | if (argc < 2) /* Not enough arguments--don't know what to do */ | |
97 | { | |
98 | fprintf (stderr, "Error:\n\t%s <Wierd Filename>\n", argv[0]); | |
99 | exit (1); | |
100 | } | |
101 | infile = fopen (argv[1], "r"); | |
102 | if (infile == NULL) /* Bad input filename given */ | |
103 | { | |
104 | fprintf (stderr, "Error: Invalid Wierd filename: \"%s\".\n", | |
105 | argv[1]); | |
106 | exit (2); | |
107 | } | |
108 | ||
109 | for (x=0;x<SIZE;++x) /* Clear the memoryspace */ | |
110 | for (y=0;y<SIZE;++y) | |
111 | workspace[x][y] = '\000'; | |
112 | ||
113 | y = 1; /* Read the file into the memoryspace */ | |
114 | while (!feof (infile)) | |
115 | { | |
116 | fscanf (infile, "%[^\n]", &workspace[y][1]); | |
117 | fgetc (infile); | |
118 | #ifdef DEBUG | |
119 | printf ("%s\n", &workspace[y][1]); | |
120 | #endif | |
121 | ++y; | |
122 | } | |
123 | fclose (infile); /* Clean up file handles */ | |
124 | for (x=0;x<SIZE;++x) /* Convert nulls to spaces */ | |
125 | for (y=0;y<SIZE;++y) | |
126 | if (workspace[x][y] == '\000') | |
127 | workspace[x][y] = ' '; | |
128 | ||
129 | /* Initialize the first IP */ | |
130 | list = (struct iplist *) malloc (sizeof (struct iplist)); | |
131 | list->x = list->y = list->dx = list->dy = 1; | |
132 | list->s_top = 0; | |
133 | list->next = list; | |
134 | list->ipid = ++ipid; | |
135 | ||
136 | /* Loop as long as the location is valid */ | |
137 | while (workspace[list->x][list->y] != ' ') | |
138 | { | |
139 | ip_killed = 0; /* Initialize the kill-flag */ | |
140 | #ifdef DEBUG | |
141 | printf ("<%d>\t", list->ipid); | |
142 | printf ("(%d,%d)\t", list->y, list->x); | |
143 | for (i=0;i<list->s_top;++i) | |
144 | printf ("[%d] ", list->stack[i]); | |
145 | #endif | |
146 | tmpx = list->dx; /* Save the current direction */ | |
147 | tmpy = list->dy; /* and change it */ | |
148 | i = getnextturn (list->x, list->y, &tmpx, &tmpy); | |
149 | #ifdef DEBUG | |
150 | printf ("\t\t%d\n", i); | |
151 | #endif | |
152 | if (i % 45) /* Invalid direction! */ | |
153 | printf ("\007ERROR!!\007\n"); | |
154 | else { /* Call the appropriate function */ | |
155 | i = function[i/45](&list); | |
156 | if (i == -1) /* Out of IPs */ | |
157 | { | |
158 | free (list); | |
159 | return 0; | |
160 | } | |
161 | } | |
162 | if (!ip_killed) /* Only update if it's the same IP */ | |
163 | { | |
164 | list->x += list->dx = tmpx; /* Update location */ | |
165 | list->y += list->dy = tmpy; | |
166 | list = list->next; /* Next IP */ | |
167 | } | |
168 | } | |
169 | #ifdef DEBUG | |
170 | printf ("Program ungracefully terminated!\n"); | |
171 | #endif | |
172 | return 0; | |
173 | } | |
174 | ||
175 | /* Function checkdir(): | |
176 | * Simple function to determine validity of location a given delta | |
177 | * from the given location. | |
178 | */ | |
179 | int checkdir (int x, int y, int dx, int dy) | |
180 | { | |
181 | return (workspace[x+dx][y+dy] != ' '); /* Only space is invalid */ | |
182 | } | |
183 | ||
184 | /* Function rotate(): | |
185 | * Turns an IP the specified number of degrees (though only in 45- | |
186 | * degree increments). | |
187 | */ | |
188 | int rotate (int * xdir, int * ydir, int turn) | |
189 | { | |
190 | int i; | |
191 | ||
192 | for (i=0;i<turn;i+=45) /* We only work in 45-degree increments */ | |
193 | turn45 (xdir, ydir); | |
194 | return 0; | |
195 | } | |
196 | ||
197 | /* Function turn45(): | |
198 | * Rotates a dx,dy heading 45 degrees clockwise. Very unclean | |
199 | * implementation, but it works for now. Once we expand beyond two | |
200 | * dimensions, though, this will have to be heavily rewritten. | |
201 | */ | |
202 | int turn45 (int * xdir, int * ydir) | |
203 | { | |
204 | if (*ydir == 1 && *xdir == -1 || *ydir == -1 && *xdir == 1) | |
205 | *ydir = 0; | |
206 | else if (*xdir == 1 && *ydir == 1 || *xdir == -1 && *ydir == -1) | |
207 | *xdir = 0; | |
208 | else if (*ydir) | |
209 | *xdir -= *ydir; | |
210 | else *ydir += *xdir; | |
211 | return 0; | |
212 | } | |
213 | ||
214 | /* Function getnextturn(): | |
215 | * Checks the 7 of the 8 valid directions from the given point, | |
216 | * choosing those 7 based on the IP delta. Returns the "leftmost" | |
217 | * direction closest to "straight" that is available from the given | |
218 | * location. | |
219 | */ | |
220 | int getnextturn (int x, int y, int * dx, int * dy) | |
221 | { | |
222 | if (checkdir (x, y, *dx, *dy)) | |
223 | return 0; | |
224 | rotate (dx, dy, 45); | |
225 | if (checkdir (x, y, *dx, *dy)) | |
226 | return 45; | |
227 | rotate (dx, dy, 270); | |
228 | if (checkdir (x, y, *dx, *dy)) | |
229 | return 315; | |
230 | rotate (dx, dy, 135); | |
231 | if (checkdir (x, y, *dx, *dy)) | |
232 | return 90; | |
233 | rotate (dx, dy, 180); | |
234 | if (checkdir (x, y, *dx, *dy)) | |
235 | return 270; | |
236 | rotate (dx, dy, 225); | |
237 | if (checkdir (x, y, *dx, *dy)) | |
238 | return 135; | |
239 | rotate (dx, dy, 90); | |
240 | if (checkdir (x, y, *dx, *dy)) | |
241 | return 225; | |
242 | return 180; | |
243 | } | |
244 | ||
245 | /* Function add_thread(): | |
246 | * Inserts a node on the circular linked list of IPs, and initializes | |
247 | * the node as a new IP. | |
248 | */ | |
249 | int add_thread (struct iplist * ip, int dx, int dy) | |
250 | { | |
251 | struct iplist *temp; | |
252 | int i; | |
253 | ||
254 | /* Create new node on list */ | |
255 | temp = (struct iplist *) malloc (sizeof (struct iplist)); | |
256 | temp->ipid = ++ipid; /* Give an identifier */ | |
257 | temp->next = ip->next; /* Insert into list */ | |
258 | temp->x = ip->x - dx; /* Initialize based on current IP */ | |
259 | temp->y = ip->y - dy; | |
260 | temp->dx = - dx; | |
261 | temp->dy = - dy; | |
262 | temp->s_top = ip->s_top; | |
263 | for (i=0;i<ip->s_top;++i) | |
264 | temp->stack[i] = ip->stack[i]; | |
265 | ip->next = temp; | |
266 | #ifdef DEBUG | |
267 | printf ("Thread #%d created.\n", temp->ipid); | |
268 | #endif | |
269 | return 0; | |
270 | } | |
271 | ||
272 | /* Function kill_thread(): | |
273 | * Removes the current node from the circular linked list of IPs. | |
274 | */ | |
275 | int kill_thread (struct iplist ** ip) | |
276 | { | |
277 | struct iplist *temp; | |
278 | #ifdef DEBUG | |
279 | int id; | |
280 | ||
281 | id = (*ip)->ipid; | |
282 | #endif | |
283 | temp = *ip; | |
284 | while (temp->next != *ip) /* Get IP before this one */ | |
285 | temp = temp->next; | |
286 | temp->next = (*ip)->next; /* Point around the current IP */ | |
287 | free (*ip); /* Deallocate the IP */ | |
288 | *ip = temp; /* Return the previous one */ | |
289 | #ifdef DEBUG | |
290 | printf ("Thread #%d destroyed, passing to #%d.\n", id, (*ip)->ipid); | |
291 | #endif | |
292 | return 0; | |
293 | } | |
294 | ||
295 | /* Function find_far(): | |
296 | * Called when the IP has no obvious place to go. Checks the region | |
297 | * around (7x7 locations) the current IP location for a "closest | |
298 | * point" based on the current location as well as the current IP | |
299 | * direction. | |
300 | */ | |
301 | int find_far (int x, int y, int dx, int dy, int **xcoors, int **ycoors) | |
302 | { | |
303 | int i, j, pts, xs[40], ys[40], ti, tj, | |
304 | a[] = {2, 3, -2, -3, 0, 1, -1}; /* Order of precedence */ | |
305 | ||
306 | pts = 0; | |
307 | for (i=0;i<7;++i) for (j=0;j<7;++j) | |
308 | /* Scan along the array in two dimensions */ | |
309 | if (i < 4 || j < 4) /* If at least one index looks at {2,3} */ | |
310 | { | |
311 | ti = dx>0?a[i]:-a[i]; /* Invert if a delta is */ | |
312 | tj = dy>0?a[j]:-a[j]; /* negative */ | |
313 | if (x>a[i] && y>a[j] && | |
314 | workspace[x+ti][y+tj] != ' ') | |
315 | { /* If the location exists and isn't */ | |
316 | xs[pts] = x + ti; /* a space */ | |
317 | ys[pts] = y + tj; /* Add to list */ | |
318 | if (xs[pts] > 0 && ys[pts] > 0) | |
319 | ++ pts; | |
320 | } | |
321 | } | |
322 | *xcoors = (int *) malloc (sizeof (int) * pts); | |
323 | *ycoors = (int *) malloc (sizeof (int) * pts); | |
324 | for (i=0;i<pts;++i) /* Copy the list of candidates to where the */ | |
325 | { /* calling function suggests */ | |
326 | (*xcoors)[i] = xs[i]; | |
327 | (*ycoors)[i] = ys[i]; | |
328 | } | |
329 | return (pts); /* Return the number of points found */ | |
330 | } | |
331 | ||
332 | /*** Source Code for internal Interpreter Operations (called from the | |
333 | function table only ***/ | |
334 | ||
335 | /* Function nop(): | |
336 | * No-operation. | |
337 | */ | |
338 | int nop (struct iplist ** list) | |
339 | { | |
340 | return 0; /* Self-explanatory */ | |
341 | } | |
342 | ||
343 | /* Function push1(): | |
344 | * Pushes a constant value 1 onto the IP's stack. | |
345 | */ | |
346 | int push1 (struct iplist ** ip) | |
347 | { | |
348 | struct iplist *list = *ip; | |
349 | ||
350 | list->stack[list->s_top++] = 1; /* Self-explanatory */ | |
351 | return 0; | |
352 | } | |
353 | ||
354 | /* Function condition(): | |
355 | * If the top of the IP's stack is zero, functions as nop(). | |
356 | * Otherwise, it reverses the direction of the IP. | |
357 | */ | |
358 | int condition (struct iplist ** ip) | |
359 | { | |
360 | int i; | |
361 | struct iplist *list = *ip; | |
362 | ||
363 | /* Two coincident 90-degree turns spawns a new IP */ | |
364 | if (workspace[list->x-tmpx][list->y-tmpy] != ' ') | |
365 | add_thread (list, tmpx, tmpy); | |
366 | /* Otherwise, check top of the stack determines whether */ | |
367 | /* we continue or change direction */ | |
368 | else if (list->s_top && list->stack[--list->s_top]) | |
369 | { | |
370 | list->x += tmpx; | |
371 | list->y += tmpy; | |
372 | i = tmpx; /* Reflect the IP */ | |
373 | tmpx = -tmpy; | |
374 | tmpy = -i; | |
375 | i = getnextturn (list->x, list->y, &tmpx, &tmpy); | |
376 | #ifdef DEBUG | |
377 | printf ("<%d>\t", list->ipid); | |
378 | printf ("(%d,%d)\t", list->y, list->x); | |
379 | for (i=0;i<list->s_top;++i) | |
380 | printf ("[%d] ", list->stack[i]); | |
381 | printf ("\t\t%d\n", i); | |
382 | #endif | |
383 | } | |
384 | *ip = list; /* Fix the IP list in case the current thread changed */ | |
385 | return 0; | |
386 | } | |
387 | ||
388 | /* Function getput(): | |
389 | * If the top of the stack is zero, retrieves the byte stored at the | |
390 | * coordinates specified on the stack. Otherwise, takes the element | |
391 | * on the stack beneath the coordinates and stores the value at those | |
392 | * coordinates. | |
393 | */ | |
394 | int getput (struct iplist ** ip) | |
395 | { | |
396 | int xcoor, ycoor; | |
397 | struct iplist *list = *ip; | |
398 | ||
399 | if (list->s_top < 3) /* Not enough stack elements to do anything */ | |
400 | return 1; | |
401 | if (list->stack[--list->s_top]) /* A non-zero is a "put" */ | |
402 | { | |
403 | xcoor = list->stack[--list->s_top]; | |
404 | ycoor = list->stack[--list->s_top]; | |
405 | list->stack[list->s_top++] = workspace[xcoor][ycoor]; | |
406 | } | |
407 | else { /* Otherwise it's a "get" */ | |
408 | xcoor = list->stack[--list->s_top]; | |
409 | ycoor = list->stack[--list->s_top]; | |
410 | workspace[xcoor][ycoor] = list->stack[--list->s_top]; | |
411 | } | |
412 | return 0; | |
413 | } | |
414 | ||
415 | /* Function inputoutput(): | |
416 | * If the top of the stack is zero, gets a character from input. | |
417 | * Otherwise, it prints the next character on the stack. | |
418 | */ | |
419 | int inputoutput (struct iplist ** ip) | |
420 | { | |
421 | struct iplist *list = *ip; | |
422 | ||
423 | if (list->s_top < 1) /* Nothing useful on the stack */ | |
424 | return 1; | |
425 | if (list->stack[--list->s_top]) /* If it's nonzero, print the next */ | |
426 | putchar (list->stack[--list->s_top]); | |
427 | /* Otherwise request a character */ | |
428 | else list->stack[list->s_top++] = getchar (); | |
429 | return 0; | |
430 | } | |
431 | ||
432 | /* Function subtract(): | |
433 | * Subtracts the top two stack elements. | |
434 | */ | |
435 | int subtract (struct iplist ** ip) | |
436 | { | |
437 | struct iplist *list = *ip; | |
438 | ||
439 | if (list->s_top < 2) /* Can't subtract without two elements */ | |
440 | return 1; | |
441 | list->stack[list->s_top - 2] -= list->stack[list->s_top - 1]; | |
442 | --list->s_top; /* Otherwise, subtract top from under and pop */ | |
443 | return 0; | |
444 | } | |
445 | ||
446 | /* Function terminus(): | |
447 | * Based on current environmental conditions, either sparks the IP | |
448 | * across the gap, or kills the IP. | |
449 | */ | |
450 | int terminus (struct iplist ** ip) | |
451 | { | |
452 | int i, j, k, *xlist, *ylist; | |
453 | struct iplist *list = *ip; | |
454 | ||
455 | /* Check for a line to spark to */ | |
456 | j = find_far (list->x, list->y, list->dx, list->dy, &xlist, &ylist); | |
457 | #ifdef DEBUG | |
458 | for (k=0;k<j;++k) | |
459 | printf ("\t\t{%d,%d}\n", ylist[k], xlist[k]); | |
460 | #endif | |
461 | if (j < 3) /* Less than three means it's probably our */ | |
462 | { /* incoming path */ | |
463 | if (list->next == list) | |
464 | return -1; /* so kill the thread */ | |
465 | kill_thread (&list); | |
466 | ip_killed = 1; | |
467 | } | |
468 | else { /* Otherwise, we have valid locations */ | |
469 | list->x = xlist[0]; /* and they *should* be ordered */ | |
470 | list->y = ylist[0]; /* by preference */ | |
471 | i = getnextturn (list->x, list->y, &tmpx, &tmpy); | |
472 | #ifdef DEBUG | |
473 | printf ("==> %d choices available.\n", j); | |
474 | printf ("<%d>\t", list->ipid); | |
475 | printf ("(%d,%d)\t", list->y, list->x); | |
476 | for (i=0;i<list->s_top;++i) | |
477 | printf ("[%d] ", list->stack[i]); | |
478 | printf ("\t\t%d\n", i); | |
479 | #endif | |
480 | } | |
481 | *ip = list; /* Fix the list pointer in case it was changed */ | |
482 | return 0; | |
483 | } |