Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #60556 > unrolled thread

Starting Forth

Started bychristopherdumas@gmail.com
First post2017-06-10 07:15 -0700
Last post2017-06-10 15:50 -0700
Articles 20 on this page of 42 — 16 participants

Back to article view | Back to comp.lang.forth


Contents

  Starting Forth christopherdumas@gmail.com - 2017-06-10 07:15 -0700
    Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 07:19 -0700
    Re: Starting Forth Melzzzzz <Melzzzzz@zzzzz.com> - 2017-06-10 14:35 +0000
      Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 07:43 -0700
        Re: Starting Forth rickman <gnuarm@gmail.com> - 2017-06-11 12:44 -0400
          Re: Starting Forth christopherdumas@gmail.com - 2017-06-11 20:44 -0700
      Re: Starting Forth gavino himself <jackvanc3@gmail.com> - 2017-06-12 12:52 -0700
    Re: Starting Forth new@to.forth - 2017-06-10 15:19 +0000
      Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 08:27 -0700
        Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 08:29 -0700
          Re: Starting Forth hughaguilar96@gmail.com - 2017-06-10 15:34 -0700
            Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 15:56 -0700
              Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 15:57 -0700
                Re: Starting Forth rickman <gnuarm@gmail.com> - 2017-06-15 11:52 -0400
        Re: Starting Forth new@to.forth - 2017-06-10 21:38 +0000
          Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 15:53 -0700
          Re: Starting Forth NN <november.nihal@gmail.com> - 2017-06-12 05:36 -0700
            Re: Starting Forth christopherdumas@gmail.com - 2017-06-12 07:02 -0700
              Re: Starting Forth Julian Fondren <julian.fondren@gmail.com> - 2017-06-12 08:29 -0700
                Factor (was: Starting Forth) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-06-12 16:16 +0000
                  Re: Factor (was: Starting Forth) hughaguilar96@gmail.com - 2017-06-12 10:26 -0700
                    Re: Factor (was: Starting Forth) NN <november.nihal@gmail.com> - 2017-06-12 11:25 -0700
                      Re: Factor (was: Starting Forth) hughaguilar96@gmail.com - 2017-06-12 17:16 -0700
                    Re: Factor (was: Starting Forth) gavino himself <jackvanc3@gmail.com> - 2017-06-12 13:05 -0700
                  Re: Factor (was: Starting Forth) mhx@iae.nl - 2017-06-12 11:08 -0700
                    Re: Factor (was: Starting Forth) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2017-06-13 16:31 +0000
                Re: Starting Forth christopherdumas@gmail.com - 2017-06-14 07:49 -0700
                  Re: Starting Forth Andrew Haley <andrew29@littlepinkcloud.invalid> - 2017-06-14 11:50 -0500
                  Re: Starting Forth hughaguilar96@gmail.com - 2017-06-14 21:18 -0700
                Re: Starting Forth Cecil Bayona <cbayona@cbayona.com> - 2017-06-14 10:02 -0500
                  Re: Starting Forth Julian Fondren <julian.fondren@gmail.com> - 2017-06-14 08:49 -0700
                    Re: Starting Forth stephen@mpeforth.com (Stephen Pelc) - 2017-06-14 16:45 +0000
                  Re: Starting Forth Mark Wills <markwills1970@gmail.com> - 2017-06-14 09:05 -0700
                    Re: Starting Forth Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2017-06-14 19:05 +0100
                      Re: Starting Forth hughaguilar96@gmail.com - 2017-06-14 21:43 -0700
                        Re: Starting Forth Julian Fondren <julian.fondren@gmail.com> - 2017-06-14 22:03 -0700
                        Re: Starting Forth Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2017-06-15 21:50 +0100
      Re: Starting Forth foxaudioresearch@gmail.com - 2017-06-10 09:22 -0700
        Re: Starting Forth foxaudioresearch@gmail.com - 2017-06-10 09:40 -0700
        Re: Starting Forth Cecil Bayona <cbayona@cbayona.com> - 2017-06-10 12:21 -0500
    Re: Starting Forth Julian Fondren <julian.fondren@gmail.com> - 2017-06-10 14:30 -0700
      Re: Starting Forth christopherdumas@gmail.com - 2017-06-10 15:50 -0700

Page 1 of 3  [1] 2 3  Next page →


#60556 — Starting Forth

Fromchristopherdumas@gmail.com
Date2017-06-10 07:15 -0700
SubjectStarting Forth
Message-ID<190cd076-acbb-495e-8cac-4f7ba47680be@googlegroups.com>
Hi forthers. So I want to check out Forth for the first time, and I'm not exactly sure what implementation would be the best to use, and where I should start. I've found the GForth Manual, Starting Forth and Thinking Forth. So at least that's a start. I've also installed GForth on my Macbook through Homebrew. My question is, should I try colorForth instead? It looks awesome but I can't seem to find an ISO (or something) to run in QEMU or Bochs. Or maybe I should stick with GForth? I've heard its massively bloated compared to other Forths, though, and since I'm a Scheme fan I'd prefer a tiny language. Or should I start with Factor? I've heard its similar, but with a dev environment/IDE all its own. Do you guys have any advice? Thank you!

[toc] | [next] | [standalone]


#60557

Fromchristopherdumas@gmail.com
Date2017-06-10 07:19 -0700
Message-ID<07259c1b-2b1c-4b67-a767-b05782f2151c@googlegroups.com>
In reply to#60556
On Saturday, June 10, 2017 at 7:15:29 AM UTC-7, christop...@gmail.com wrote:
> Hi forthers. So I want to check out Forth for the first time, and I'm not exactly sure what implementation would be the best to use, and where I should start. I've found the GForth Manual, Starting Forth and Thinking Forth. So at least that's a start. I've also installed GForth on my Macbook through Homebrew. My question is, should I try colorForth instead? It looks awesome but I can't seem to find an ISO (or something) to run in QEMU or Bochs. Or maybe I should stick with GForth? I've heard its massively bloated compared to other Forths, though, and since I'm a Scheme fan I'd prefer a tiny language. Or should I start with Factor? I've heard its similar, but with a dev environment/IDE all its own. Do you guys have any advice? Thank you!

If knowing my programming background would help, I'm most comfortable programming in Scheme and Javascript, with C and C++ coming after that, and Ruby and Python after that. I prefer to program functionally in most programming languages if allowed, but if another paradigm is more idiomatic (like OO in Ruby) I always make sure learn to use that paradigm.

[toc] | [prev] | [next] | [standalone]


#60558

FromMelzzzzz <Melzzzzz@zzzzz.com>
Date2017-06-10 14:35 +0000
Message-ID<ohh02o$oeh$4@news.albasani.net>
In reply to#60556
On 2017-06-10, christopherdumas@gmail.com <christopherdumas@gmail.com> wrote:
> Hi forthers. So I want to check out Forth for the first time, and I'm
> not exactly sure what implementation would be the best to use, and
> where I should start. I've found the GForth Manual, Starting Forth and
> Thinking Forth. So at least that's a start. I've also installed GForth
> on my Macbook through Homebrew. My question is, should I try
> colorForth instead? It looks awesome but I can't seem to find an ISO
> (or something) to run in QEMU or Bochs. Or maybe I should stick with
> GForth? I've heard its massively bloated compared to other Forths,
> though, and since I'm a Scheme fan I'd prefer a tiny language. Or
> should I start with Factor? I've heard its similar, but with a dev
> environment/IDE all its own. Do you guys have any advice? Thank you!
Scheme is huge bloatware in comparison to any Forth. So don' t let that
criteria leads you in choice.

-- 
press any key to continue or any other to quit...

[toc] | [prev] | [next] | [standalone]


#60559

Fromchristopherdumas@gmail.com
Date2017-06-10 07:43 -0700
Message-ID<5f966aba-d3c1-4602-94ab-57b2c148a2ce@googlegroups.com>
In reply to#60558
Based on size, yes, but not based on numbers of built-in operations for R5RS Scheme. All I'm really looking for is something that won't overwhelm me with stuff I have to memorize or look in the manual for. It doesn't really matter that much, though. I'm just not sure which of the 2.127 million versions of Forth I should use. (:

[toc] | [prev] | [next] | [standalone]


#60615

Fromrickman <gnuarm@gmail.com>
Date2017-06-11 12:44 -0400
Message-ID<ohjrqp$f4b$1@dont-email.me>
In reply to#60559
christopherdumas@gmail.com wrote on 6/10/2017 10:43 AM:
> Based on size, yes, but not based on numbers of built-in operations for R5RS Scheme. All I'm really looking for is something that won't overwhelm me with stuff I have to memorize or look in the manual for. It doesn't really matter that much, though. I'm just not sure which of the 2.127 million versions of Forth I should use. (:

If you don't want to have to memorize or read the manual, I think you are 
out of luck with Forth.  Most of the learning consists of finding and using 
appropriate words for your project.  Once you come up to speed on the words 
you need (as least the N most common ones) you can do most of your work with 
less frequent dictionary searching.  But Forth is *all about* learning the 
not so common words and ways that make it so unique.

For example, input and output use about a dozen words, but they are not at 
all like the functions of other languages.  Math has some dozen or two, but 
again, not much in common with other languages (consider how extended 
precision intermediates and modulo arithmetic is handled).  Lather, rinse, 
repeat with other areas of Forth.

In fact, the book Starting Forth presents much of this with an organization 
based around the functional groupings of the dictionary.  If you learn 
everything presented in that book, you get a very good start.  But you will 
still need to refer to the standard document to find new words that help you 
do your jobs more effectively.

-- 

Rick C

[toc] | [prev] | [next] | [standalone]


#60637

Fromchristopherdumas@gmail.com
Date2017-06-11 20:44 -0700
Message-ID<17b77041-4c11-44ae-8c40-e6b095628ea3@googlegroups.com>
In reply to#60615
I'm apologise if this seems contradictory to what I said earlier, or if my earlier statements were unclear (I'm not a good spur-of-the-moment writer), but I don't mind memorizing words/commands AT ALL. What I'm trying to avoid is a weird, bloated language like C++ or CLISP that has tons of exceptions and sub-languages, etc. Anyway, I've adopted GForth and absolutely LOVING it.

[toc] | [prev] | [next] | [standalone]


#60668

Fromgavino himself <jackvanc3@gmail.com>
Date2017-06-12 12:52 -0700
Message-ID<a118047a-2923-44b9-b50b-f901622855c2@googlegroups.com>
In reply to#60558
On Saturday, June 10, 2017 at 10:35:06 AM UTC-4, Melzzzzz wrote:
> On 2017-06-10, christopherdumas@gmail.com <christopherdumas@gmail.com> wrote:
> > Hi forthers. So I want to check out Forth for the first time, and I'm
> > not exactly sure what implementation would be the best to use, and
> > where I should start. I've found the GForth Manual, Starting Forth and
> > Thinking Forth. So at least that's a start. I've also installed GForth
> > on my Macbook through Homebrew. My question is, should I try
> > colorForth instead? It looks awesome but I can't seem to find an ISO
> > (or something) to run in QEMU or Bochs. Or maybe I should stick with
> > GForth? I've heard its massively bloated compared to other Forths,
> > though, and since I'm a Scheme fan I'd prefer a tiny language. Or
> > should I start with Factor? I've heard its similar, but with a dev
> > environment/IDE all its own. Do you guys have any advice? Thank you!
> Scheme is huge bloatware in comparison to any Forth. So don' t let that
> criteria leads you in choice.
> 
> -- 
> press any key to continue or any other to quit...

awesome!!!

[toc] | [prev] | [next] | [standalone]


#60561

Fromnew@to.forth
Date2017-06-10 15:19 +0000
Message-ID<ohh2mm$jeu$1@gioia.aioe.org>
In reply to#60556
> Hi forthers. So I want to check out Forth for the first time, and
> I'm not e xactly sure what implementation would be the best to
> use, and where I shoul d start. I've found the GForth Manual,
> Starting Forth and Thinking Forth. S o at least that's a start.
> I've also installed GForth on my Macbook through Homebrew. My
> question is, should I try colorForth instead? It looks awesom e
> but I can't seem to find an ISO (or something) to run in QEMU or
> Bochs. O r maybe I should stick with GForth? I've heard its
> massively bloated compar ed to other Forths, though, and since
> I'm a Scheme fan I'd prefer a tiny la nguage. Or should I start
> with Factor? I've heard its similar, but with a d ev environment/IDE
> all its own. Do you guys have any advice? Thank you!

I'm at a similar place WRT learning Forth.  I'm mostly using Starting
Forth as a text but, as has been pointed out by others here, the book
contains some dated materials.  Pretty much you can skip the block-files
section; would only be useful now on systems without an operation system.
Also the information on the return stack is missleading, at least in the
earlier versions of the book.  Other than that Starting Forth is pretty
good in my opinion.

As for Forths, I'm mostly using gforth as it's available for most systems
without a bunch of dependencies and it's a modern Forth.  It even runs on
Android so you can do Forth instead of listening in those manditory office
meetings. ;)  Other Forths I'm using are pforth and ff, but both of those
are more tempermental and missing some common Forth words, ie. ff doesn't
have LEAVE even though it's a core word.

Some other free resources I've found helpful:

http://forth-standard.org/
http://field-theory.org/articles/starting-forth/index.html
http://galileo.phys.virginia.edu/classes/551.jvn.fall01/primer.htm
http://www.mpeforth.com/arena/ProgramForth.pdf

[toc] | [prev] | [next] | [standalone]


#60562

Fromchristopherdumas@gmail.com
Date2017-06-10 08:27 -0700
Message-ID<6dd217bf-ba96-4359-8d89-5eb584a9b1ea@googlegroups.com>
In reply to#60561
On Saturday, June 10, 2017 at 8:19:54 AM UTC-7, n...@to.forth wrote:
> > Hi forthers. So I want to check out Forth for the first time, and
> > I'm not e xactly sure what implementation would be the best to
> > use, and where I shoul d start. I've found the GForth Manual,
> > Starting Forth and Thinking Forth. S o at least that's a start.
> > I've also installed GForth on my Macbook through Homebrew. My
> > question is, should I try colorForth instead? It looks awesom e
> > but I can't seem to find an ISO (or something) to run in QEMU or
> > Bochs. O r maybe I should stick with GForth? I've heard its
> > massively bloated compar ed to other Forths, though, and since
> > I'm a Scheme fan I'd prefer a tiny la nguage. Or should I start
> > with Factor? I've heard its similar, but with a d ev environment/IDE
> > all its own. Do you guys have any advice? Thank you!
> 
> I'm at a similar place WRT learning Forth.  I'm mostly using Starting
> Forth as a text but, as has been pointed out by others here, the book
> contains some dated materials.  Pretty much you can skip the block-files
> section; would only be useful now on systems without an operation system.
> Also the information on the return stack is missleading, at least in the
> earlier versions of the book.  Other than that Starting Forth is pretty
> good in my opinion.
> 
> As for Forths, I'm mostly using gforth as it's available for most systems
> without a bunch of dependencies and it's a modern Forth.  It even runs on
> Android so you can do Forth instead of listening in those manditory office
> meetings. ;)  Other Forths I'm using are pforth and ff, but both of those
> are more tempermental and missing some common Forth words, ie. ff doesn't
> have LEAVE even though it's a core word.
> 
> Some other free resources I've found helpful:
> 
> http://forth-standard.org/
> http://field-theory.org/articles/starting-forth/index.html
> http://galileo.phys.virginia.edu/classes/551.jvn.fall01/primer.htm
> http://www.mpeforth.com/arena/ProgramForth.pdf

What are your opinions on Factor (factorcode.org)?

[toc] | [prev] | [next] | [standalone]


#60563

Fromchristopherdumas@gmail.com
Date2017-06-10 08:29 -0700
Message-ID<cd446d89-db37-4a4c-8dce-f89f8e0739df@googlegroups.com>
In reply to#60562
On Saturday, June 10, 2017 at 8:27:59 AM UTC-7, christop...@gmail.com wrote:
> On Saturday, June 10, 2017 at 8:19:54 AM UTC-7, n...@to.forth wrote:
> > > Hi forthers. So I want to check out Forth for the first time, and
> > > I'm not e xactly sure what implementation would be the best to
> > > use, and where I shoul d start. I've found the GForth Manual,
> > > Starting Forth and Thinking Forth. S o at least that's a start.
> > > I've also installed GForth on my Macbook through Homebrew. My
> > > question is, should I try colorForth instead? It looks awesom e
> > > but I can't seem to find an ISO (or something) to run in QEMU or
> > > Bochs. O r maybe I should stick with GForth? I've heard its
> > > massively bloated compar ed to other Forths, though, and since
> > > I'm a Scheme fan I'd prefer a tiny la nguage. Or should I start
> > > with Factor? I've heard its similar, but with a d ev environment/IDE
> > > all its own. Do you guys have any advice? Thank you!
> > 
> > I'm at a similar place WRT learning Forth.  I'm mostly using Starting
> > Forth as a text but, as has been pointed out by others here, the book
> > contains some dated materials.  Pretty much you can skip the block-files
> > section; would only be useful now on systems without an operation system.
> > Also the information on the return stack is missleading, at least in the
> > earlier versions of the book.  Other than that Starting Forth is pretty
> > good in my opinion.
> > 
> > As for Forths, I'm mostly using gforth as it's available for most systems
> > without a bunch of dependencies and it's a modern Forth.  It even runs on
> > Android so you can do Forth instead of listening in those manditory office
> > meetings. ;)  Other Forths I'm using are pforth and ff, but both of those
> > are more tempermental and missing some common Forth words, ie. ff doesn't
> > have LEAVE even though it's a core word.
> > 
> > Some other free resources I've found helpful:
> > 
> > http://forth-standard.org/
> > http://field-theory.org/articles/starting-forth/index.html
> > http://galileo.phys.virginia.edu/classes/551.jvn.fall01/primer.htm
> > http://www.mpeforth.com/arena/ProgramForth.pdf
> 
> What are your opinions on Factor (factorcode.org)?

Also, on a side note, I'm looking for some kind of graphics library for GForth. Can anyone help me there? I've heard that Forth was/is good for game programming. In addition, my favorite way to learn a programming language is writing a game in it.

[toc] | [prev] | [next] | [standalone]


#60584

Fromhughaguilar96@gmail.com
Date2017-06-10 15:34 -0700
Message-ID<5ad8ddc0-52b1-4cc4-b85e-0457685b691e@googlegroups.com>
In reply to#60563
On Saturday, June 10, 2017 at 8:29:37 AM UTC-7, christop...@gmail.com wrote:
> On Saturday, June 10, 2017 at 8:27:59 AM UTC-7, christop...@gmail.com wrote:
> > What are your opinions on Factor (factorcode.org)?

I programmed in Factor a little bit, but then went back to Forth.

Factor is a dynamic-OOP language derived from Lisp, so it has tagged data. OForth also has tagged data. Both languages are good for desktop-computer programming.

I'm more into Forth because my interest is in micro-controllers.

> Also, on a side note, I'm looking for some kind of graphics library for GForth. Can anyone help me there? I've heard that Forth was/is good for game programming. In addition, my favorite way to learn a programming language is writing a game in it.

Another novice recently said the same thing, that he wanted to program a game in Forth to learn.
https://groups.google.com/forum/#!topic/comp.lang.forth/N5B1AbXqPfQ%5B1-25%5D

ANS-Forth doesn't work for games because TICKS was banned by the ANS-Forth committee. This was done presumably for the purpose of preventing common Forthers from writing games in competition with the ANS-Forth committee members.

VFX does have TICKS though, which is non-standard. Unfortunately, VFX has a bug in AT-XY that is a standard word.

I wrote a small demo game. This requires VFX because it needs TICKS available. It is playable, but because of the bug in AT-XY it scrolls off the top of the screen and you see two images of your game on the screen, which is pretty weird.

My game requires the novice-package, and it will be included in the next release of the novice-package along with my other example programs. 
This is the game:
---------------------------------------------------------------------------

\ ARENA.4TH --- derived from tiny-arena01.fs by Darin Murphy --- needs NOVICE.4TH and LIST.4TH included.

\ This file is a framework that can be used in any char-based game.
\ Put your game in another file.

\ We need to have TICKS defined, which is not ANS-Forth and can't be written in ANS-Forth.

marker arena.4th 

VFX? 0= [if]   

!!! TICKS is needed!

: ticks ( -- ms )       \ current time in milliseconds
    ...
    ;

[then]    


\ ******
\ ****** This contains SCREEN which is the array representing the screen.
\ ******

0                       \ kinds of elements in the game
    enum empty  
    enum wall           \   II
    enum ball           \   {}      \ this could be a ball, such as in BreakOut
    enum eyes           \   oo      \ this could represent the player
    enum wide-eyes      \   OO      \ this could represent the player under duress
    enum mouth          \   <>      \ this could represent a monster
    enum horz-bar       \   ==      \ this could represent a bar in a BreakOut game
    enum brick          \   ##      \ this could represent a brick in a BreakOut game
    enum treasure       \   $$      \ this could represent a bag of money
    enum vert-bar       \   []      \ this could represent a bar in a Pong game
    enum down-spike     \   \/      \ this could fall from the top of the screen
    enum up-spike       \   /\      \ this could shoot up from the bottom of the screen
constant kind-limit

\ We need to have EMPTY and WALL --- the others can be changed --- more can be added if needed.
\ Make sure that LEFT-SYMBOLS and RITE-SYMBOLS are updated too.

\ The suggestions above for what the elements represent will vary from game to game.
\ For example, DOWN-SPIKE and UP-SPIKE could be food that the player needs to consume.

\ The elements are two characters wide (they have a left and a right part).
\ The typical screen width is somewhat over twice the height, so we want wide elements.
\ Otherwise the screen would appear to be stretched out horizontally.

create left-symbols     \ must correspond to elements
    bl      c,          \ empty
    char I  c,          \ wall
    char {  c,          \ ball
    char o  c,          \ eyes
    char O  c,          \ wide-eyes
    char <  c,          \ mouth
    char [  c,          \ horz-bar
    char #  c,          \ brick
    char $  c,          \ treasure
    char =  c,          \ vert-bar
    char \  c,          \ down-spike
    char /  c,          \ up-spike
    
create rite-symbols     \ must correspond to elements
    bl      c,          \ empty
    char I  c,          \ wall
    char }  c,          \ ball
    char o  c,          \ eyes
    char O  c,          \ wide-eyes
    char >  c,          \ mouth
    char ]  c,          \ horz-bar
    char #  c,          \ brick
    char $  c,          \ treasure
    char =  c,          \ vert-bar
    char /  c,          \ down-spike
    char \  c,          \ up-spike

: check-element ( element -- element )    
    dup 0<               abort" *** SYMBOL given negative element ***"
    dup kind-limit >=    abort" *** SYMBOL given too large element ***"
    ;
    
: symbol ( element -- rite-char left-char )    
    check-element
    dup rite-symbols +  c@
    swap left-symbols +  c@ ;

35 constant horz        \ horizontal size of screen     \ half of display screen
25 constant vert        \ vertical size of screen

\ HORZ is half of the display screen because the elements are two chars wide.
\ HORZ should not be the full screen because the CR in <DISPLAY-SCREEN> would be redundant.
\ HORZ is less than the full screen so there is a margin on the right edge for data (score, clock, etc.).

horz 2 /  constant cx
vert 2 /  constant cy   \ CX and CY are the center of the screen    

c 0 horz vert ary screen    \ 0 0 is the upper-left corner 

-1 constant up 
 1 constant down
 
-1 constant left
 1 constant rite
 
\ It is traditional in games that 0 0 is the upper-left corner, not the lower-left corner like in Cartesian coordinates.
\ UP and DOWN would seem to be backwards for somebody who is assuming the first quadrant in Cartesian coordinates.
 
: traverse-screen { 'element -- }       \ 'ELEMENT ( col col-adr -- )
    vert 0 do  
        <screen  I ->                   \ -- row-adr
        horz 0 do
            I                           \ -- row-adr col
            over  I screen>             \ -- row-adr col col-adr
            'element execute            \ -- row-adr
            loop
        drop                            \ --
        loop ;
        
: <clear-screen> ( col col-adr -- )
    empty  swap c!
    drop ;

: clear-screen ( -- )                   \ fills SCREEN with EMPTY SYMBOL
    ['] <clear-screen>  traverse-screen ;

: <display-screen> ( col col-adr -- )    
    c@ symbol  emit emit                \ -- col
    horz 1- = if  cr  then 
    ;
    
: display-screen ( -- )                 \ displays SCREEN on the display screen
    0 0 at-xy                           \ AT-XY doesn't work in VFX --- but PAGE results in too much blinking
    ['] <display-screen>  traverse-screen ;
    
    
\ ******
\ ****** This contains ERASE-BOX and DRAW-BOX for drawing obstacles.
\ ******    
        
: <draw-box> { width height lx uy kind | rx dy -- }         \ KIND is typically WALL or EMPTY
    lx  width +  1 -    to rx                               \ RX is right-X, LX is left-X
    uy  height +  1-    to dy                               \ UY is upper-Y, DY is lower-Y
    rx lx ?do  
        kind  I uy screen c!                                \ up edge
        kind  I dy screen c!                                \ down edge
        loop
    dy uy ?do  
        kind  lx I screen c!                                \ left edge
        kind  rx I screen c!                                \ right edge
        loop 
    kind  rx dy screen c! ;                                 \ left-down corner was not done in the loops above
    
: erase-box ( width height lx uy -- )       \ LX UY is the upper-left corner
    empty <draw-box> ;
    
: draw-box ( width height lx uy -- )        \ LX UY is the upper-left corner
    wall <draw-box> ;
    
\ DRAW-BOX is typically done during initialization, so it doesn't have to be efficient.
\ The assumption is that boxes don't move around during the game.
\ If they do move, use ERASE-BOX to get rid of the old box, then DRAW-BOX to install the new box.
        

\ ******
\ ****** This contains PLAY-GAME that executes the user's code peiodically and exits on ESC.
\ ******    

300 value cycle         \ how many milliseconds per cycle

variable cycles         \ how many full cycles have passed      \ this needs to be initialized to 0

27 constant <esc>       \ the ascii for the ESC key

: elapsed ( start-time -- time )
    ticks  swap - ;
    
: cycled? ( start-time -- flag )    
    elapsed  cycle > ;
    
: cursor-beyond ( -- )    
    horz vert at-xy  cr ;

: play-game ( 'cycle -- )   \ 'CYCLE  ( char|false -- str|false )    
    ticks  false                                            \ -- 'cycle start-time char|false
    begin  dup <esc> <> while               
        rover execute                                       \ -- 'cycle start-time str|false
        display-screen                                      \ -- 'cycle start-time str|false
        ?dup if  
            cursor-beyond  count type  
            2drop  exit then
        dup cycled? abort" *** the 'CYCLE code took too long ***"
        begin  dup cycled? until
        1 cycles +!
        cycle +                                             \ -- 'cycle new-start-time
        key? if  key  else  false  then                     \ -- 'cycle new-start-time char|false
        repeat
    cursor-beyond  ." ESCAPE"
    3drop ;
    
\ PLAY-GAME calls 'CYCLE every CYCLE milliseconds giving it the most recent keypress.
\ PLAY-GAME exits if the ESC key is pressed, so ESC can't be part of the game user-interface.

\ If the key is held down, there is a delay, then it begins to repeat --- this is very clumsy.
\ It is best for the player to just tap the key rather than hold it down.    
\ The direction indicated by the key will continue to be in effect until another key is tapped.


\ ******
\ ****** This contains OBJECT and some support code.
\ ******
    
list                    \ these are objects in the game, other than WALL or EMPTY
    w field .kind       \ kind of element displayed
    w field .x          
    w field .y          \ coordinates of location
    w field .dx
    w field .dy         \ offset to move
constant object    

\ An offset is one of:  -1 0 1

: init-object ( x y kind node -- node )
    init-list >r
    r@ .kind !
    r@ .y !
    r@ .x !
    0 r@ .dy !
    0 r@ .dx !
    r> ;
    
: new-object ( x y kind -- node )    
    object alloc
    init-object ;
    
: kill-object ( node -- )
    dealloc ;
    
: draw-object { node -- }
    node .kind @  
    node .x @  node .y @  screen c! ;

: erase-object { node -- }
    empty
    node .x @  node .y @  screen c! ;
    
: collision? { nodeA nodeB -- flag }
    nodeA .x @  nodeB .x @  <> if  false exit then
    nodeA .y @  nodeB .y @  <> if  false exit then
    true ;
    
    
\ ******
\ ****** This contains SEEK and MOVE-OBJECT and some support code.
\ ******
    
300 value severe            \ how many full cycles pass before the monsters totally zero in on the player
                            \ if CYCLE is 100 then a SEVERE of 1000 would be 10 seconds    
    
: tweak-offset ( offset -- new-offset )             \ randomly tweaks the offset
    cycles @  severe bias  < if
        ?dup if     negate  
        else        1 rnd  2 *  1 -     then
        then ;
        
: seek { monster goal -- }                          \ sets the .DX .DY offsets for the monster
    goal .x @  monster .x @  -  sgn  tweak-offset  monster .dx !
    goal .y @  monster .y @  -  sgn  tweak-offset  monster .dy ! ;
    
\ When CYCLES is low (early in the game) the chance of it being < the RND value is high, so the monster changes direction.
\ As the game progresses, the chance decreases, so the monster is increasingly likely to stay aimed at the player.
\ When CYCLES reaches SEVERE the chance is zero, so the monster is totally focused on the player.
\ When changing direction, if the direction is -1 or 1 then the direction becomes opposite.
\ If the direction is zero then we randomly choose -1 or 1 as the new direction.

\ We need INIT-SEED called in the initialization, because TWEAK-OFFSET uses RND above.

: move-object { node -- }               \ needs .DX .DY set, adjusts .X .Y      \ doesn't move into WALL
    node .x @  node .dx @  +            \ -- x
    node .y @  node .dy @  +            \ -- x y
    2dup screen c@  wall = if   
        2drop                           \ leave object unmoved if there is a WALL in front of it
    else  
        node .y !  node .x !            \ move object, possibly running into another object
        then ;
        
    
\ ******
\ ****** This is a small example game --- it is kept simple for educational purposes.
\ ****** The player has to run over all the treasures before the monsters run over him.
\ ****** The player is displayed eyes oo early in the game, then becomes wide-eyes OO as the monsters' aggression increases
\ ****** The monsters are mouths <> and the treasures are money-bags: $$
\ ****** Initially the monsters are biased to moving away from the player, but increasingly
\ ****** become biased to moving toward the player. At SEVERE full cycles they totally go after the player.
\ ****** Anybody writing a game should put it in another file, unless it is a direct upgrade of this game.
\ ******    

variable treasures          \ list of treasures
variable monsters           \ list of monsters
variable player             \ the player

: <guide-player> ( dx dy -- )       \ sets the .DX .DY offsets for the player
    player @ .dy !
    player @ .dx ! ;
    
<switch                             \ PLAY-GAME also uses the <ESC> key to escape
    :noname  drop    1  0 <guide-player> ;      char l  swof        \ right
    :noname  drop   -1  0 <guide-player> ;      char k  swof        \ left
    :noname  drop    0 -1 <guide-player> ;      char q  swof        \ up
    :noname  drop    0  1 <guide-player> ;      char a  swof        \ down
    :noname  drop ;  fast-switch> guide-player ( char|false -- )

: init-obstacles ( -- )                                 \ assumes CLEAR-SCREEN already done
    horz vert 0 0 draw-box                              \ border
    1 7 cx 2 - cy 3 - draw-box                          \ left rail   
    1 7 cx 2 + cy 3 - draw-box                          \ right rail
    4 7 cx 11 - cy 7 - draw-box                         \ left box
    4 7 cx 8 + cy 1 + draw-box                          \ right box
    ;
    
: init-treasures ( -- node )
    0
    cx      cy          treasure new-object link        \ center treasure
    cx 5 -  cy 3 -      treasure new-object link        \ left treasure
    cx 5 +  cy 3 +      treasure new-object link        \ right treasure
    ;

: init-monsters ( -- node )
    0
    cx 5 -  cy 7 -      mouth new-object link           \ upper-left monster
    cx 5 -  cy 7 +      mouth new-object link           \ upper-right monster
    cx 5 -  cy 3 +      mouth new-object link           \ middle-left monster
    cx 5 +  cy 3 -      mouth new-object link           \ middle-right monster
    cx 5 +  cy 7 -      mouth new-object link           \ lower-left monster
    cx 5 +  cy 7 +      mouth new-object link           \ lower-right monster
    ;
    
: init-player ( -- node )    
    1       1           eyes new-object ;
    
: init-game ( -- )
    page
    1 seed !  \ init-seed
    0 cycles ! 
    clear-screen  
    init-obstacles  
    init-treasures      dup treasures !     ['] draw-object  each
    init-monsters       dup monsters !      ['] draw-object  each
    init-player         dup player !        draw-object
    display-screen ;
    
: maybe-remove-treasure { node -- }                     \ NODE must be in the TREASURES list
    node  player @ collision? if
        treasures @  node  remove                       \ -- new-head node
        dup erase-object  kill-object                   \ -- new-head node
        treasures !  then ;
        
: taken-all-treasure? ( -- flag )
    treasures @  ['] maybe-remove-treasure  each
    treasures @  0= ;
        
: <eaten-by-monster?> ( flag node -- new-flag )         \ NODE must be in the MONSTERS list
    player @ collision?  or ;

: eaten-by-monster? ( -- flag )        
    false 
    monsters @  ['] <eaten-by-monster?>   each ;
        
: guide-monster ( node -- )                             \ sets the .DX .DY offsets for the monster
    player @  seek ;
    
: erase-movers ( -- )                                   \ the monsters and the player can move
    monsters @      ['] erase-object    each
    player @        erase-object 
    ;
    
: move-monsters ( -- )    
    monsters @      ['] guide-monster   each
    monsters @      ['] move-object     each            \ monsters can run into each other and occupy the same space
    ;
    
: move-player ( char|false -- )    
    guide-player
    player @        move-object
    ;
        
: draw-all ( -- )                                       \ treasures, monsters and the player
    treasures @     ['] draw-object     each            \ treasures first so a monster can overwrite it
    monsters @      ['] draw-object     each
    player @        draw-object
    ;    
    
\ DRAW-ALL redraws the treasures in case a monster over-wrote it previously.    
\ The treasures are drawn first, so if a monster is there the monster will over-write it in the display.
    
: <main> ( char|false -- str|false )
    cycles @  severe 4 /  >= if                         \ the monsters are becoming increasingly aggressive
        wide-eyes  player @ .kind !  then       
    erase-movers                                        \ -- char|false
    move-monsters                                       \ -- char|false
    move-player                                         \ --
    draw-all                                            \ --
    taken-all-treasure? if  c" WIN!  :-D "  exit then
    eaten-by-monster?  if   c" LOSE  :-( "  exit then
    false ;

\ Monsters can run into other monsters or the treasure and occupy the same space. 
\ If a monster is on top of a treasure, the monster is displayed (because monsters are drawn after treasures).
\ Neither monsters nor the player can occupy the same space as a wall.        
    
: main ( -- )    
    init-game
    begin  key? until                                   \ don't begin game until player presses a key
    ['] <main>  play-game 
    treasures @     ['] kill-object  each
    monsters @      ['] kill-object  each
    player @        kill-object ;

[toc] | [prev] | [next] | [standalone]


#60587

Fromchristopherdumas@gmail.com
Date2017-06-10 15:56 -0700
Message-ID<2ccde611-7eb6-4b6b-a3cf-6b845f9e500a@googlegroups.com>
In reply to#60584
On Saturday, June 10, 2017 at 3:34:38 PM UTC-7, hughag...@gmail.com wrote:
> On Saturday, June 10, 2017 at 8:29:37 AM UTC-7, christop...@gmail.com wrote:
> > On Saturday, June 10, 2017 at 8:27:59 AM UTC-7, christop...@gmail.com wrote:
> > > What are your opinions on Factor (factorcode.org)?
> 
> I programmed in Factor a little bit, but then went back to Forth.
> 
> Factor is a dynamic-OOP language derived from Lisp, so it has tagged data. OForth also has tagged data. Both languages are good for desktop-computer programming.
> 
> I'm more into Forth because my interest is in micro-controllers.
> 
> > Also, on a side note, I'm looking for some kind of graphics library for GForth. Can anyone help me there? I've heard that Forth was/is good for game programming. In addition, my favorite way to learn a programming language is writing a game in it.
> 
> Another novice recently said the same thing, that he wanted to program a game in Forth to learn.
> https://groups.google.com/forum/#!topic/comp.lang.forth/N5B1AbXqPfQ%5B1-25%5D
> 
> ANS-Forth doesn't work for games because TICKS was banned by the ANS-Forth committee. This was done presumably for the purpose of preventing common Forthers from writing games in competition with the ANS-Forth committee members.
> 
> VFX does have TICKS though, which is non-standard. Unfortunately, VFX has a bug in AT-XY that is a standard word.
> 
> I wrote a small demo game. This requires VFX because it needs TICKS available. It is playable, but because of the bug in AT-XY it scrolls off the top of the screen and you see two images of your game on the screen, which is pretty weird.
> 
> My game requires the novice-package, and it will be included in the next release of the novice-package along with my other example programs. 
> This is the game:
> ---------------------------------------------------------------------------
> 
> \ ARENA.4TH --- derived from tiny-arena01.fs by Darin Murphy --- needs NOVICE.4TH and LIST.4TH included.
> 
> \ This file is a framework that can be used in any char-based game.
> \ Put your game in another file.
> 
> \ We need to have TICKS defined, which is not ANS-Forth and can't be written in ANS-Forth.
> 
> marker arena.4th 
> 
> VFX? 0= [if]   
> 
> !!! TICKS is needed!
> 
> : ticks ( -- ms )       \ current time in milliseconds
>     ...
>     ;
> 
> [then]    
> 
> 
> \ ******
> \ ****** This contains SCREEN which is the array representing the screen.
> \ ******
> 
> 0                       \ kinds of elements in the game
>     enum empty  
>     enum wall           \   II
>     enum ball           \   {}      \ this could be a ball, such as in BreakOut
>     enum eyes           \   oo      \ this could represent the player
>     enum wide-eyes      \   OO      \ this could represent the player under duress
>     enum mouth          \   <>      \ this could represent a monster
>     enum horz-bar       \   ==      \ this could represent a bar in a BreakOut game
>     enum brick          \   ##      \ this could represent a brick in a BreakOut game
>     enum treasure       \   $$      \ this could represent a bag of money
>     enum vert-bar       \   []      \ this could represent a bar in a Pong game
>     enum down-spike     \   \/      \ this could fall from the top of the screen
>     enum up-spike       \   /\      \ this could shoot up from the bottom of the screen
> constant kind-limit
> 
> \ We need to have EMPTY and WALL --- the others can be changed --- more can be added if needed.
> \ Make sure that LEFT-SYMBOLS and RITE-SYMBOLS are updated too.
> 
> \ The suggestions above for what the elements represent will vary from game to game.
> \ For example, DOWN-SPIKE and UP-SPIKE could be food that the player needs to consume.
> 
> \ The elements are two characters wide (they have a left and a right part).
> \ The typical screen width is somewhat over twice the height, so we want wide elements.
> \ Otherwise the screen would appear to be stretched out horizontally.
> 
> create left-symbols     \ must correspond to elements
>     bl      c,          \ empty
>     char I  c,          \ wall
>     char {  c,          \ ball
>     char o  c,          \ eyes
>     char O  c,          \ wide-eyes
>     char <  c,          \ mouth
>     char [  c,          \ horz-bar
>     char #  c,          \ brick
>     char $  c,          \ treasure
>     char =  c,          \ vert-bar
>     char \  c,          \ down-spike
>     char /  c,          \ up-spike
>     
> create rite-symbols     \ must correspond to elements
>     bl      c,          \ empty
>     char I  c,          \ wall
>     char }  c,          \ ball
>     char o  c,          \ eyes
>     char O  c,          \ wide-eyes
>     char >  c,          \ mouth
>     char ]  c,          \ horz-bar
>     char #  c,          \ brick
>     char $  c,          \ treasure
>     char =  c,          \ vert-bar
>     char /  c,          \ down-spike
>     char \  c,          \ up-spike
> 
> : check-element ( element -- element )    
>     dup 0<               abort" *** SYMBOL given negative element ***"
>     dup kind-limit >=    abort" *** SYMBOL given too large element ***"
>     ;
>     
> : symbol ( element -- rite-char left-char )    
>     check-element
>     dup rite-symbols +  c@
>     swap left-symbols +  c@ ;
> 
> 35 constant horz        \ horizontal size of screen     \ half of display screen
> 25 constant vert        \ vertical size of screen
> 
> \ HORZ is half of the display screen because the elements are two chars wide.
> \ HORZ should not be the full screen because the CR in <DISPLAY-SCREEN> would be redundant.
> \ HORZ is less than the full screen so there is a margin on the right edge for data (score, clock, etc.).
> 
> horz 2 /  constant cx
> vert 2 /  constant cy   \ CX and CY are the center of the screen    
> 
> c 0 horz vert ary screen    \ 0 0 is the upper-left corner 
> 
> -1 constant up 
>  1 constant down
>  
> -1 constant left
>  1 constant rite
>  
> \ It is traditional in games that 0 0 is the upper-left corner, not the lower-left corner like in Cartesian coordinates.
> \ UP and DOWN would seem to be backwards for somebody who is assuming the first quadrant in Cartesian coordinates.
>  
> : traverse-screen { 'element -- }       \ 'ELEMENT ( col col-adr -- )
>     vert 0 do  
>         <screen  I ->                   \ -- row-adr
>         horz 0 do
>             I                           \ -- row-adr col
>             over  I screen>             \ -- row-adr col col-adr
>             'element execute            \ -- row-adr
>             loop
>         drop                            \ --
>         loop ;
>         
> : <clear-screen> ( col col-adr -- )
>     empty  swap c!
>     drop ;
> 
> : clear-screen ( -- )                   \ fills SCREEN with EMPTY SYMBOL
>     ['] <clear-screen>  traverse-screen ;
> 
> : <display-screen> ( col col-adr -- )    
>     c@ symbol  emit emit                \ -- col
>     horz 1- = if  cr  then 
>     ;
>     
> : display-screen ( -- )                 \ displays SCREEN on the display screen
>     0 0 at-xy                           \ AT-XY doesn't work in VFX --- but PAGE results in too much blinking
>     ['] <display-screen>  traverse-screen ;
>     
>     
> \ ******
> \ ****** This contains ERASE-BOX and DRAW-BOX for drawing obstacles.
> \ ******    
>         
> : <draw-box> { width height lx uy kind | rx dy -- }         \ KIND is typically WALL or EMPTY
>     lx  width +  1 -    to rx                               \ RX is right-X, LX is left-X
>     uy  height +  1-    to dy                               \ UY is upper-Y, DY is lower-Y
>     rx lx ?do  
>         kind  I uy screen c!                                \ up edge
>         kind  I dy screen c!                                \ down edge
>         loop
>     dy uy ?do  
>         kind  lx I screen c!                                \ left edge
>         kind  rx I screen c!                                \ right edge
>         loop 
>     kind  rx dy screen c! ;                                 \ left-down corner was not done in the loops above
>     
> : erase-box ( width height lx uy -- )       \ LX UY is the upper-left corner
>     empty <draw-box> ;
>     
> : draw-box ( width height lx uy -- )        \ LX UY is the upper-left corner
>     wall <draw-box> ;
>     
> \ DRAW-BOX is typically done during initialization, so it doesn't have to be efficient.
> \ The assumption is that boxes don't move around during the game.
> \ If they do move, use ERASE-BOX to get rid of the old box, then DRAW-BOX to install the new box.
>         
> 
> \ ******
> \ ****** This contains PLAY-GAME that executes the user's code peiodically and exits on ESC.
> \ ******    
> 
> 300 value cycle         \ how many milliseconds per cycle
> 
> variable cycles         \ how many full cycles have passed      \ this needs to be initialized to 0
> 
> 27 constant <esc>       \ the ascii for the ESC key
> 
> : elapsed ( start-time -- time )
>     ticks  swap - ;
>     
> : cycled? ( start-time -- flag )    
>     elapsed  cycle > ;
>     
> : cursor-beyond ( -- )    
>     horz vert at-xy  cr ;
> 
> : play-game ( 'cycle -- )   \ 'CYCLE  ( char|false -- str|false )    
>     ticks  false                                            \ -- 'cycle start-time char|false
>     begin  dup <esc> <> while               
>         rover execute                                       \ -- 'cycle start-time str|false
>         display-screen                                      \ -- 'cycle start-time str|false
>         ?dup if  
>             cursor-beyond  count type  
>             2drop  exit then
>         dup cycled? abort" *** the 'CYCLE code took too long ***"
>         begin  dup cycled? until
>         1 cycles +!
>         cycle +                                             \ -- 'cycle new-start-time
>         key? if  key  else  false  then                     \ -- 'cycle new-start-time char|false
>         repeat
>     cursor-beyond  ." ESCAPE"
>     3drop ;
>     
> \ PLAY-GAME calls 'CYCLE every CYCLE milliseconds giving it the most recent keypress.
> \ PLAY-GAME exits if the ESC key is pressed, so ESC can't be part of the game user-interface.
> 
> \ If the key is held down, there is a delay, then it begins to repeat --- this is very clumsy.
> \ It is best for the player to just tap the key rather than hold it down.    
> \ The direction indicated by the key will continue to be in effect until another key is tapped.
> 
> 
> \ ******
> \ ****** This contains OBJECT and some support code.
> \ ******
>     
> list                    \ these are objects in the game, other than WALL or EMPTY
>     w field .kind       \ kind of element displayed
>     w field .x          
>     w field .y          \ coordinates of location
>     w field .dx
>     w field .dy         \ offset to move
> constant object    
> 
> \ An offset is one of:  -1 0 1
> 
> : init-object ( x y kind node -- node )
>     init-list >r
>     r@ .kind !
>     r@ .y !
>     r@ .x !
>     0 r@ .dy !
>     0 r@ .dx !
>     r> ;
>     
> : new-object ( x y kind -- node )    
>     object alloc
>     init-object ;
>     
> : kill-object ( node -- )
>     dealloc ;
>     
> : draw-object { node -- }
>     node .kind @  
>     node .x @  node .y @  screen c! ;
> 
> : erase-object { node -- }
>     empty
>     node .x @  node .y @  screen c! ;
>     
> : collision? { nodeA nodeB -- flag }
>     nodeA .x @  nodeB .x @  <> if  false exit then
>     nodeA .y @  nodeB .y @  <> if  false exit then
>     true ;
>     
>     
> \ ******
> \ ****** This contains SEEK and MOVE-OBJECT and some support code.
> \ ******
>     
> 300 value severe            \ how many full cycles pass before the monsters totally zero in on the player
>                             \ if CYCLE is 100 then a SEVERE of 1000 would be 10 seconds    
>     
> : tweak-offset ( offset -- new-offset )             \ randomly tweaks the offset
>     cycles @  severe bias  < if
>         ?dup if     negate  
>         else        1 rnd  2 *  1 -     then
>         then ;
>         
> : seek { monster goal -- }                          \ sets the .DX .DY offsets for the monster
>     goal .x @  monster .x @  -  sgn  tweak-offset  monster .dx !
>     goal .y @  monster .y @  -  sgn  tweak-offset  monster .dy ! ;
>     
> \ When CYCLES is low (early in the game) the chance of it being < the RND value is high, so the monster changes direction.
> \ As the game progresses, the chance decreases, so the monster is increasingly likely to stay aimed at the player.
> \ When CYCLES reaches SEVERE the chance is zero, so the monster is totally focused on the player.
> \ When changing direction, if the direction is -1 or 1 then the direction becomes opposite.
> \ If the direction is zero then we randomly choose -1 or 1 as the new direction.
> 
> \ We need INIT-SEED called in the initialization, because TWEAK-OFFSET uses RND above.
> 
> : move-object { node -- }               \ needs .DX .DY set, adjusts .X .Y      \ doesn't move into WALL
>     node .x @  node .dx @  +            \ -- x
>     node .y @  node .dy @  +            \ -- x y
>     2dup screen c@  wall = if   
>         2drop                           \ leave object unmoved if there is a WALL in front of it
>     else  
>         node .y !  node .x !            \ move object, possibly running into another object
>         then ;
>         
>     
> \ ******
> \ ****** This is a small example game --- it is kept simple for educational purposes.
> \ ****** The player has to run over all the treasures before the monsters run over him.
> \ ****** The player is displayed eyes oo early in the game, then becomes wide-eyes OO as the monsters' aggression increases
> \ ****** The monsters are mouths <> and the treasures are money-bags: $$
> \ ****** Initially the monsters are biased to moving away from the player, but increasingly
> \ ****** become biased to moving toward the player. At SEVERE full cycles they totally go after the player.
> \ ****** Anybody writing a game should put it in another file, unless it is a direct upgrade of this game.
> \ ******    
> 
> variable treasures          \ list of treasures
> variable monsters           \ list of monsters
> variable player             \ the player
> 
> : <guide-player> ( dx dy -- )       \ sets the .DX .DY offsets for the player
>     player @ .dy !
>     player @ .dx ! ;
>     
> <switch                             \ PLAY-GAME also uses the <ESC> key to escape
>     :noname  drop    1  0 <guide-player> ;      char l  swof        \ right
>     :noname  drop   -1  0 <guide-player> ;      char k  swof        \ left
>     :noname  drop    0 -1 <guide-player> ;      char q  swof        \ up
>     :noname  drop    0  1 <guide-player> ;      char a  swof        \ down
>     :noname  drop ;  fast-switch> guide-player ( char|false -- )
> 
> : init-obstacles ( -- )                                 \ assumes CLEAR-SCREEN already done
>     horz vert 0 0 draw-box                              \ border
>     1 7 cx 2 - cy 3 - draw-box                          \ left rail   
>     1 7 cx 2 + cy 3 - draw-box                          \ right rail
>     4 7 cx 11 - cy 7 - draw-box                         \ left box
>     4 7 cx 8 + cy 1 + draw-box                          \ right box
>     ;
>     
> : init-treasures ( -- node )
>     0
>     cx      cy          treasure new-object link        \ center treasure
>     cx 5 -  cy 3 -      treasure new-object link        \ left treasure
>     cx 5 +  cy 3 +      treasure new-object link        \ right treasure
>     ;
> 
> : init-monsters ( -- node )
>     0
>     cx 5 -  cy 7 -      mouth new-object link           \ upper-left monster
>     cx 5 -  cy 7 +      mouth new-object link           \ upper-right monster
>     cx 5 -  cy 3 +      mouth new-object link           \ middle-left monster
>     cx 5 +  cy 3 -      mouth new-object link           \ middle-right monster
>     cx 5 +  cy 7 -      mouth new-object link           \ lower-left monster
>     cx 5 +  cy 7 +      mouth new-object link           \ lower-right monster
>     ;
>     
> : init-player ( -- node )    
>     1       1           eyes new-object ;
>     
> : init-game ( -- )
>     page
>     1 seed !  \ init-seed
>     0 cycles ! 
>     clear-screen  
>     init-obstacles  
>     init-treasures      dup treasures !     ['] draw-object  each
>     init-monsters       dup monsters !      ['] draw-object  each
>     init-player         dup player !        draw-object
>     display-screen ;
>     
> : maybe-remove-treasure { node -- }                     \ NODE must be in the TREASURES list
>     node  player @ collision? if
>         treasures @  node  remove                       \ -- new-head node
>         dup erase-object  kill-object                   \ -- new-head node
>         treasures !  then ;
>         
> : taken-all-treasure? ( -- flag )
>     treasures @  ['] maybe-remove-treasure  each
>     treasures @  0= ;
>         
> : <eaten-by-monster?> ( flag node -- new-flag )         \ NODE must be in the MONSTERS list
>     player @ collision?  or ;
> 
> : eaten-by-monster? ( -- flag )        
>     false 
>     monsters @  ['] <eaten-by-monster?>   each ;
>         
> : guide-monster ( node -- )                             \ sets the .DX .DY offsets for the monster
>     player @  seek ;
>     
> : erase-movers ( -- )                                   \ the monsters and the player can move
>     monsters @      ['] erase-object    each
>     player @        erase-object 
>     ;
>     
> : move-monsters ( -- )    
>     monsters @      ['] guide-monster   each
>     monsters @      ['] move-object     each            \ monsters can run into each other and occupy the same space
>     ;
>     
> : move-player ( char|false -- )    
>     guide-player
>     player @        move-object
>     ;
>         
> : draw-all ( -- )                                       \ treasures, monsters and the player
>     treasures @     ['] draw-object     each            \ treasures first so a monster can overwrite it
>     monsters @      ['] draw-object     each
>     player @        draw-object
>     ;    
>     
> \ DRAW-ALL redraws the treasures in case a monster over-wrote it previously.    
> \ The treasures are drawn first, so if a monster is there the monster will over-write it in the display.
>     
> : <main> ( char|false -- str|false )
>     cycles @  severe 4 /  >= if                         \ the monsters are becoming increasingly aggressive
>         wide-eyes  player @ .kind !  then       
>     erase-movers                                        \ -- char|false
>     move-monsters                                       \ -- char|false
>     move-player                                         \ --
>     draw-all                                            \ --
>     taken-all-treasure? if  c" WIN!  :-D "  exit then
>     eaten-by-monster?  if   c" LOSE  :-( "  exit then
>     false ;
> 
> \ Monsters can run into other monsters or the treasure and occupy the same space. 
> \ If a monster is on top of a treasure, the monster is displayed (because monsters are drawn after treasures).
> \ Neither monsters nor the player can occupy the same space as a wall.        
>     
> : main ( -- )    
>     init-game
>     begin  key? until                                   \ don't begin game until player presses a key
>     ['] <main>  play-game 
>     treasures @     ['] kill-object  each
>     monsters @      ['] kill-object  each
>     player @        kill-object ;

Nice. I'll look more thuroughly through your code later. In the meantime, I'll check out VFX Forth. Based on other recommendations here, I'm going to choose between GForth and VFX Forth.

[toc] | [prev] | [next] | [standalone]


#60588

Fromchristopherdumas@gmail.com
Date2017-06-10 15:57 -0700
Message-ID<cb190d8e-d3e8-47c5-8d5d-451196aedb3d@googlegroups.com>
In reply to#60587
On Saturday, June 10, 2017 at 3:56:23 PM UTC-7, christop...@gmail.com wrote:
> On Saturday, June 10, 2017 at 3:34:38 PM UTC-7, hughag...@gmail.com wrote:
> > On Saturday, June 10, 2017 at 8:29:37 AM UTC-7, christop...@gmail.com wrote:
> > > On Saturday, June 10, 2017 at 8:27:59 AM UTC-7, christop...@gmail.com wrote:
> > > > What are your opinions on Factor (factorcode.org)?
> > 
> > I programmed in Factor a little bit, but then went back to Forth.
> > 
> > Factor is a dynamic-OOP language derived from Lisp, so it has tagged data. OForth also has tagged data. Both languages are good for desktop-computer programming.
> > 
> > I'm more into Forth because my interest is in micro-controllers.
> > 
> > > Also, on a side note, I'm looking for some kind of graphics library for GForth. Can anyone help me there? I've heard that Forth was/is good for game programming. In addition, my favorite way to learn a programming language is writing a game in it.
> > 
> > Another novice recently said the same thing, that he wanted to program a game in Forth to learn.
> > https://groups.google.com/forum/#!topic/comp.lang.forth/N5B1AbXqPfQ%5B1-25%5D
> > 
> > ANS-Forth doesn't work for games because TICKS was banned by the ANS-Forth committee. This was done presumably for the purpose of preventing common Forthers from writing games in competition with the ANS-Forth committee members.
> > 
> > VFX does have TICKS though, which is non-standard. Unfortunately, VFX has a bug in AT-XY that is a standard word.
> > 
> > I wrote a small demo game. This requires VFX because it needs TICKS available. It is playable, but because of the bug in AT-XY it scrolls off the top of the screen and you see two images of your game on the screen, which is pretty weird.
> > 
> > My game requires the novice-package, and it will be included in the next release of the novice-package along with my other example programs. 
> > This is the game:
> > ---------------------------------------------------------------------------
> > 
> > \ ARENA.4TH --- derived from tiny-arena01.fs by Darin Murphy --- needs NOVICE.4TH and LIST.4TH included.
> > 
> > \ This file is a framework that can be used in any char-based game.
> > \ Put your game in another file.
> > 
> > \ We need to have TICKS defined, which is not ANS-Forth and can't be written in ANS-Forth.
> > 
> > marker arena.4th 
> > 
> > VFX? 0= [if]   
> > 
> > !!! TICKS is needed!
> > 
> > : ticks ( -- ms )       \ current time in milliseconds
> >     ...
> >     ;
> > 
> > [then]    
> > 
> > 
> > \ ******
> > \ ****** This contains SCREEN which is the array representing the screen.
> > \ ******
> > 
> > 0                       \ kinds of elements in the game
> >     enum empty  
> >     enum wall           \   II
> >     enum ball           \   {}      \ this could be a ball, such as in BreakOut
> >     enum eyes           \   oo      \ this could represent the player
> >     enum wide-eyes      \   OO      \ this could represent the player under duress
> >     enum mouth          \   <>      \ this could represent a monster
> >     enum horz-bar       \   ==      \ this could represent a bar in a BreakOut game
> >     enum brick          \   ##      \ this could represent a brick in a BreakOut game
> >     enum treasure       \   $$      \ this could represent a bag of money
> >     enum vert-bar       \   []      \ this could represent a bar in a Pong game
> >     enum down-spike     \   \/      \ this could fall from the top of the screen
> >     enum up-spike       \   /\      \ this could shoot up from the bottom of the screen
> > constant kind-limit
> > 
> > \ We need to have EMPTY and WALL --- the others can be changed --- more can be added if needed.
> > \ Make sure that LEFT-SYMBOLS and RITE-SYMBOLS are updated too.
> > 
> > \ The suggestions above for what the elements represent will vary from game to game.
> > \ For example, DOWN-SPIKE and UP-SPIKE could be food that the player needs to consume.
> > 
> > \ The elements are two characters wide (they have a left and a right part).
> > \ The typical screen width is somewhat over twice the height, so we want wide elements.
> > \ Otherwise the screen would appear to be stretched out horizontally.
> > 
> > create left-symbols     \ must correspond to elements
> >     bl      c,          \ empty
> >     char I  c,          \ wall
> >     char {  c,          \ ball
> >     char o  c,          \ eyes
> >     char O  c,          \ wide-eyes
> >     char <  c,          \ mouth
> >     char [  c,          \ horz-bar
> >     char #  c,          \ brick
> >     char $  c,          \ treasure
> >     char =  c,          \ vert-bar
> >     char \  c,          \ down-spike
> >     char /  c,          \ up-spike
> >     
> > create rite-symbols     \ must correspond to elements
> >     bl      c,          \ empty
> >     char I  c,          \ wall
> >     char }  c,          \ ball
> >     char o  c,          \ eyes
> >     char O  c,          \ wide-eyes
> >     char >  c,          \ mouth
> >     char ]  c,          \ horz-bar
> >     char #  c,          \ brick
> >     char $  c,          \ treasure
> >     char =  c,          \ vert-bar
> >     char /  c,          \ down-spike
> >     char \  c,          \ up-spike
> > 
> > : check-element ( element -- element )    
> >     dup 0<               abort" *** SYMBOL given negative element ***"
> >     dup kind-limit >=    abort" *** SYMBOL given too large element ***"
> >     ;
> >     
> > : symbol ( element -- rite-char left-char )    
> >     check-element
> >     dup rite-symbols +  c@
> >     swap left-symbols +  c@ ;
> > 
> > 35 constant horz        \ horizontal size of screen     \ half of display screen
> > 25 constant vert        \ vertical size of screen
> > 
> > \ HORZ is half of the display screen because the elements are two chars wide.
> > \ HORZ should not be the full screen because the CR in <DISPLAY-SCREEN> would be redundant.
> > \ HORZ is less than the full screen so there is a margin on the right edge for data (score, clock, etc.).
> > 
> > horz 2 /  constant cx
> > vert 2 /  constant cy   \ CX and CY are the center of the screen    
> > 
> > c 0 horz vert ary screen    \ 0 0 is the upper-left corner 
> > 
> > -1 constant up 
> >  1 constant down
> >  
> > -1 constant left
> >  1 constant rite
> >  
> > \ It is traditional in games that 0 0 is the upper-left corner, not the lower-left corner like in Cartesian coordinates.
> > \ UP and DOWN would seem to be backwards for somebody who is assuming the first quadrant in Cartesian coordinates.
> >  
> > : traverse-screen { 'element -- }       \ 'ELEMENT ( col col-adr -- )
> >     vert 0 do  
> >         <screen  I ->                   \ -- row-adr
> >         horz 0 do
> >             I                           \ -- row-adr col
> >             over  I screen>             \ -- row-adr col col-adr
> >             'element execute            \ -- row-adr
> >             loop
> >         drop                            \ --
> >         loop ;
> >         
> > : <clear-screen> ( col col-adr -- )
> >     empty  swap c!
> >     drop ;
> > 
> > : clear-screen ( -- )                   \ fills SCREEN with EMPTY SYMBOL
> >     ['] <clear-screen>  traverse-screen ;
> > 
> > : <display-screen> ( col col-adr -- )    
> >     c@ symbol  emit emit                \ -- col
> >     horz 1- = if  cr  then 
> >     ;
> >     
> > : display-screen ( -- )                 \ displays SCREEN on the display screen
> >     0 0 at-xy                           \ AT-XY doesn't work in VFX --- but PAGE results in too much blinking
> >     ['] <display-screen>  traverse-screen ;
> >     
> >     
> > \ ******
> > \ ****** This contains ERASE-BOX and DRAW-BOX for drawing obstacles.
> > \ ******    
> >         
> > : <draw-box> { width height lx uy kind | rx dy -- }         \ KIND is typically WALL or EMPTY
> >     lx  width +  1 -    to rx                               \ RX is right-X, LX is left-X
> >     uy  height +  1-    to dy                               \ UY is upper-Y, DY is lower-Y
> >     rx lx ?do  
> >         kind  I uy screen c!                                \ up edge
> >         kind  I dy screen c!                                \ down edge
> >         loop
> >     dy uy ?do  
> >         kind  lx I screen c!                                \ left edge
> >         kind  rx I screen c!                                \ right edge
> >         loop 
> >     kind  rx dy screen c! ;                                 \ left-down corner was not done in the loops above
> >     
> > : erase-box ( width height lx uy -- )       \ LX UY is the upper-left corner
> >     empty <draw-box> ;
> >     
> > : draw-box ( width height lx uy -- )        \ LX UY is the upper-left corner
> >     wall <draw-box> ;
> >     
> > \ DRAW-BOX is typically done during initialization, so it doesn't have to be efficient.
> > \ The assumption is that boxes don't move around during the game.
> > \ If they do move, use ERASE-BOX to get rid of the old box, then DRAW-BOX to install the new box.
> >         
> > 
> > \ ******
> > \ ****** This contains PLAY-GAME that executes the user's code peiodically and exits on ESC.
> > \ ******    
> > 
> > 300 value cycle         \ how many milliseconds per cycle
> > 
> > variable cycles         \ how many full cycles have passed      \ this needs to be initialized to 0
> > 
> > 27 constant <esc>       \ the ascii for the ESC key
> > 
> > : elapsed ( start-time -- time )
> >     ticks  swap - ;
> >     
> > : cycled? ( start-time -- flag )    
> >     elapsed  cycle > ;
> >     
> > : cursor-beyond ( -- )    
> >     horz vert at-xy  cr ;
> > 
> > : play-game ( 'cycle -- )   \ 'CYCLE  ( char|false -- str|false )    
> >     ticks  false                                            \ -- 'cycle start-time char|false
> >     begin  dup <esc> <> while               
> >         rover execute                                       \ -- 'cycle start-time str|false
> >         display-screen                                      \ -- 'cycle start-time str|false
> >         ?dup if  
> >             cursor-beyond  count type  
> >             2drop  exit then
> >         dup cycled? abort" *** the 'CYCLE code took too long ***"
> >         begin  dup cycled? until
> >         1 cycles +!
> >         cycle +                                             \ -- 'cycle new-start-time
> >         key? if  key  else  false  then                     \ -- 'cycle new-start-time char|false
> >         repeat
> >     cursor-beyond  ." ESCAPE"
> >     3drop ;
> >     
> > \ PLAY-GAME calls 'CYCLE every CYCLE milliseconds giving it the most recent keypress.
> > \ PLAY-GAME exits if the ESC key is pressed, so ESC can't be part of the game user-interface.
> > 
> > \ If the key is held down, there is a delay, then it begins to repeat --- this is very clumsy.
> > \ It is best for the player to just tap the key rather than hold it down.    
> > \ The direction indicated by the key will continue to be in effect until another key is tapped.
> > 
> > 
> > \ ******
> > \ ****** This contains OBJECT and some support code.
> > \ ******
> >     
> > list                    \ these are objects in the game, other than WALL or EMPTY
> >     w field .kind       \ kind of element displayed
> >     w field .x          
> >     w field .y          \ coordinates of location
> >     w field .dx
> >     w field .dy         \ offset to move
> > constant object    
> > 
> > \ An offset is one of:  -1 0 1
> > 
> > : init-object ( x y kind node -- node )
> >     init-list >r
> >     r@ .kind !
> >     r@ .y !
> >     r@ .x !
> >     0 r@ .dy !
> >     0 r@ .dx !
> >     r> ;
> >     
> > : new-object ( x y kind -- node )    
> >     object alloc
> >     init-object ;
> >     
> > : kill-object ( node -- )
> >     dealloc ;
> >     
> > : draw-object { node -- }
> >     node .kind @  
> >     node .x @  node .y @  screen c! ;
> > 
> > : erase-object { node -- }
> >     empty
> >     node .x @  node .y @  screen c! ;
> >     
> > : collision? { nodeA nodeB -- flag }
> >     nodeA .x @  nodeB .x @  <> if  false exit then
> >     nodeA .y @  nodeB .y @  <> if  false exit then
> >     true ;
> >     
> >     
> > \ ******
> > \ ****** This contains SEEK and MOVE-OBJECT and some support code.
> > \ ******
> >     
> > 300 value severe            \ how many full cycles pass before the monsters totally zero in on the player
> >                             \ if CYCLE is 100 then a SEVERE of 1000 would be 10 seconds    
> >     
> > : tweak-offset ( offset -- new-offset )             \ randomly tweaks the offset
> >     cycles @  severe bias  < if
> >         ?dup if     negate  
> >         else        1 rnd  2 *  1 -     then
> >         then ;
> >         
> > : seek { monster goal -- }                          \ sets the .DX .DY offsets for the monster
> >     goal .x @  monster .x @  -  sgn  tweak-offset  monster .dx !
> >     goal .y @  monster .y @  -  sgn  tweak-offset  monster .dy ! ;
> >     
> > \ When CYCLES is low (early in the game) the chance of it being < the RND value is high, so the monster changes direction.
> > \ As the game progresses, the chance decreases, so the monster is increasingly likely to stay aimed at the player.
> > \ When CYCLES reaches SEVERE the chance is zero, so the monster is totally focused on the player.
> > \ When changing direction, if the direction is -1 or 1 then the direction becomes opposite.
> > \ If the direction is zero then we randomly choose -1 or 1 as the new direction.
> > 
> > \ We need INIT-SEED called in the initialization, because TWEAK-OFFSET uses RND above.
> > 
> > : move-object { node -- }               \ needs .DX .DY set, adjusts .X .Y      \ doesn't move into WALL
> >     node .x @  node .dx @  +            \ -- x
> >     node .y @  node .dy @  +            \ -- x y
> >     2dup screen c@  wall = if   
> >         2drop                           \ leave object unmoved if there is a WALL in front of it
> >     else  
> >         node .y !  node .x !            \ move object, possibly running into another object
> >         then ;
> >         
> >     
> > \ ******
> > \ ****** This is a small example game --- it is kept simple for educational purposes.
> > \ ****** The player has to run over all the treasures before the monsters run over him.
> > \ ****** The player is displayed eyes oo early in the game, then becomes wide-eyes OO as the monsters' aggression increases
> > \ ****** The monsters are mouths <> and the treasures are money-bags: $$
> > \ ****** Initially the monsters are biased to moving away from the player, but increasingly
> > \ ****** become biased to moving toward the player. At SEVERE full cycles they totally go after the player.
> > \ ****** Anybody writing a game should put it in another file, unless it is a direct upgrade of this game.
> > \ ******    
> > 
> > variable treasures          \ list of treasures
> > variable monsters           \ list of monsters
> > variable player             \ the player
> > 
> > : <guide-player> ( dx dy -- )       \ sets the .DX .DY offsets for the player
> >     player @ .dy !
> >     player @ .dx ! ;
> >     
> > <switch                             \ PLAY-GAME also uses the <ESC> key to escape
> >     :noname  drop    1  0 <guide-player> ;      char l  swof        \ right
> >     :noname  drop   -1  0 <guide-player> ;      char k  swof        \ left
> >     :noname  drop    0 -1 <guide-player> ;      char q  swof        \ up
> >     :noname  drop    0  1 <guide-player> ;      char a  swof        \ down
> >     :noname  drop ;  fast-switch> guide-player ( char|false -- )
> > 
> > : init-obstacles ( -- )                                 \ assumes CLEAR-SCREEN already done
> >     horz vert 0 0 draw-box                              \ border
> >     1 7 cx 2 - cy 3 - draw-box                          \ left rail   
> >     1 7 cx 2 + cy 3 - draw-box                          \ right rail
> >     4 7 cx 11 - cy 7 - draw-box                         \ left box
> >     4 7 cx 8 + cy 1 + draw-box                          \ right box
> >     ;
> >     
> > : init-treasures ( -- node )
> >     0
> >     cx      cy          treasure new-object link        \ center treasure
> >     cx 5 -  cy 3 -      treasure new-object link        \ left treasure
> >     cx 5 +  cy 3 +      treasure new-object link        \ right treasure
> >     ;
> > 
> > : init-monsters ( -- node )
> >     0
> >     cx 5 -  cy 7 -      mouth new-object link           \ upper-left monster
> >     cx 5 -  cy 7 +      mouth new-object link           \ upper-right monster
> >     cx 5 -  cy 3 +      mouth new-object link           \ middle-left monster
> >     cx 5 +  cy 3 -      mouth new-object link           \ middle-right monster
> >     cx 5 +  cy 7 -      mouth new-object link           \ lower-left monster
> >     cx 5 +  cy 7 +      mouth new-object link           \ lower-right monster
> >     ;
> >     
> > : init-player ( -- node )    
> >     1       1           eyes new-object ;
> >     
> > : init-game ( -- )
> >     page
> >     1 seed !  \ init-seed
> >     0 cycles ! 
> >     clear-screen  
> >     init-obstacles  
> >     init-treasures      dup treasures !     ['] draw-object  each
> >     init-monsters       dup monsters !      ['] draw-object  each
> >     init-player         dup player !        draw-object
> >     display-screen ;
> >     
> > : maybe-remove-treasure { node -- }                     \ NODE must be in the TREASURES list
> >     node  player @ collision? if
> >         treasures @  node  remove                       \ -- new-head node
> >         dup erase-object  kill-object                   \ -- new-head node
> >         treasures !  then ;
> >         
> > : taken-all-treasure? ( -- flag )
> >     treasures @  ['] maybe-remove-treasure  each
> >     treasures @  0= ;
> >         
> > : <eaten-by-monster?> ( flag node -- new-flag )         \ NODE must be in the MONSTERS list
> >     player @ collision?  or ;
> > 
> > : eaten-by-monster? ( -- flag )        
> >     false 
> >     monsters @  ['] <eaten-by-monster?>   each ;
> >         
> > : guide-monster ( node -- )                             \ sets the .DX .DY offsets for the monster
> >     player @  seek ;
> >     
> > : erase-movers ( -- )                                   \ the monsters and the player can move
> >     monsters @      ['] erase-object    each
> >     player @        erase-object 
> >     ;
> >     
> > : move-monsters ( -- )    
> >     monsters @      ['] guide-monster   each
> >     monsters @      ['] move-object     each            \ monsters can run into each other and occupy the same space
> >     ;
> >     
> > : move-player ( char|false -- )    
> >     guide-player
> >     player @        move-object
> >     ;
> >         
> > : draw-all ( -- )                                       \ treasures, monsters and the player
> >     treasures @     ['] draw-object     each            \ treasures first so a monster can overwrite it
> >     monsters @      ['] draw-object     each
> >     player @        draw-object
> >     ;    
> >     
> > \ DRAW-ALL redraws the treasures in case a monster over-wrote it previously.    
> > \ The treasures are drawn first, so if a monster is there the monster will over-write it in the display.
> >     
> > : <main> ( char|false -- str|false )
> >     cycles @  severe 4 /  >= if                         \ the monsters are becoming increasingly aggressive
> >         wide-eyes  player @ .kind !  then       
> >     erase-movers                                        \ -- char|false
> >     move-monsters                                       \ -- char|false
> >     move-player                                         \ --
> >     draw-all                                            \ --
> >     taken-all-treasure? if  c" WIN!  :-D "  exit then
> >     eaten-by-monster?  if   c" LOSE  :-( "  exit then
> >     false ;
> > 
> > \ Monsters can run into other monsters or the treasure and occupy the same space. 
> > \ If a monster is on top of a treasure, the monster is displayed (because monsters are drawn after treasures).
> > \ Neither monsters nor the player can occupy the same space as a wall.        
> >     
> > : main ( -- )    
> >     init-game
> >     begin  key? until                                   \ don't begin game until player presses a key
> >     ['] <main>  play-game 
> >     treasures @     ['] kill-object  each
> >     monsters @      ['] kill-object  each
> >     player @        kill-object ;
> 
> Nice. I'll look more thuroughly through your code later. In the meantime, I'll check out VFX Forth. Based on other recommendations here, I'm going to choose between GForth and VFX Forth.

Oh no. Spellcheck, you've failed me!

[toc] | [prev] | [next] | [standalone]


#60782

Fromrickman <gnuarm@gmail.com>
Date2017-06-15 11:52 -0400
Message-ID<ohua9h$3no$2@dont-email.me>
In reply to#60588
christopherdumas@gmail.com wrote on 6/10/2017 6:57 PM:
>>
>> Nice. I'll look more thuroughly through your code later. In the meantime, I'll check out VFX Forth. Based on other recommendations here, I'm going to choose between GForth and VFX Forth.
>
> Oh no. Spellcheck, you've failed me!

Thorough is a tough word to learn to spell (along with tough and rough).  I 
think I picked it up when the AMD Thoroughbred processor came out, lol.

-- 

Rick C

[toc] | [prev] | [next] | [standalone]


#60580

Fromnew@to.forth
Date2017-06-10 21:38 +0000
Message-ID<ohhos5$1lgv$1@gioia.aioe.org>
In reply to#60562
>..
>What are your opinions on Factor (factorcode.org)?

IDK, never used it.  Obviously it's creators think Forth was lacking
and decided to implement their own vision of how a stack-based language
should work.  Right now I'm just focused on learning FOrth.

>graphics libraries?

I see a vector graphics library here:
http://theforth.net/packages

Looks like gforth includes an interface (libffg2) to the G^2 2-D web graphics library:
https://github.com/cd/g2

[toc] | [prev] | [next] | [standalone]


#60586

Fromchristopherdumas@gmail.com
Date2017-06-10 15:53 -0700
Message-ID<f47e6092-176f-4135-9de3-f2404c2b818c@googlegroups.com>
In reply to#60580
On Saturday, June 10, 2017 at 2:38:17 PM UTC-7, n...@to.forth wrote:
> >..
> >What are your opinions on Factor (factorcode.org)?
> 
> IDK, never used it.  Obviously it's creators think Forth was lacking
> and decided to implement their own vision of how a stack-based language
> should work.  Right now I'm just focused on learning FOrth.
> 
> >graphics libraries?
> 
> I see a vector graphics library here:
> http://theforth.net/packages
> 
> Looks like gforth includes an interface (libffg2) to the G^2 2-D web graphics library:
> https://github.com/cd/g2

Ah, that's helpful. Also, it's encouraging to see there's a package manager.

[toc] | [prev] | [next] | [standalone]


#60652

FromNN <november.nihal@gmail.com>
Date2017-06-12 05:36 -0700
Message-ID<2d86868a-15e0-46fd-9754-40de5654300b@googlegroups.com>
In reply to#60580
On Saturday, 10 June 2017 22:38:17 UTC+1, n...@to.forth  wrote:
> >..
> >What are your opinions on Factor (factorcode.org)?
> 
> IDK, never used it.  Obviously it's creators think Forth was lacking
> and decided to implement their own vision of how a stack-based language
> should work.  Right now I'm just focused on learning FOrth.
> 
> >graphics libraries?
> 
> I see a vector graphics library here:
> http://theforth.net/packages
> 
> Looks like gforth includes an interface (libffg2) to the G^2 2-D web graphics library:
> https://github.com/cd/g2


My take is people compare factor and forth due to some similarities (eg short definitions, stacks) whilst forgetting the differences ( eg combinators, sequences )

If you want to know something about factor why not check out https://www.youtube.com/watch?v=f_0QlhYlS8g  . Its long but well worth watching.

Good luck with forth.

NN

[toc] | [prev] | [next] | [standalone]


#60656

Fromchristopherdumas@gmail.com
Date2017-06-12 07:02 -0700
Message-ID<c807d9be-91e0-4c29-b998-1584f8196dd1@googlegroups.com>
In reply to#60652
Thanks, NN! I've been trying to decide between GForth and Factor now, and the one comparison that I know of, rosycrew.org/FactorVsForth.pdf, is no longer on the internet. I'm really split because I want to learn a pure stack-based language and I really like GForth so far, but Factor sounds really cool, being as it is a combination of Lisp (my favorite language) and Forth. The IDE isn't really a consideration for me, because I have EMACS, the Universal IDE. (:

[toc] | [prev] | [next] | [standalone]


#60660

FromJulian Fondren <julian.fondren@gmail.com>
Date2017-06-12 08:29 -0700
Message-ID<91691e59-e568-4d60-bc4b-0350a0e4ba84@googlegroups.com>
In reply to#60656
On Monday, June 12, 2017 at 9:02:39 AM UTC-5, christop...@gmail.com wrote:
> Thanks, NN! I've been trying to decide between GForth and Factor now, and the one comparison that I know of, rosycrew.org/FactorVsForth.pdf, is no longer on the internet.

*shrug*. I don't care enough about Factor even to have good arguments
against it. I'd have to have used it for more than ten minutes to even
be able to complain about it. But as someone who's seen it without
finding it interesting, I can at least share that much perspective.

When someone comes out with an incompatible Forth-like language, the
first question to answer is "Why didn't you just extend Forth?" You
have the most extensible language in existence (although not
tamely extensible to all things), and instead of building on it you
build some new thing that in Factor's case A) runs on only three x86
OSes, and B) has only a single implementation with a single set of
tradeoffs. What, besides the ego of the creator, was the point?

In Factor I see a lot of library work that could've gone into Forth
instead, and a quotation-heavy style that I don't care for, but that
at least is a little bit annoying to replicate in Forth. Today gforth
(development version), lina, and iForth all have [: ... ;] and return
stack manipulation can get you that as well. 

So it's weird in a way I don't care for and it has libraries. I'd
rather have libraries in Forth, a language with a standard and many
good implementations for enormously more architectures, without any
worries like: tomorrow Slava Pestov will decide that what Factor
really needs is *lazy semantics* - breaking all existing code.

And I don't have rosy glasses about libraries or things appearing to
be easy. There are limits to software that you only meet after a lot
of investment in that software. Something that works like a dream for
300 users becomes a huge problem at 30,000 users. A library is easy
easy easy until a tiny increment in desired behavior comes down the
line... which the library makes impossible to do. So rather than the
"oh a new thing, let's spend a lot of time on it!" attitude that I
once had with programming languages, nowadays I spare some concern on
"what are my options if this new thing is inadequate?"

I've had very good experiences with Forth libraries that were
inadequate. I used the part of the library I wanted, then dug up its
buried tools to extend it in the direction I wanted. If a Forth system
is ever part of the problem I know that there are other systems to
consider. I glanced at the Factor mailing list and found this:
http://www.mail-archive.com/factor-talk@lists.sourceforge.net/msg08109.html

Sounds like a problem I don't want to run into 98% into a project. Or
120% into it, doing support work.

One answer to "what are my options if this new thing is inadequate?",
depending on your circumstances, is "use some of your budget to pay
other people to fix the problem". If you have a problem with influxdb,
a time-series database (in Go unfortunately--anyone doing time-series
in Forth?), then you can pay InfluxData. I glanced at factorcode.org
just now and the first thing my browser told me is that the SSL cert
has been expired since March, so that option's probably out.

[toc] | [prev] | [next] | [standalone]


#60663 — Factor (was: Starting Forth)

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2017-06-12 16:16 +0000
SubjectFactor (was: Starting Forth)
Message-ID<2017Jun12.181647@mips.complang.tuwien.ac.at>
In reply to#60660
Julian Fondren <julian.fondren@gmail.com> writes:
>When someone comes out with an incompatible Forth-like language, the
>first question to answer is "Why didn't you just extend Forth?" You
>have the most extensible language in existence (although not
>tamely extensible to all things), and instead of building on it you
>build some new thing that in Factor's case A) runs on only three x86
>OSes, and B) has only a single implementation with a single set of
>tradeoffs. What, besides the ego of the creator, was the point?

In the case of Factor, the point is that it is a managed language: The
Factor system has type information on the data that it uses for dyamic
and partially static type checking, and for supporting garbage
collection.  And that can have quite a lot of advantages when
designing library functions.

If you want to go there, extending a normal Forth does not appear to
be a very viable approach to me.  And the result will be so different
that I don't see a benefit to extending a normal Forth.  Mixing normal
Forth with the managed part would destroy various invariants that the
run-time system relies on, unless the Forth code obeys the
restrictions that are necessary to keep them up; but then you are in
the foreign managed world instead of in the familiar low-level Forth
world.

So, his point was that he wanted to go there, and actually went there.

That being said, my experience with Factor has been rather miserable:
At the Forth-Tagung 2012 there was a Factor workshop, and we were
given the task to do something, and the first steps went well, and
then there was some step that rubbed the static type checker the wrong
way, and I could not get it to work, no matter what I tried; some
others achieved that step, but their advice did not help me.

My impression is that the static type checker has a rather fractal
surface: sometimes it decides that this is something it can check
statically, and then it may complain about something that the dynamic
checker would not complain about, and other times, it leaves the field
to the dynamic checker, which is much more reasonable.

But that impression is based on playing around with it for half an
afternoon.  I am sure if you get more familiar with it, you learn to
deal with this issue and it soon becomes a non-issue.

- anton
-- 
M. Anton Ertl  http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
     New standard: http://www.forth200x.org/forth200x.html
   EuroForth 2017: http://www.euroforth.org/ef17/

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.forth


csiph-web