atarionline.pl Snake w ATALAN - Forum Atarum

    Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

    • :
    • :

    Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

      • 1: CommentAuthorJKR
      • CommentTime7 Aug 2010 15:08
       
      Witam wszystkich atarowiczów

      Jeśli ktoś ma ochotę pograć sobie w nowego snake'a to proszę bardzo.

      Program napisany w ATALAN'ie.
      Wiem, że pomysł mało oryginalny ale zawsze chciałem napisać sobie własnego snake'a.

      Kto pierwszy dojdzie do 9ego poziomu ?
      • 2: CommentAuthorJKR
      • CommentTime7 Aug 2010 15:08
       
      Tutaj sa źródła:
      • 3:
         
        CommentAuthorlarek
      • CommentTime7 Aug 2010 19:08
       
      Dodaj dźwięki i będzie fajna gierka.

      PS. Doszedłem tylko do 4-go ;)
      • 4:
         
        CommentAuthorWolfen
      • CommentTime7 Aug 2010 20:08 zmieniony
       
      Powiem tak :) mimo braku dzwieku (przydalby sie jak Larek slusznie zauwazyl :) gra coz... moze inaczje - opisze moja przygode z gierka ;>

      1. Odpalilem gierke - no... snake... eh... nudne...
      2. 5 minut pozniej no... w sumie poprawnie sie gra... bez fajerwerkow...
      3. 10 minut pozniej no... jeszcez kilka zer i koncze... ale gra sie fajnie no ale to prosta gra - nic ciekawego
      4. 15 minut pozniej ...no... jeszcze chwile pogram... ale gra no... nic specjalnego...
      5. 20 minut pozniej ...jeszcze tylko pare zerek zjem...
      6. 25 minut pozniej ...nie no ... taka sobie ta gierka i dzwieku nie ma... jeszcze tylko pare zer zjem i koniec...
      7. 30 minut pozniej... hmmm... jakby ta gra byla taka zla to bym 30 minut nie gral ot tak :P wiec postanowilem o tym napisac :D

      I z pewnoscia do gierki wroce :) jest... prosta... ale przez to zaje...sta! :D Czlowiem nie zauwaza nawet kiedy z tego "a jeszcze kilka zer" ;P robi sie nagle pol godziny ;)

      Good work! :) Swietna adaptacja Snake'a :) grywalnosc jak w Nokii :) (a to niemaly komplement! :)
      • 5: CommentAuthorw1k
      • CommentTime8 Aug 2010 11:08
       
      atalan is too hard to understand.. :/
      • 6:
         
        CommentAuthorCosi
      • CommentTime8 Aug 2010 12:08
       
      Brawo! Teraz czekamy na wbudowaną w ATALAN obsługę duszków :-)
      Btw. Rudla, how about adding module support (I mean importing modules, as in Python) to ATALAN?
      • 7:
         
        CommentAuthorjhusak
      • CommentTime8 Aug 2010 12:08
       
      I am impressed. New language quiet well working. Two playable classic games. The sources written in atalan are very clear and easy to manage.

      The only disadvantage (but not really, there is the Python language) is when you do not have the editor which helps you to make indentations easy way. Vim rules!

      Rudla, maybe you should think about syntax coloring for vim?
      please...
      • 8: CommentAuthorJKR
      • CommentTime8 Aug 2010 12:08
       
      Dzięki za komplementy.

      Dźwięki będą w wersji 0.2. (Muszę sobie przypomnieć jak się je generuje - to mój pierwszy program na Atari od 15 lat z górką. Coś mi się zdaje, że były tam jakieś 4 kanały, tak ? :-))

      Podpowiedź dla tych co nie czytali kodu źródłowego: Podczas gry, jak sie naciśnie fire, waż robi sie bardziej żwawy. Tego nawet w Nokii nie było :-)

      @w1k:
      Atalan is under development and still has some bugs and not yet implemented features.

      For instance I couldn't write:

      if ... and ... then ...

      I had to write:

      if ...
      if ... then
      ...

      Also nested 'if-else' statements didn't work yet and I had to do some workarounds.
      Let's keep fingers crossed for the author to continue the development.
      • 9:
         
        CommentAuthorKaz
      • CommentTime8 Aug 2010 13:08
       
      Gratulacje! Pierwszy po latach program i od razu w egzotycznym jezyku :).

      Jezeli bedziesz dodawal dzwiek to moze tez i postulowana przez kolegow muzyke? Muzykow kilku na scenie jest, mozna zrobic przetarg :)
      • 10: CommentAuthornosty
      • CommentTime8 Aug 2010 13:08
       
      Bardzo przyjemny gameplay (o ile to w snake mozliwe ;) i wyglad...

      Czy mi sie zdaje, czy "zera" do zjadania" jakos czesciej pojawiaja sie przy scianach i w katach, niz by to wynikalo z rachunku prawdopodobienstwa? :)
      • 11: CommentAuthorJKR
      • CommentTime8 Aug 2010 15:08
       
      @nosty
      Też mam takie wrażenie. Zastanowię się nad modyfikacją procedury losującej.
      Z drugiej strony, chociaż niezamierzony, to jednak ten efekt nie jest tak do końca niewłaściwy. Nieco utrudnia grę.
      • 12:
         
        CommentAuthorKaz
      • CommentTime9 Aug 2010 14:08 zmieniony
       
      Poniewaz zrodelka weza sa publicznie dostepne i niezle opisane, to pozwalam sobie nizej je przedstawic w formie bezposrednio czytelnej, przydadza sie do przekonywania niedowiarkow :D

      ; 'Atalan the Snake'
      ;---------------------------------------------------------------------
      ; Snake game implemented in ATALAN Programming language
      ; by Jakub Krzak
      ; Katowice, August 2010
      ;---------------------------------------------------------------------
      ; Compiled with Atalan compiler, ver. 05-08-2010


      ; SCREEN --------------------------------------------------------

      ;GR.0, 40 x 25 characters 
      ;We force it to address $8000 to make it aligned correctly.
      _scr@$8000:array(0..39, 0..24) of byte

      ;Display list 
      const dl:array = 2 times $70, $42, _scr, $10, 23 times $02, $10, $02, $41, dl

      ; CONSTANTS ------------------------------------------------------

      ;Font file
      const fontFileName:font = file "snake.fnt"

      ; Starting position of the snake on the screen 
      const 
          HSx = 22
          HSy = 10
          SLength = 7

      ;Characters 
      const 
          SNAKE_HEAD_l     = 72
          SNAKE_HEAD_r     = 69
          SNAKE_HEAD_u     = 70
          SNAKE_HEAD_d     = 71
          SNAKE_BODY_nw     = 75
          SNAKE_BODY_ws     = 77
          SNAKE_BODY_se    = 78
          SNAKE_BODY_en     = 76
          SNAKE_BODY_v     = 79
          SNAKE_BODY_h     = 80
          SNAKE_TAIL_l     = 66
          SNAKE_TAIL_r     = 68
          SNAKE_TAIL_u     = 65
          SNAKE_TAIL_d     = 67
          
          FRUIT            = 16
          
          WALL_CHR         = 73
          RWALL_CHR         = 74

      type bool:0..1

      ; some hardware registers
      out COL'BK@$d01a:byte
      out COL'PF1@$d017:byte
      out COL'PF2@$d018:byte
      in RTCLOCK@20:byte

      ; GLOBAL VARIABLES ------------------------------------------------

      ; Position of the snake on the screen 
      Hx:0..39
      Hy:0..24
      Tx:0..39
      Ty:0..24

      ;Snake's head direction 
      HDir:stick'state

      Score:0..10000
      Level:1..9
      LevDelay:0..10

      ; PROCEDURES ---------------------------------------

      initialize:proc =
          Score = 0
          Level = 1
          LevDelay = 10


      writeCredits:proc =
          _scr(3,7)   = "+--------------------------------+"
          _scr(3,8)   = "!                                !"
          _scr(3,9)   = "!       PROGRAMMED BY JKR        !"
          _scr(3,10)  = "!                                !"
          _scr(3,11)  = "! IN ATALAN PROGRAMMING LANGUAGE !"
          _scr(3,12)  = "!                                !"
          _scr(3,13)  = "!     KATOWICE, AUGUST 2010      !"
          _scr(3,14)  = "!                                !"
          _scr(3,15)  = "+--------------------------------+"

          
      erasePlayfield:proc =
          for yy:2..22 for xx:1..38 _scr(xx, yy) = 0

          
      drawSnakeBegin:proc(x y len) =
          Hx = x
          Hy = y
          Tx = x - len
          Ty = y

          xx = Tx
          until xx > Hx
              _scr(xx, Hy) = SNAKE_BODY_h
              inc xx

          _scr(Hx, Hy) = SNAKE_HEAD_r
          _scr(Tx, Ty) = SNAKE_TAIL_r

          HDir = right

          
      getNextHeadCoord:proc(>x:byte >y:byte) = 
          ; get next head's coordinates depending on its direction
          if HDir = right
              x = Hx + 1
              y = Hy
          else if HDir = up
              x = Hx 
              y = Hy - 1
          else if HDir = left
              x = Hx - 1
              y = Hy
          else
              x = Hx
              y = Hy + 1

              
      getNextTailCoord:proc(ss:byte >x:byte >y:byte) = 
          ; get next tail's coordinates depending on its direction
          if ss = SNAKE_TAIL_r
              x = Tx + 1
              y = Ty
          else if ss = SNAKE_TAIL_l
              x = Tx - 1
              y = Ty
          else if ss = SNAKE_TAIL_u
              x = Tx
              y = Ty - 1
          else if ss = SNAKE_TAIL_d
              x = Tx
              y = Ty + 1

              
      moveTail:proc =
          ts = _scr(Tx,Ty) ; current 'tail' character
          xx,yy = getNextTailCoord ts
          ns = _scr(xx,yy) ; snake's character next to the 'tail'
          
          _scr(Tx,Ty) = 0 ; erase the tail

          ; put a new 'tail' character (rotated, if needed)
          if ns = SNAKE_BODY_nw 
              if ts = SNAKE_TAIL_r then _scr(xx,yy) = SNAKE_TAIL_u else _scr(xx,yy) = SNAKE_TAIL_l
                  
          else if ns = SNAKE_BODY_ws 
              if ts = SNAKE_TAIL_r _scr(xx,yy) = SNAKE_TAIL_d else _scr(xx,yy) = SNAKE_TAIL_l
                  
          else if ns = SNAKE_BODY_se
              if ts = SNAKE_TAIL_u _scr(xx,yy) = SNAKE_TAIL_r else _scr(xx,yy) = SNAKE_TAIL_d
                  
          else if ns = SNAKE_BODY_en
              if ts = SNAKE_TAIL_l _scr(xx,yy) = SNAKE_TAIL_u else _scr(xx,yy) = SNAKE_TAIL_r

          else
              _scr(xx,yy) = ts
              
          Tx = xx
          Ty = yy

              
      putNeck:proc(dir1:stick'state neck1 dir2:stick'state neck2 body) =
          ; put the 'neck1', 'neck2' or 'body' characters
          ; in the current head's position
          ; depending on the 'dir1' and 'dir2' arguments
          if HDir = dir1
              _scr(Hx,Hy) = neck1  
          else if HDir = dir2
              _scr(Hx,Hy) = neck2
          else 
              _scr(Hx,Hy) = body

              
      increaseLevel:proc =
          inc(Level)
          dec(LevDelay)

      eatFruit:proc =
          
          l:Level = 0                ; this was 'Score = Score + 10 * Level'
          while l < Level            ; but it didn't compile for some reason
              Score = Score + 10
              inc l
              
          if Score = 150 increaseLevel ; 15 * 10
          if Score = 450 increaseLevel ; + 15 * 20
          if Score = 900 increaseLevel ; + 15 * 30 
          if Score = 1500 increaseLevel ; + 15 * 40
          if Score = 2500 increaseLevel ; + 20 * 50
          if Score = 3700 increaseLevel ; + 20 * 60
          if Score = 5800 increaseLevel ; + 30 * 70
          if Score = 9000 increaseLevel ; + 40 * 80
              
          l = Level
          s:Score = Score      ; for some reason '"... SCORE: [Score]"' doesn't work
          _scr(0,24) = " LEVEL: [l]                   SCORE: [s]" 

          
      generateFruit:proc =
          ; generate random coordinates inside the playing area: 1..38, 2..22
          x = (RANDOM and 63) + 1
          y = (RANDOM and 31) + 2
          while x > 38 x = x - 38
          while y > 22 y = y - 22
          ; if this position is occupied, find a free one by increasing (and wrapping) x, then y
          while _scr(x,y) <> 0
              if x <> 38
                  inc x
              else
                  x = 1
                  if y = 22 then 
                      y = 2
                  else 
                      inc y
          ; put the fruit on the screen                
          _scr(x,y) = FRUIT

          
      moveHead:proc(>gotFruit:0..1) = 
          gotFruit = 0
          
          hs = _scr(Hx,Hy) ; current 'head' character
          xx,yy = getNextHeadCoord
          ns = _scr(xx,yy) ; character in front of the 'head'

          ; find a new 'head' character
          if HDir = right     
              nh = SNAKE_HEAD_r
          else if HDir = up
              nh = SNAKE_HEAD_u
          else if HDir = left
              nh = SNAKE_HEAD_l
          else
              nh = SNAKE_HEAD_d
              
          ; turn the head
          _scr(Hx,Hy) = nh
          
          ; check what is ahead and if the move is possible
          if ns = FRUIT
              gotFruit = 1 
          else if ns <> 0 
              goto game'over
          
          ; find and put the character next to the head
          if hs = SNAKE_HEAD_r 
              putNeck(up SNAKE_BODY_nw down SNAKE_BODY_ws SNAKE_BODY_h)
                  
          if hs = SNAKE_HEAD_u 
              putNeck(left SNAKE_BODY_ws right SNAKE_BODY_se SNAKE_BODY_v)
              
          if hs = SNAKE_HEAD_l 
              putNeck(up SNAKE_BODY_en down SNAKE_BODY_se SNAKE_BODY_h)
              
          if hs = SNAKE_HEAD_d 
              putNeck(left SNAKE_BODY_nw right SNAKE_BODY_en SNAKE_BODY_v)

          ; put the head character in the new position
          _scr(xx,yy) = nh
          Hx = xx
          Hy = yy


      ; Random animation -------------------------

      drawSnakeAtRandomPosition:proc =
          rl = (RANDOM and 15) + 6
          while rl > 15 
              rl = rl - 9
          ry = (RANDOM and 15) + 2
          while ry > 13 
              ry = ry - 11
          if ry > 6 then ry = ry + 9
          rx = (RANDOM and 63) + (1 + rl)
          while rx > 38 
              rx = rx - 38 + (1 + rl)
              
          drawSnakeBegin(rx ry rl)

          
      changeDirection:proc =
          if _scr(Hx+1,Hy) <> 0
              if _scr(Hx-1,Hy) <> 0
                  if _scr(Hx,Hy+1) <> 0
                      if _scr(Hx,Hy-1) <> 0
                          
                          ; no more move
                          timer = 0
                          while timer < 100
                              COL'BK = VCOUNT * 2 + RTCLOCK    ; do the Atari rainbow
                              if STRIG(0) = pressed  goto ex1

                          erasePlayfield
                          writeCredits
                          drawSnakeAtRandomPosition
                          goto ex1

          r = RANDOM 
          if r >= 128 goto turn'right
          
          turn'left@
          if HDir = right    
              HDir = up
          else if HDir = up
              HDir = left
          else if HDir = left
              HDir = down
          else
              HDir = right
          
          xx,yy = getNextHeadCoord
          if _scr(xx,yy) <> 0 
              goto turn'left
          moveHead
          goto ex1
          
          
          turn'right@
          if HDir = right    
              HDir = down
          else if HDir = up
              HDir = right
          else if HDir = left
              HDir = up
          else
              HDir = left

          xx,yy = getNextHeadCoord
          if _scr(xx,yy) <> 0 
              goto turn'right
          moveHead
          
          ex1@ ; exit

          
      animateSnake:proc =
          if timer >= 12

              moveTail

              xx,yy = getNextHeadCoord
              if _scr(xx,yy) <> 0
                  changeDirection
                  goto ex2

              r = (RANDOM and 15) 
              if r < 3 
                  changeDirection
                  goto ex2
                  
              moveHead
              
              ex2@

              timer = 0

      ; -------------------------------------
              
      drawArea:proc =
          _scr(0,0)  = "       .-+  ATALAN THE SNAKE  +-.   V0.1"

          for xx:0..39
              _scr(xx, 1) = WALL_CHR
              _scr(xx, 23) = WALL_CHR
              
          for yy:2..22    
              _scr(0, yy) = WALL_CHR
              _scr(39, yy) = RWALL_CHR
              for xx:1..38
                  _scr(xx, yy) = 0
          
          _scr(39, 1) = RWALL_CHR
          _scr(39, 23) = RWALL_CHR
          
          writeCredits
          
          _scr(0,24) = "     -+  PRESS TRIGGER TO START  +-     "

          timer = 0
          drawSnakeAtRandomPosition
          
          ; now, wait for trigger and animate the snake
          until STRIG(0) = pressed
              animateSnake

          erasePlayfield

          _scr(0,24) = " LEVEL: 1                   SCORE: 0    "

          ;  wait for the trigger to be released
          until STRIG(0) = not'pressed

          
      ; START -------------------------------------------

      ;Initialize graphics.
      sdlstl = dl
      COLOR0(2) = 0
      COLOR0(5) = 0
      set'font fontFileName

      start'game@

          initialize

          drawArea ; draws the playfield and waits for the trigger to start

          drawSnakeBegin(HSx HSy SLength)
          generateFruit ; put the first fruit

          grow:bool = 0
          delayCounter:0..20
          
      loop@    ; Main loop

          if STRIG(0) = pressed
              delayCntr = 2 ; if we push the trigger, the snake goes faster
          else
              delayCntr = LevDelay

          nDir = HDir
              
          while delayCntr > 0    ; delay loop

              ; wait for tick and check the stick in the meantime
              timer = 0
              while timer < 1
              
                  ss:stick'state = STICK(0)
                  if HDir = right then ss = ss or 8
                  else if HDir = up then ss = ss or 1
                  else if HDir = left then ss = ss or 4
                  else if HDir = down then ss = ss or 2
                      
                  if ss = right
                      if HDir = up then nDir = ss
                      if HDir = down then nDir = ss
                  else if ss = left
                      if HDir = up then nDir = ss
                      if HDir = down then nDir = ss
                  else if ss = up
                      if HDir = left then nDir = ss
                      if HDir = right then nDir = ss
                  else if ss = down
                      if HDir = left then nDir = ss
                      if HDir = right then nDir = ss
              
              dec delayCntr
              
          HDir = nDir ; new direction

      ; move snake forward

          if grow = 0 
              moveTail ; only if the snake hasn't eaten a fruit before
          else 
              grow = 0
          
          if moveHead = 1
              eatFruit
              generateFruit
              grow = 1

      goto loop

      ;The game is over.
      ;Display message and wait for the player to press the button to play again.

      game'over@

      _scr(11,24) = "-+ GAME OVER +-"

      until STRIG(0) = not'pressed

      until STRIG(0) = pressed   
          COL'BK = VCOUNT * 2 + RTCLOCK    ; do the Atari rainbow

      until STRIG(0) = not'pressed

      goto start'game
      • 13: CommentAuthornosty
      • CommentTime9 Aug 2010 18:08 zmieniony
       
      Juz doszedlem.
      Generator wyznaczajacy pozycje nowego owocu jest zly.

      (sorki za takie wstawienie ale nie umiem cytowac :/ )

      generateFruit:proc =
      ; generate random coordinates inside the playing area: 1..38, 2..22
      x = (RANDOM and 63) + 1
      y = (RANDOM and 31) + 2
      while x > 38 x = x - 38
      while y > 22 y = y - 22
      ; if this position is occupied, find a free one by increasing (and wrapping) x, then y
      while _scr(x,y) <> 0
      if x <> 38
      inc x
      else
      x = 1
      if y = 22 then
      y = 2
      else
      inc y
      ; put the fruit on the screen
      _scr(x,y) = FRUIT


      Po losowaniu x jest od 1 do 64, a y od 2 do 33 ale potem jest robione obciecie przez odejmowanie.
      W wyniku tego x od 1 do 26 jest wybierany 2x czescien niz z zakresu 27 - 38.
      Co wiecej, w wyniku omijania zajetych pol szansa na X=1 jest jeszcze wieksza (bedzie tak zawsze kiedy wylosujemy X=38)

      Z Y jest podobnie ale jeszcze gorzej. Bo w wyniku dzialania "while y > 22 y = y - 22" moze pasc y =1 a wtedy zadziala omijanie zajetych pol i zostanie ustawione y=2. Jesli wylosujemy y = 22 to tez dostaniemy y=2.

      Czyli szansa wylosowania owocu przy gornej lub lewej bandzie jest _na poczatku gry_ okolo 3x wieksza niz przy dole planszy.

      To by bylo calkiem fajne, bo niechcacy troche utrudnia gre :)

      Ale z czasem, kiedy waz zajmuje coraz wiecej miejsca na planszy, coraz czesciej zaczyna dzialac omijanie zajetych pol. A ono nie losuje nowego pola, tylko przesuwa owoc zawsze w tym samym kierunku (w prawo i w dol) tuz obok weza. A to juz moze wkurzac.
      • 14:
         
        CommentAuthorKaz
      • CommentTime9 Aug 2010 18:08 zmieniony
       
      Nosty - dodalem znacznik [ code ] w Twoim poscie. Znaczniki byly opisane w tym watku: ->link<-
      • 15: CommentAuthorJKR
      • CommentTime9 Aug 2010 20:08
       
      Kaz, zrobiłeś mi miłą niespodziankę tym, że mój Snake trafił do nowinki na głównej stronie AtariOnline.

      Teraz to już muszę zrobić drugą ulepszoną wersję :-)
      (zwłaszcza, że trafiają się tu tacy goście jak Nosty, którzy od razu znajdą niedoskonałości)

      Co do samego języka:
      Myślę że przed autorem jeszcze długa droga. Nie działa jeszcze sporo rzeczy dość podstawowych.
      Nie jestem pewien czy warto, póki co, pisać coś większego w Atalanie (mój snake to właściwie tylko trochę rozbudowany programik zrobiony w oparciu o tetrisa z przykładów zamieszczonych przez Rudlę)
      Ale idea jest fajna i zachęcam wszystkich do prób w Atalanie żeby zdopingować autora do rozwoju kompilatora.
      • 16: CommentAuthorJKR
      • CommentTime9 Aug 2010 20:08
       
      Nosty, masz rację. Tam właśnie jest 'kruczek pogrzebany'.

      Chodziło mi o to, żeby wylosować dwie liczby z zakresów: 2..22 i 1..38 i jeśli wypadnie zajęte pole to nie powtarzać już losowania (to ma działać szybko nawet jak wąż jest już duży).

      Niestety funkcja (czy też makro) RANDOM zwraca po prostu bajt i nie bardzo mam pomysł jak w prosty sposób ograniczyć zakres tak, żeby rozkład prawdopodobieństwa był równomierny.

      Drugą część procedury można pewnie zmienić tak, żeby przesuwać się nie o 1 ale o jakiś losowo wybrany krok.

      Any ideas ?
      • 17:
         
        CommentAuthorKaz
      • CommentTime9 Aug 2010 21:08
       
      Moja idea opierala sie na tym, zeby napisac w tej sprawie do autora - wyslalem maila na jego adresy (ten forumowy i ten ze strony projektu). Moze cos zaradzi.
      • 18: CommentAuthorrudla
      • CommentTime9 Aug 2010 21:08
       
      You certainly did good job in giving me some more inspiration to improve the language.

      @cosi: module support is one of the planned features
      There will be keyword 'USE <filename> (that's going to be normal include file).
      Another will be 'platform:<platform>' at the beginning of the file. It will define, which platform is the application developed form and will include the right file for the platform (and check, that files from different platforms are not mixed together).
      'atari' is going to stay the default platform :-)
      but c64 is planned too.
      You may look into 'atari.atl' file to see, how the platform definition file looks.

      @jhusak: I'm not using Vim, but maybe you can try? I will send you list of keywords. However, if you do not like indent (or do not have appropriate editor :-), you may use blocks enclosed in ( ) - that should not require indentation.

      @JKR: The way may be long, but it will pass faster together:-) That's why I published Atalan in early stages and your achievement proves me right :-) Thank you one more.
      • 19: CommentAuthorrudla
      • CommentTime9 Aug 2010 21:08
       
      New version of ATALAN supports operator mod, which is basically the proper way of implementing integer range.

      2 + RANDOM mod 21

      However I believe the method used by you is correct too (it's modulo implemented by loop) and will be faster (as multiplication, division and modulo are slow operations on 6502).

      So problem is in finding the unoccupied one, which I think is more problem of an algorithm than the language.

      One method I can think of is managing array of unoccupied positions and choose randomly one of the positions in this array. As ordering of such array is not important, used position may be simply replaced by the last free position, new free position may be easily added to the end of the array. One dimensional array longer than 256 elements are supported by ATALAN :-)
      • 20: CommentAuthornosty
      • CommentTime9 Aug 2010 22:08 zmieniony
       
      @Kaz - szukalem, szukalem, bo liczylem ze opis znacznikow bedzie gdzies pod ręką , w jakiejs "pomocy" :P

      @JKR - uwzgledniajac ze RANDOM losuje z zakresu 0..255, cala procedure wyznaczajaca pozycje owocu POWINNO sie dac zapisac tak:

      x = RANDOM
      y = RANDOM
      while (x < 1) or (x > 38) or (y < 2) or (y > 22) or ( _scr(x,y) <> 0 )
      x = RANDOM
      y = RANDOM

      _scr(x,y) = FRUIT


      Niewydajne, ale pewnie wystarczy ;)

      Tyle ze to chyba nie zadziala :/

      Zrobilem experyment. To dziala:

      ;generate random x from 1 to 38
      ;WORKS

      x = RANDOM

      while x > 37 x = RANDOM
      x = x +1

      "x = [x]"


      Ale takie cos, kompiluje sie, ale juz NIE dziala :(

      ;should generate random x = 1 to 38
      ;but DONT WORK cause generate x = 0 to 255
      ;I dont know why

      x = RANDOM

      while (x < 1 ) or ( x > 38 ) x = RANDOM

      "x = [x]"


      Nie mam pojecia dlaczego, ale z eksperymentow mi wyszlo ze generuje x od 0 do 255.
      • 21: CommentAuthornosty
      • CommentTime9 Aug 2010 22:08 zmieniony
       
      A tak swoja droga: za nic nie moge wyczaic skad kompilator wie gdzie jest koniec bloku wykonywanego przy komendach while czy until??
      W opisie jezyka nie znalazlem. Z przykladow sie nie domyslilem. Raz jest to jedna komenda, innym razem kilka Zadnego znacznika konca nie ma...

      Moglby mnie ktos oswiecic?
      • 22: CommentAuthorrudla
      • CommentTime9 Aug 2010 22:08
       
      @nosty: there are three kinds of blocks:
      I will use optional 'then' after if.
      In all variants, "Hello" is not part of a block.

      1. one line (new line ends the block)
      if x = 10 then a=1 b=2
      "Hello"

      2. parentheses
      if x = 10 then ( a=1 b=2 ) "Hello"

      or
      if x = 10 then ( 
      a=1
      b=2
      )
      "Hello"


      3. indent

      if x = 10 then
      a=1
      b=2
      "Hello"


      In this case, any line, that is indented less than the first line of the block ends the block.
      • 23: CommentAuthornosty
      • CommentTime9 Aug 2010 23:08
       
      Thank you rudla.
      IMHO indent variant is risky. Cause people often uses code formatters.
      • 24: CommentAuthorrudla
      • CommentTime9 Aug 2010 23:08
       
      That is of course matter of taste (discussion on indent or not indent seems to take forever on Python mailing lists).

      However, I know from experience, that not taking indent into account leads to serious errors too.
      We, as people, suppose indent shows program structure, compiler should 'think' same way as we do.

      Following C snippet:

      if (x == 10)
      a = 1;
      b = 2;

      would misled anyone.

      if (x == 10) {
      a = 1;
      b = 2;
      }

      Is not readable at all.


      The only problem with indent (as I see it :-) is undefined size of tab character. Atalan fights this problem so, that you may use both tabs and spaces, but there must be first tabs and then spaces. Mixing tabs and spaces is forbidden.

      This somewhat minimizes the problem.

      However, if you do not like indent, feel free to use variant with parentheses. In this variant, indent is ignored.
      • 25: CommentAuthorScalak
      • CommentTime9 Aug 2010 23:08 zmieniony
       
      dla mnie losowanie do skutku nie jest najlepszym pomysłem bowiem im dłuższy wąż tym losowanie przebiega dłużej. Najlepiej losować z pól nie zajętych przez węża.

      Swoją drogą ciekaw jestem czy gra mocno zwolni (czy zwolni?) przy losowaniu do skutku gdy wąż zajmuje już prawie całe pole.
      • 26: CommentAuthornosty
      • CommentTime9 Aug 2010 23:08
       
      @rudla - do you have any idea why this code don't work properly?
      I expected x from 1 to 38, but I see x from 0 to 255. Why?

      x = RANDOM
      while (x < 1 ) or ( x > 38 ) x = RANDOM
      "x = [x]"
      • 27: CommentAuthorrudla
      • CommentTime9 Aug 2010 23:08
       
      Don't know. I will try to analyze it. Must be some error.
      • 28: CommentAuthornosty
      • CommentTime9 Aug 2010 23:08
       
      @Scalak - moje rozwiazanie bylo maksymalnie proste ale tez najbardziej nieoptymalne. Tak to zwykle jest :)
      To byl tylko przyklad.

      Jesli zapiszemy wszystkie warunki tak jak ja w jednej lini z OR, to prawdopodobienstwo udanego losowania wynosi:

      38/256 * 21/256 * ilosc_pol_zajetych/ilosc_wszystkich_pol

      Nie wiem jakie sa rekordy, ale jesli waz zajmuje 50% dostepnej powierzchni, to szansa na udane losowanie wynosi 0,006.

      Czyli musimy losowac srednio 164 razy zeby trafic. Biorac pod uwage, ze jak pisze autor, RANDOM, to po prostu odczyt z rejestru Atari, a warunki tez sie sprawdza banalnie, to chyba gracz nie zauwazy spowolnienia? Czyli bardzo nieeleganckie, ale pewnie skuteczne :)

      Ale skoro w ATALAN juz jest MOD, to sa to rozwazania akademickie :)
      • 29: CommentAuthornosty
      • CommentTime11 Aug 2010 12:08
       
      Sprobowalem skompilowac SNAKE i mam errora:

      error: no rule for translating instruction
      add _1001:-2147483648..2147483647, rl, 1
      jmp _lbl68
      snake.asm (1287) ERROR: Undeclared label _LBL68 (BANK=0)

      Dlaczemu?
      • 30: CommentAuthorJKR
      • CommentTime12 Aug 2010 19:08
       
      Nosty,
      Też mam ten błąd. Najnowsza wersja kompilatora nie akceptuje czegoś takiego:
      while rx > 38 
      rx = rx - 38 + (1 + rl)

      ale akceptuje już:
      while rx > 38 
      rx = rx - 37 + rl


      Jak już to wcześniej pisałem, przed Rudlą jeszcze długa droga. Trzeba dać chłopakowi czas i trzymać kciuki żeby nie stracił zapału.

      Dołączam na wszelki wypadek poprzednią wersję kompilatora na której kompilacja przechodzi.