+TheBF Posted March 6, 2019 Share Posted March 6, 2019 LOL. That's a good analysis. So you have put your finger on a proper partition. I should begin thinking about overview and you can be the detail guy. Where I have an idea on a detail you can evaluate if that's how you want to build it but we can leave those decisions to you. I was feeling a little ill last night so I didn't get much accomplished but I noticed the use of ON GOSUB in the game. Here is a fast Vector CASE statement that I saw in HsForth and is also used by others. I tried to make it work with FBForth quickly bit it didn't work with <BUILDS DOES>. Perhaps because DOES> is used outside the original colon definition. ? This might useful later after everything is working. However I did play the game for a while last night and I think the speedups in Forth and the freedom to go beyond arrays will make it work well. So my first overview request is let's: "make it work, then make it better" Steve Jobs. Meaning nothing to fancy out of the gate , just use Forth, create some meta words to handle the complexity and on we go. \ FAST vector table from HsForth, Jim Kalihan (RIP) \ no speed difference versus CASE OF ENDOF etc.. for 2 items \ improves greatly with long list of cases. : CASE: ( -- -7) CREATE ; : | ( <name> ) ' , ; : ;CASE ( n -- ) DOES> OVER + + @ EXECUTE ; \ !! no runtime error checking !! \ example code: \ : FOO ." FOO" ; \ : BAR ." BAR" ; \ : FIZZ ." FIZZ" ; \ : BUZZ ." BUZZ" ; \ CASE: CHOICE ( n -- ) | FOO | BAR | FIZZ | BUZZ ;CASE \ Usage: 3 CHOICE ( executes BUZZ) \ equivalent with Eaker CASE statement \ : TEST \ CASE \ 0 OF FOO ENDOF \ 1 OF BAR ENDOF \ 2 OF FIZZ ENDOF \ 3 OF BUZZ ENDOF \ ENDCASE ; Quote Link to comment Share on other sites More sharing options...
+TheBF Posted March 6, 2019 Share Posted March 6, 2019 (edited) "Also pondered how to handle restoring background when pieces are moved. Thought of keeping a screen copy in RAM to grab those background pieces—only need 640 bytes. There must be a way to simplify handling this 10x10 board with its 3x2 “squares”—even with its forbidden zones." Yes you could even create a screen stack in VDP ram using a single variable pointer and the BUFFER word for the transfers. It would let you save/restore previous screens quickly. \ untested idea (correct word names for FBForth names) HEX 2000 VARIABLE SCRSTK 300 CONSTANT $300 : PUSHSCR SCRTOP @ 79 BUFFER $300 VSBR 79 BUFFER SCRSTK $300 VSBW $300 SCRSTK +1 ; : POPSCR SCRSTK 79 BUFFER $300 VSBR 79 BUFFER SCRTOP $300 VSBW $300 MINUS SCRSTK +! ; To manage the screen and piece movement it would be nice to have a set of words that lets you abstract all that detail away for moving things around. : PIECE: ( arg arg arg arg -- ) <BUILDS .... \ build a data structure of a given piece with all fields DOES> ( return my address ; \ From Wikipedia \ RANK NAME COUNT FEATURE \ --------------------------------------------- \ B Bomb 6 Immovable; defeats any attacking piece except Miner \ 10 or 1 Marshal 1 Can be captured by the Spy \ 9 or 2 General 1 \ 8 or 3 Colonel 2 \ 7 or 4 Major 3 \ 6 or 5 Captain 4 \ 5 or 6 Lieutenant 4 \ 4 or 7 Sergeant 4 \ 3 or 8 Miner 5 Can defuse bombs \ 2 or 9 Scout 8 Can move any distance in a straight line, without leaping over pieces / lakes \ 1 or S Spy 1 Can defeat the Marshal, but only if the Spy makes the attack \ F Flag 1 : SHAPE: ( n n n n n n -- ) <BUILDS , , , , , , DOES> ; HEX A0 A1 A2 A3 A4 A5 A6 SHAPE: ABOMB A7 A8 A9 AA AB AC AD SHAPE: AMARSHAL \ piece type just return the correct args to make a piece \ rank1 rank2 motion special shape \ ----- ----- ------- ------- ----- B B 0 0 ABOMB PIECE: BOMB 10 1 1 S AMARSHAL PIECE: Marshal 8 3 1 0 AGENEAL PIECE: General 7 4 1 0 AMAJOR PIECE: Major \ simple access to piece fields : _RANK1 ( piece -- addr) ; : _RANK2 ( piece -- addr) 2+ ; : _MOTION ( piece -- addr) 4 + ; : _special ( piece -- addr) 6 + ; : _shape ( piece -- addr) 8 + ; \ usage BOMB _RANK1 @ . Marshal MOTION @ . : DRAW-PIECE ( x y piece -- ) _SHAPE @ PLACE-PIECE ... ; : MOVE-PIECE ( X Y piece -- ) ERASE-PIECE _SHAPE @ DRAW-PIECE ... ; \ etc... Not fully thought out, but this is a way to make it more readable than using array indices. Edited March 6, 2019 by TheBF 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 6, 2019 Author Share Posted March 6, 2019 LOL. That's a good analysis. So you have put your finger on a proper partition. I should begin thinking about overview and you can be the detail guy. Where I have an idea on a detail you can evaluate if that's how you want to build it but we can leave those decisions to you. I was feeling a little ill last night so I didn't get much accomplished but I noticed the use of ON GOSUB in the game. Here is a fast Vector CASE statement that I saw in HsForth and is also used by others. I tried to make it work with FBForth quickly bit it didn't work with <BUILDS DOES>. Perhaps because DOES> is used outside the original colon definition. ? This might useful later after everything is working. However I did play the game for a while last night and I think the speedups in Forth and the freedom to go beyond arrays will make it work well. So my first overview request is let's: "make it work, then make it better" Steve Jobs. Meaning nothing to fancy out of the gate , just use Forth, create some meta words to handle the complexity and on we go. <snip> Sounds good to me. Re <BUILDS DOES> , what you say about the split definition is, indeed, likely, They “like” to be in the same word because DOES> compiles the address of an entry point into the inner interpreter that executes the cfa of the defining word. CREATE also may not work the way you think it does. However, one thing is definitely wrong: In fbForth 2.0 (mostly figForth-based), tick ( ' ) yields the pfa (parameter field address) of a word not its cfa (code field address). That said, tick looks for the word following it in the input stream, so you should probably use -FIND (works like BL WORD and is not immediate like tick) , the stack signature for which is ( -- false | [pfa len true] ). Here are definitions that work in fbForth 2.0: : CASE: ( -- ) <BUILDS 0 , DOES> OVER + + @ EXECUTE ; : | ( -- ) (IS:<name> ) -FIND IF DROP ELSE ' NOP THEN CFA , ; : ;CASE ( -- ) ; <--does nothing but look pretty The execution of a word defined by CASE: requires the option number on the stack. I could not figure out a useful function for ;CASE other than eye candy. ...lee 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 6, 2019 Author Share Posted March 6, 2019 Here is the STRATEGO blocks file with the splash screen followed by the startup screen before placement of random features: STRATEGOfbf_03.zip If you put STRATEGO on DSK2, the following will start it: USEBFL DSK2.STRATEGO 1 LOAD ...lee Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 6, 2019 Author Share Posted March 6, 2019 One more pass at the splash and opening screens: STRATEGOfbf_04.zip You can compare four different ways of handling the splash screen. The fastest is from files (be sure to point to the STRATEGO blocks file [see last post]): 1 LOAD Compare this with loading from blocks: 6 LOAD Also from blocks, but not blanking the screen, with color table loaded first: 4 LOAD and with pattern table loaded first: 5 LOAD ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted March 6, 2019 Share Posted March 6, 2019 I think we should use blocks throughout for V1.0 Make it work.... (which you have done) I like the effect of blanking the screen until the image is ready to display. Did any of my nonense about data structures resonate? (I know none of it works as is) Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 6, 2019 Author Share Posted March 6, 2019 I think we should use blocks throughout for V1.0 Make it work.... (which you have done) I like the effect of blanking the screen until the image is ready to display. Did any of my nonense about data structures resonate? (I know none of it works as is) Indeed, it did. I think that will eventually make it look like working on the 10x10 board it is—dealing with illegal moves. of course. ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted March 7, 2019 Share Posted March 7, 2019 Indeed, it did. I think that will eventually make it look like working on the 10x10 board it is—dealing with illegal moves. of course. ...lee Cool. Yes we should be able to make it look very much like talking about the game in English. (Well maybe like Yoda speaks English) :-) 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted March 7, 2019 Share Posted March 7, 2019 Lee, Here is a working version of the faster case statement. It seems to be about 2X faster than the Eaker CASE when selecting the 5th option. Might help down the road. Of course if we did the execution with DOES>ASM it would another 50% faster at least. \ Vectored CASE for FbForth : ['] -FIND SWAP DROP 0= IF ." ['] can't find" ABORT THEN CFA ; : | ['] , ; : CASE: ( -- ) 99 <BUILDS 0 , DOES> OVER + + @ EXECUTE ; : ;CASE ( -- ) 99 ?PAIRS ; \ example code: : FOO ." FOO" ; : BAR ." BAR" ; : FIZZ ." FIZZ" ; : BUZZ ." BUZZ" ; CASE: CHOICE ( n -- ) | FOO | BAR | FIZZ | BUZZ | NOP ;CASE \ Usage: 4 CHOICE ( executes BUZZ) \ equivalent with Eaker CASE statement : CHOICE2 CASE 1 OF FOO ENDOF 2 OF BAR ENDOF 3 OF FIZZ ENDOF 4 OF BUZZ ENDOF 5 OF NOP ENDOF ENDCASE ; DECIMAL : TEST1 10000 0 DO 5 CHOICE LOOP ; : TEST2 10000 0 DO 5 CHOICE2 LOOP ; 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 7, 2019 Author Share Posted March 7, 2019 Brilliant! Maybe we could use that first cell in the created word to store a choice limit. I have not figured out yet how we would do that, but .... Oh—and you can use ABORT" in ['] . ...lee 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 7, 2019 Author Share Posted March 7, 2019 Brilliant! Maybe we could use that first cell in the created word to store a choice limit. I have not figured out yet how we would do that, but .... Oh—and you can use ABORT" in ['] . ...lee OK...the following code, though a bit busy, stores a CASE: -defined word’s option count in its pfa and does runtime range checking: \ Vectored CASE for fbForth with runtime error checking : ['] -FIND SWAP DROP 0= ABORT" ['] can't find" CFA ; : | 1 LATEST PFA +! ['] , ; : CASE: ( -- ) 99 <BUILDS 0 , DOES> OVER OVER @ OVER < OVER 1 < OR ABORT" range!" + + @ EXECUTE ; : ;CASE ( -- ) 99 ?PAIRS ; ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted March 8, 2019 Share Posted March 8, 2019 (edited) Not sure how far along you are with things but here is a way to do PIECE: SHAPE: that lets you build pieces and get the parts out them as well.. I also made CREATE: which works like ANS CREATE which can be handy for defining constant arrays at compile time. The "shapes" are actually byte counted strings using BYTE, So if there are other structures that work as counted string data you can 'CREATE:" those too. \ PIECE array creation for Stratego in FbForth : CREATE: 0 VARIABLE -2 ALLOT ; \ works like ANS Create : BOUNDS OVER + SWAP ; \ handy for indexing through arrays in DO LOOPS \ creates a byte counted string from stack data : BYTES, DUP C, 0 DO C, LOOP ; : SHAPE: CREATE: 6 BYTES, ; \ 6 chars on stack 1 2 3 4 5 6 SHAPE: ABOMB \ get ALL characters from a SHAPE : _PARTS ( piece -- c c c c c c) COUNT BOUNDS DO I C@ LOOP ; Edited March 8, 2019 by TheBF 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted March 8, 2019 Author Share Posted March 8, 2019 I have done nothing but pitch horseshoes on the beach since my last post! ...lee 4 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 13, 2019 Share Posted April 13, 2019 (edited) A new word for FbForth. Sometimes you want a loop to continue until a values gets to zero. Typically you would use "0= UNTIL" like this: HEX : TEST FFFF BEGIN 1- DUP 0= UNTIL ; Although the Forth interpreter is only 3 instructions it does take time and on the old 9900 everything takes more time than you want it to. So how about we make a new compiler word that loops until zero is encountered? It's easily done by using two other words and extend the compiler. : UNTIL0 [COMPILE] WHILE [COMPILE] REPEAT ; IMMEDIATE : FASTERTEST FFFF BEGIN -1 DUP UNTIL0 ; FASTERTEST runs about 10% faster than TEST partially because the contents of the loop are small but it does remove the need to the 0= comparison as separate Forth instruction. Edited April 14, 2019 by TheBF 2 Quote Link to comment Share on other sites More sharing options...
GDMike Posted April 14, 2019 Share Posted April 14, 2019 That's tight Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 14, 2019 Author Share Posted April 14, 2019 (edited) A new word for FbForth. Sometimes you want a loop to continue until a values gets to zero. Typically you would use "0= UNTIL" like this: HEX : TEST FFFF BEGIN 1- DUP 0= UNTIL ; Although the Forth interpreter is only 3 instructions it does take time and on the old 9900 everything takes more time than you want it to. So how about we make a new compiler word that loops until zero is encountered? It's easily done by using two other words and extend the compiler. : UNTIL0 [COMPILE] WHILE [COMPILE] REPEAT ; IMMEDIATE : FASTERTEST FFFF BEGIN -1 DUP UNTIL0 ; FASTERTEST runs about 10% faster than TEST partially because the contents of the loop are small but it does remove the need to the 0= comparison as separate Forth instruction. Very nice. A few things, however: Your “1-” and “-1” should both be “1 -” “1-” Instead of “1 -”, you should use “-1 +” because it is 30 % faster TEST and FASTERTEST should probably DROP the value left on the stack after the loop [minor and not really your point] But, then, why not just use : ANOTHERTEST FFFF BEGIN 1- DUP WHILE REPEAT ; I do realize the aesthetics are not the same and UNTIL0 does make the logic neater. ...lee Edited April 14, 2019 by Lee Stewart Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted April 14, 2019 Author Share Posted April 14, 2019 OOPS! My last post is somewhat erroneous—now corrected! I forgot the word “1-”. I have had too long a hiatus! ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted April 14, 2019 Share Posted April 14, 2019 Very nice. A few things, however: Your “1-” and “-1” should both be “1 -” “1-” Instead of “1 -”, you should use “-1 +” because it is 30 % faster TEST and FASTERTEST should probably DROP the value left on the stack after the loop [minor and not really your point] But, then, why not just use : ANOTHERTEST FFFF BEGIN 1- DUP WHILE REPEAT ; I do realize the aesthetics are not the same and UNTIL0 does make the logic neater. ...lee Yes they should both be 1- I was free styling up here in the kitchen, not using real code to paste into the web. I had been thinking I wanted to make word to this and then realized that WHILE REPEAT did it for me. So yes as with all things Forth, you can decide to make a new word or not depending on how many times you need it or aesthetics as you see fit. I tried it in FbForth just to be sure the speed up was not my implementation only. B Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 8, 2019 Author Share Posted September 8, 2019 While trying to get back to porting Walid’s Stratego game, I reviewed a lot of the Forth code above to see what it was doing. So far, everything makes sense except that I got tripped up on : ['] -FIND SWAP DROP 0= ABORT" ['] can't find" CFA ; back in posts #1534 and #1536. I cannot figure out why it works because, as near as I can tell, it should fail at the SWAP if -FIND fails to locate a word and returns only 0 to the stack. I think it works because of the fortuitous 99 (check-number for ?PAIRS in ;CASE ) on the stack below the 0 (FALSE) result from -FIND , which 99 is irrelevant after ABORT" executes ABORT . Anyway, to make it more robust, I think it should be coded as follows: : ['] -FIND 0= ABORT" ['] can't find" DROP CFA ; , unless, of course, I am missing something—entirely possible. Unless the specialized error message is important, the following is shorter and will tell you which word failed: : ['] [COMPILE] ' CFA ; ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted September 8, 2019 Share Posted September 8, 2019 Yes this was my attempt to provide some meaningful messages for what will be a very big program. For reference here is my library code. It bare bones and it works fine. You could probably avoid the ['] definition and simply put it in the '|" word. : CASE: ( -- <name> ) CREATE ; : | ( <name> ) ' , ; : ;CASE ( n -- ) DOES> SWAP 2* + @ EXECUTE ; \ !! no runtime error checking !! Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 12, 2019 Author Share Posted September 12, 2019 With the above considerations, here are the latest CASE: | ;CASE definitions: : CASE: ( -- 99 ) ( IS:<name> ) \ defines choice words 99 \ for error checking by ;CASE <BUILDS \ ...compile-time action for CASE:-defined word 0 , \ reserve space for choice count and initialize to 0 DOES> ( n -- ) \ ...runtime action for CASE:-defined word 2DUP \ dup n pfa..........stack:n pfa n pfa @ \ get choice count...stack:n pfa n cnt OVER < \ cnt < n?...........stack:n pfa n f1 OVER 1 < \ n < 1?.............stack:n pfa n f1 f2 OR ABORT" range!" \ abort if either flag true..stack:n pfa n + + \ pfa + n + n = addr of cfa of choice(n) @ \ get cfa(n) EXECUTE \ execute cfa(n) ; : | ( IS:<name> ) 1 LATEST PFA +! \ increment choice count of word defined by CASE: [COMPILE] ' CFA , \ compile CFA of this choice ; : ;CASE ( -- ) 99 ?PAIRS ; \ check for 99 from CASE:..else error ...lee 3 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 12, 2019 Author Share Posted September 12, 2019 It just occurred to me that the above definition of | is a little dangerous. If the last word defined before executing | was not defined by CASE: , it will be trashed! Here is a definition for | that checks for that contingency: \ Compile CFA of next choice <name> into just-defined CASE: word : | ( n -- 99 ) ( IS:<name> ) 99 ?PAIRS \ check that latest word was defined by CASE:..else error 99 \ restore error-checking # for next | or ;CASE 1 LATEST PFA +! \ increment choice count of word defined by CASE: [COMPILE] ' CFA , \ compile CFA of <name> as this choice ; ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted September 12, 2019 Share Posted September 12, 2019 5 hours ago, Lee Stewart said: It just occurred to me that the above definition of | is a little dangerous. If the last word defined before executing | was not defined by CASE: , it will be trashed! Here is a definition for | that checks for that contingency: \ Compile CFA of next choice <name> into just-defined CASE: word : | ( n -- 99 ) ( IS:<name> ) 99 ?PAIRS \ check that latest word was defined by CASE:..else error 99 \ restore error-checking # for next | or ;CASE 1 LATEST PFA +! \ increment choice count of word defined by CASE: [COMPILE] ' CFA , \ compile CFA of <name> as this choice ; ...lee Safety first! It's very interesting to me to see how Forth has changed since '94. Many complain about the standard but there are some things that seem a little simpler to implement than FIG Forth. 1 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 28, 2019 Author Share Posted October 28, 2019 I was hoping to have Walid’s Stratego game ported to fbForth 2.0 by Chicago-Faire time, but no go—too much to do and, besides there have been too many distractions in the interim. Life does its own thing, dontcha know? Through no fault of mine (I was driving), one of our cars was totaled. Then, a month later, its new replacement was totaled—again, not my fault. Neither of us suffered any injuries, thankfully. Needless to say, though Brian and I have made significant progress that we have not posted here, fbForth Stratego is nowhere near ready for the coming weekend! Instead, what I will be presenting relates to the development of the SINPLOT program posted elsewhere in this forum. That development revealed a couple of bugs in fbForth 2.0:11 that I should have fixed by Faire time. If anyone has bugs to report, please let me know ASAP! ...lee 2 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted October 29, 2019 Author Share Posted October 29, 2019 I need to polish(?) my presentation, but I do have a tentative Build 12 I can probably distribute at the Faire if no other bugs crop up. ...lee 1 Quote Link to comment 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.