Hans23 Posted December 27, 2020 Share Posted December 27, 2020 (edited) Hi, I am struggling with doing things the Forth way, maybe someone here can help me out or point me to an material that'd help. I'm attempting to write a game in TurboForth. It will be a two person game where the objective of each player is to reach the base of the other player. Consider it to be a programming exercise more than the attempt at a good game, as it is my first. Anyway, here is what it looks like right now: The vertical walls with the moving gates are updated every few frames, and the code that does it looks like this: $A6 value gate-char 22 value wall-height variable gates 3 cells allot variable gate-width 5 gate-width ! variable gate-speed 10 gate-speed ! : update-gate ( n -- ) >r r@ 1 and if r@ gate@ dup r@ gate-x swap gotoxy gate-char emit dup gate-width @ + wall-height mod r@ gate-x swap gotoxy space 1+ else r@ gate@ dup r@ gate-x swap gotoxy space dup gate-width @ + wall-height mod r@ gate-x swap gotoxy gate-char emit 1- then wall-height mod r@ gate! r> drop ; : update-gates ( -- ) 4 0 do i update-gate loop ; The word that concerns me is obviously UPDATE-GATE, which moves the gate in one of the walls up or down, depending on whether its index is even or odd - I find it really hard to understand what the code does. By using the return stack to hold the gate number, things get a little easier, yet there still is a lot of stack value juggling that one needs to follow. Also, the code duplication between the up and down movement of the gate concerns me, but how could those two branches be combined into one parameterized word that, in itself, does not need to deal with many opaque stack parameters? I'm seeing it as a reoccuring issue when I write words that need to deal with multiple associated values, like the X and Y coordinate of one or multiple objects. Many of the operations involved are very simple, but the required mechanics to access values on the stack get complicated and confusing quickly. Any help or pointers would be much appreciated! Thank you, Hans Edited December 27, 2020 by Hans23 Typo 2 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/ Share on other sites More sharing options...
+Lee Stewart Posted December 27, 2020 Share Posted December 27, 2020 5 hours ago, Hans23 said: Any help or pointers would be much appreciated! Without screwing with your logic (yet!), the following changes save some code—the first 4 lines, by placement, and the last 2, by removing the return-stack value one step sooner: $A6 value gate-char 22 value wall-height variable gates 3 cells allot variable gate-width 5 gate-width ! variable gate-speed 10 gate-speed ! : update-gate ( n -- ) >r r@ 1 and if r@ gate@ \ dup r@ gate-x swap gotoxy gate-char emit r@ gate-x over gotoxy gate-char emit \ dup gate-width @ + wall-height mod r@ gate-x swap gotoxy space r@ gate-x over gate-width @ + wall-height mod gotoxy space 1+ else r@ gate@ \ dup r@ gate-x swap gotoxy space r@ gate-x over gotoxy space \ dup gate-width @ + wall-height mod r@ gate-x swap gotoxy gate-char emit r@ gate-x over gate-width @ + wall-height mod gotoxy gate-char emit 1- then \ wall-height mod r@ gate! \ r> drop ; wall-height mod r> gate! ; : update-gates ( -- ) 4 0 do i update-gate loop ; ...lee 1 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709221 Share on other sites More sharing options...
Hans23 Posted December 27, 2020 Author Share Posted December 27, 2020 Hi Lee, thank you for looking at my code! I had considered working with the data stack more, but the issue that I really have is that I then have one more value on the stack that I need to keep track of in my head in order to understand the code. I don't know if this is difficult for me because I am not used to it or if it is and just stays difficult, being the price of the simplicity of Forth. It also seems to me that my words are just too long, and making them generally smaller would make sense. What keeps me from trying to go that way is that I also find it hard to invent meaningful names, and my intuition is to keep that namespace clean. I guess that this is one of the things I need to overcome Anyway, thanks again! Any further hints, or maybe pointers to good source code to study, would be appreciated. Cheers, Hans 1 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709226 Share on other sites More sharing options...
+Lee Stewart Posted December 27, 2020 Share Posted December 27, 2020 14 minutes ago, Hans23 said: thank you for looking at my code! I had considered working with the data stack more, but the issue that I really have is that I then have one more value on the stack that I need to keep track of in my head in order to understand the code. I don't know if this is difficult for me because I am not used to it or if it is and just stays difficult, being the price of the simplicity of Forth. When stack-robatics get the least bit complicated, I keep track of the stacks (“S:” for the parameter stack and “R:” for the return stack) in comments at the right of each code line, keeping the lines simple at the expense of space: : update-gate ( n -- ) >r \ S: R:n r@ gate@ \ S:ny R:n r@ 1 and if r@ gate-x over \ S:ny nx ny R:n gotoxy gate-char emit \ S:ny R:n r@ gate-x over \ S:ny nx ny R:n gate-width @ + \ S:ny nx ny+gw R:n wall-height mod \ S:ny nx ny' R:n gotoxy space \ S:ny R:n 1+ \ S:ny+1 R:n else r@ gate-x over \ S:ny nx ny R:n gotoxy space \ S:ny R:n r@ gate-x over \ S:ny nx ny R:n gate-width @ + \ S:ny nx ny+gw R:n wall-height mod \ S:ny nx ny' R:n gotoxy gate-char emit \ S:ny R:n 1- \ S:ny-1 R:n then wall-height mod r> \ S:ny" n R: gate! ; \ S: R: [Note that I hoisted the redundant r@ gate@ out of the if construct.] 14 minutes ago, Hans23 said: It also seems to me that my words are just too long, and making them generally smaller would make sense. What keeps me from trying to go that way is that I also find it hard to invent meaningful names, and my intuition is to keep that namespace clean. I guess that this is one of the things I need to overcome You do want clarity, of course. Name length is not a big problem for the size of a program because a word’s cfa (code field address or execution token) is all that gets stored in the definition of another word. The name length does add 1 byte per character to a word’s header (padded to even cell boundary), but that should not be too onerous. There are naming guidelines most Forthers try to follow in the spirit of Forth—ideas like reusing the classic, cryptic Forth names: ! @ . ' , etc., while composing new names (as you have done in this instance). ...lee 2 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709252 Share on other sites More sharing options...
Hans23 Posted December 27, 2020 Author Share Posted December 27, 2020 Nice comment style! I'll try to use that. One thing about names in TurboForth is that they seem to be restricted to 15 characters in length, and it seems to not take it well when one tries to define a word with a long name: This caused me quite some head scratching before I realized that the limit exists. Anyway, there are some habits from the modern world that don't carry over well when going back to a small system like the TI-99/4A. Thank you again for your comment (style)! 1 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709287 Share on other sites More sharing options...
+Lee Stewart Posted December 27, 2020 Share Posted December 27, 2020 (edited) 3 hours ago, Hans23 said: Nice comment style! I'll try to use that. OK, here is my take on your update-gate : : update-gate ( n -- ) >r r@ gate@ \ S:ny R:n r@ 1 and if \ S:ny R:n **CORRECTION: dup replaced with r@ ** 1+ \ S:ny+1 R:n bl gate-char \ S:ny+1 bl gc R:n else 1- \ S:ny-1 R:n gate-char bl \ S:ny-1 gc bl R:n then r@ gate-x \ S:ny+-1 gc|bl bl|gc nx R:n r@ gate@ \ S:ny+-1 gc|bl bl|gc nx ny R:n 2dup \ S:ny+-1 gc|bl bl|gc nx ny nx ny R:n gotoxy \ S:ny+-1 gc|bl bl|gc nx ny R:n rot emit \ S:ny+-1 gc|bl nx ny R:n gate-width @ + \ S:ny+-1 gc|bl nx ny+gw R:n wall-height mod \ S:ny+-1 gc|bl nx ny' R:n gotoxy emit \ S:ny+-1 R:n wall-height mod r> \ S:ny" n R: gate! ; \ S: R: It could be a little more stack-robatics than you’d like, but there it is! ...lee Edited December 27, 2020 by Lee Stewart CORRECTION in code 3 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709314 Share on other sites More sharing options...
Willsy Posted December 27, 2020 Share Posted December 27, 2020 Factor factor factor. When it's getting hard it's normally a sign that you need to factor into smaller definitions. And don't be afraid to use global variables to store things in. It may ultimately be faster than wasting cycles just to manipulate the stack. 4 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709320 Share on other sites More sharing options...
+FarmerPotato Posted December 27, 2020 Share Posted December 27, 2020 The drawing block is so similar it could be factored. You could have an array of 2 elements, space and gate-char. The first to be emitted adds the odd-even index. The second to be emitted adds the 1-the index. 3 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709374 Share on other sites More sharing options...
+TheBF Posted December 27, 2020 Share Posted December 27, 2020 I have not tested this but to emphasize what Willsy said look how things simplify by just factoring out some of the common code from Lee's re-writes and naming them. Any time you see the same 4 or more words in a row in your code consider factoring them out into a new word that describes that function. This really is the key to making Forth simpler to use. I am sure there is more there to factor in such a long (for Forth) definition. $A6 value gate-char 22 value wall-height variable gates 3 cells allot variable gate-width 5 gate-width ! variable gate-speed 10 gate-speed ! : GATE-XY ( n -- x y) gate-x over gate-width @ + wall-height mod ; : .GATECHAR ( x y -- ) GOTOXY gate-char emit ; : update-gate ( n -- ) >r r@ 1 and if r@ gate@ r@ gate-x over .GATECHAR r@ gotoxy space 1+ else r@ gate@ r@ gate-x over gotoxy space r@ gate-xy .GATE-CHAR 1- then wall-height mod r> gate! ; : update-gates ( -- ) 4 0 do i update-gate loop ; Chuck Moore's Forth code is 1 line per definition typically. Extreme perhaps but hey it's his language. It's a very different way to think when used as designed. It's more like making a little language of words that solves your problem when you put them together in correct order. And yes it does take some time to get used to it. Some things to think about: 1. Never to try managing more than 3 parameters on the data stack. Factor out words until that is possible. If it's not possible re-think your solution or use variables. 2. Make word names that tell you what the word really does for you. It pays off since you use more function names than conventional languages. 3. Forth words can return more than one parameter. Use that as needed. When you get some free time download a copy of Thinking Forth by Leo Brodie. You have running code. Congratulations! Keep on it and it will get easier. 4 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709387 Share on other sites More sharing options...
+TheBF Posted December 27, 2020 Share Posted December 27, 2020 I was trying to think of an good example of master level Forth code and I found one. Sam Falvo's VIBE editor is mostly one liners. A thing of beauty. Vibe editor for Forth blocks (He should have used stack diagram comments if he wanted to get an 'A' grade on the paper) 2 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709392 Share on other sites More sharing options...
Willsy Posted December 27, 2020 Share Posted December 27, 2020 It is rather beautiful isn't it? I love the raw, brutal simplicity of forth. My only criticism would be the lack of stack comments. However, the definitions are so short you can easily understand them. 3 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709403 Share on other sites More sharing options...
GDMike Posted December 27, 2020 Share Posted December 27, 2020 (edited) Chuck Moore's Forth code is 1 line per definition.. really? Wow, well (KISS, keeping it short ), you know coming from other languages, we tend to cram as much as we can quickly and brutefully, this just wants to slap your grandma. I have a tough time with this, but i find myself coming back to that larger line of code, saying, but if, and adding on..so, your so right or else the WORD becomes a nightmare, like my, uh, you know the rest of the story. Edited December 27, 2020 by GDMike 2 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709431 Share on other sites More sharing options...
+TheBF Posted December 28, 2020 Share Posted December 28, 2020 I went looking for Thinking Forth myself. I think my brother-in-law has my copy. I has pleased to see there is a re-write for this century. http://thinking-forth.sourceforge.net/thinking-forth-ans.pdf 2 Quote Link to comment https://forums.atariage.com/topic/315111-forth-advice-sought/#findComment-4709970 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.