電子辞書Brainをいじる (9) BrainuxでBASICで遊ぶ


YaBasicを試す

Brainux上で動くBASICインタープリタを探してみたところ、
グラフィックもサポートしているのものとして、YaBasicというものが見つかりました。

△ yabasic  グラフィック処理も可能なBASICインタープリタ

https://packages.debian.org/bullseye/yabasic
https://2484.de/yabasic

起動:yabasic

Yabasicは伝統的なBasicインタプリタです。goto文や様々なループ文を備え、サブルーチンやライブラリを定義できます。簡単なグラフィック処理や印刷も可能です。C言語で書かれたライブラリを呼び出せるため、スタンドアロンプ​​ログラムの作成も可能です。YabasicはUnixとWindowsで動作し、充実したドキュメントが用意されています。小型でシンプル、オープンソースで無料です。

Burainuxでも動作するグラフィック処理も可能なBasicインタープリタです。

 

 インストール1:APT経由 ”sudo apt install yabasic”
 (グラフィック機能利用時には、XLIB_SKIP_ARGB_VISUALS=1が必要)

 インストール2:ソースからインストール
 (グラフィックモードの不具合解消に挑戦して、
  opwn window自体はできるようになったが、
  その先の描画でエラーになるので挫折中)
  ビルド時に-o3 -march=native指定することでの高速化はおそらくできます。

 

YaBasicの実行方法

YaBasicでBASICコードを実行するには、以下のような方法があります。
・BASICコードをファイルに保存して引数として呼び出す
 yabasic ./demo.yab

・yabasicを起動して、BASICコードを入力していき、最後に何も入力しないでEnterを押す

yabasic
 print “Hello”

 Hello

ただし、xterm上で起動すると、文字の色指定がうまく表示されないときがあるので、
その場合は、brainuxデフォルトのターミナル(lxterminal)を使いましょう。

———-

また、グラフィック処理を使う場合にはそのまま起動するだけではエラーになります。

user@brain:~$ yabasic

open window 100,100

X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 1 (X_CreateWindow)
Serial number of failed request: 18
Current serial number in output stream: 22

これは、yabasicが想定しているグラフィック環境と、実態(BrainuxのX環境)間のずれのせいでグラフィックウィンドウがうまく開けないためのようです。

この場合、以下のようにしてyabasicを起動してください。
これでグラフィックモードも開けるようになります。
 XLIB_SKIP_ARGB_VISUALS=1 yabasic

毎回入力すのが大変であれば、以下のようにalias設定すれば、
ターミナル上で、「yabasic」と入力するだけでOKになります。

echo 'alias yabasic="XLIB_SKIP_ARGB_VISUALS=1 yabasic"' >> ~/.bashrc
source ~/.bashrc

ちなみに、Linux上では、.yab の1行目に以下のどちらかを書いておいて、
chmod +x hoge.yab と打って実行権限を付ければ、
./hoge.yab で実行できるようになるそうです。

#!/usr/bin/yabasic
#!/usr/bin/env yabasic

ただbrainuxの場合は、以下のようにラッパーを作成しての対応が必要そうです。
(この対応をするのであれば、alias設定は不要です)

$ sudo mv /usr/bin/yabasic /usr/bin/yabasic-brain
$ sudo vi /usr/bin/yabasic
#!/bin/sh
XLIB_SKIP_ARGB_VISUALS=1 /usr/bin/yabasic-brain “$@”
$ sudo chmod /usr/bin/yabasic

 

———-

YaBasicのサンプルプログラム

YaBasicのマニュアルは、「https://2484.de/yabasic/support.html」に書かれています。

また、関連サイト「https://2484.de/yabasic/related.html」から、yabasicで使えるBasicコードにたどり着くこともできそうです。
Brainで使う場合は、解像度問題があるのでそこは考慮しないといけませんが、
特にRosetta Codeは非常に参考になります。

いくつか、サンプルプログラムを動かしてみます。
(一部変更済済)

hello.yab Hello World表示

#!/usr/bin/yabasic
clear screen
print "Press 'q' to quit ..."
label again
print color("green") "Hello ";
print color("blue") "World !   ";
if (inkey$(1)="q") exit
goto again

 

asciitable.yab アスキーコード表示

#!/usr/bin/yabasic
for i = 32 to 47
    for j = i to i + 80 step 16
	    s$ = chr$(j) + "  "
        if j = 32  s$ = "Spc"
        if j = 127 s$ = "Del"
		print str$(j, "#####"), ": ", s$;
    next j
    print
next i

 

gdemo.yab グラフィック表示デモ

#!/usr/bin/yabasic
w = 400
open window w, w
sleep 1
label again
backcolour 0,0,0
clear window
for i=0 to w step 5
  v = 255 * i / w
  color 0, v, (255 - v)
  line 0, i, i, w
  color (255 - v), 0, v
  line i, 0, w, i
  pause 0.025
next i
sleep 3
goto again

 

lifegame.yab ライフゲーム

#!/usr/bin/yabasic
// Game_of_Life
 
X = 59 : Y = 35 : H = 4
 
open window X*H,Y*H
backcolor 0, 0, 0
 
dim c(X,Y) : dim cn(X,Y) : dim cl(X,Y)

// Thunderbird methuselah
c(X/2-1,Y/3+1) = 1 : c(X/2,Y/3+1) = 1 : c(X/2+1,Y/3+1) = 1  
c(X/2,Y/3+3) = 1 : c(X/2,Y/3+4) = 1 : c(X/2,Y/3+5) = 1
 
s = 0
repeat
    clear window
    alive = 0 : stable = 1
    s = s + 1
    for y = 0 to Y-1 
        for x = 0 to X-1
            xm1 = mod(x-1+X, X) : xp1 = mod(x+1+X, X)
            ym1 = mod(y-1+Y, Y) : yp1 = mod(y+1+Y, Y)
            cn(x,y) = c(xm1,y) + c(xp1,y)
            cn(x,y) = c(xm1,ym1) + c(x,ym1) + c(xp1,ym1) + cn(x,y)
            cn(x,y) = c(xm1,yp1) + c(x,yp1) + c(xp1,yp1) + cn(x,y)
            if c(x,y) = 1 then
                if cn(x,y) < 2 or cn(x,y) > 3 then 
                    cn(x,y) = 0
                else 
                    cn(x,y) = 1
                    alive = alive + 1
                end if
            else 
                if cn(x,y) = 3 then 
                    cn(x,y) = 1
                    alive = alive + 1
                else
                    cn(x,y) = 0
                end if
            end if
            if c(x,y) then
                if cn(x,y) then
                    if cl(x,y) color 0, 0, 255          // adult
                    if not cl(x,y) color 0, 255, 0      // newborn
                else 
                    if cl(x,y) color 255, 0, 0          // old
                    if not cl(x,y) color 255, 255, 0    // shortlived
                end if 
                fill rect x*H,y*H,x*H+H,y*H+H
            end if
        next x
    next y

    pause 0.06
    // Copy arrays
    for i = 0 to X-1
        for j = 0 to Y-1
            if cl(i,j)<>cn(i,j) stable = 0
            cl(i,j) = c(i,j)
            c(i,j) = cn(i,j)
        next j
    next i  
until(not alive or stable)
 
if not alive then
    print "Died in ", s, " iterations"
    clear window
else 
    print "Stabilized in ", s-2, " iterations"  
end if

 

clock-degital.yab デジタル時計

#!/usr/bin/yabasic
clear screen
open window 300,100
backcolor 0, 0, 0
window origin "cc"

// Display digital clock
sub digital_clock()
    local t$(1), void
    static as$
    
    void = token(time$, t$(), "-")

    if t$(3) <> as$ then
        draw_clock(t$(1), t$(2), t$(3))
        as$ = t$(3)
    end if
end sub

sub draw_clock(hour$, mint$, ssec$)
    local d$(1), void
    
    void = token(date$, d$(), "-")
    clear window
    color 200, 255, 0
    text -140, -30, d$(3) + "/" + d$(2) + "/" + d$(4), ""
    text 0, 0, hour$ + ":" + mint$ + ":" + ssec$, "cc", ""
end sub

if peek$("library") = "main" then
    repeat
        digital_clock()
    until(upper$(inkey$(.01))="ESC")
    exit
end if

 

clock-analog.yab アナログ時計

#!/usr/bin/yabasic
REM yaclock
DEG_PER_RAD = 57.257751

winx = 440
winy = 440

radius = min(winx,winy) / 2 - 1
hx = (winx/2) - 1
hy = (winy/2) - 1

REM length of the hands (90% of the radius of the clock face)
shand = int(radius * .9)
mhand = int(radius * .9)
hhand = int(radius * .5)

REM drop coords by one since graphics are 0 based

winx = winx - 1
winy = winy - 1

clear screen

open window winx,winy

clockface()

do

    hour = val(mid$(time$,1,2))
    mins = val(mid$(time$,4,2))
    sec  = val(mid$(time$,7,2))
    
    updatehand("sec")
    updatehand("mins")
    updatehand("hour")

    pause .25

loop

sub updatehand(hand$)
    
    switch(hand$)
        case "sec"
            h_len = shand
            angle = sec * 6
            width = 6
            color 255,0,0
            ox = osx
            oy = osy
            oxm1 = osxm1
            oxm2 = osxm2
            oym1 = osym1
            oym2 = osym2
            break
        case "mins"
            h_len = mhand
            angle = mins * 6 + int(sec/10)
            width = 12
            color 0,255,0
            ox = omx
            oy = omy
            oxm1 = omxm1
            oxm2 = omxm2
            oym1 = omym1
            oym2 = omym2
            break
        case "hour"
            h_len = hhand
            angle = ((hour * 30) + (minutes / 12) * 6) + int(mins/2)
            width = 15
            color 0,0,255
            ox = ohx
            oy = ohy
            oxm1 = ohxm1
            oxm2 = ohxm2
            oym1 = ohym1
            oym2 = ohym2
            break
    end switch

    h_angle1 = angle - width
    if h_angle1 < 0 then 
        h_angle1 = h_angle1 + 360
    endif 
    h_angle1 = h_angle1 / DEG_PER_RAD
    
    h_angle2 = angle + width
    if h_angle2 > 360 then 
        h_angle2 = h_angle2 - 360
    endif   
    h_angle2 = h_angle2 / DEG_PER_RAD
    
    angle = angle / DEG_PER_RAD
    
    x = (hx + (sin(angle) * h_len))
    xm1 = (hx + (sin(h_angle1) * int(h_len * .2)))
    xm2 = (hx + (sin(h_angle2) * int(h_len * .2)))

    y = (hy - (cos(angle) * h_len))
    ym1 = (hy - (cos(h_angle1) * int(h_len * .2)))
    ym2 = (hy - (cos(h_angle2) * int(h_len * .2)))

    clear line hx,hy,oxm1,oym1
    clear line hx,hy,oxm2,oym2
    clear line oxm1,oym1,ox,oy
    clear line oxm2,oym2,ox,oy
    line hx,hy,xm1,ym1
    line hx,hy,xm2,ym2
    line xm1,ym1,x,y
    line xm2,ym2,x,y
    
    REM save off the old vals
    switch(hand$)
        case "sec"
            osx = x
            osy = y
            osxm1 = xm1
            osxm2 = xm2
            osym1 = ym1
            osym2 = ym2
            break
        case "mins"
            omx = x
            omy = y
            omxm1 = xm1
            omxm2 = xm2
            omym1 = ym1
            omym2 = ym2
            break
        case "hour"
            ohx = x
            ohy = y
            ohxm1 = xm1
            ohxm2 = xm2
            ohym1 = ym1
            ohym2 = ym2
            break
    end switch
end sub

sub clockface()
    circle hx,hy,radius
    
    htick = radius / 10
    mtick = htick / 2
    
    for z=0 to 360 step 6
        REM  Begin at zero deg and stop before 360 deg

        REM draw the hour markers
        angle = z
        angle = angle / DEG_PER_RAD
        x2 = (hx + (sin(angle) * radius))
        y2 = (hy - (cos(angle) * radius))
        if mod(z,30) = 0 then
            tick = htick
        else
            tick = mtick
        endif
        x3 = (hx + (sin(angle) * (radius - tick)))
        y3 = (hy - (cos(angle) * (radius - tick)))
        color 255,0,0
        line x2,y2,x3,y3
        color 0,0,0
    next z
end sub

 

Mandelbrot.yab マンデルブロート集合描画

#!/usr/bin/yabasic
open window 640, 400
wid = 4
xcenter = -1: ycenter = 0
ms = 0
for xcoord = 0 to 639
   for ycoord = 0 to 200
       ms = 0
       ca =(xcoord-320)/640*wid+xcenter
       cb =(ycoord-200)/640*wid+ycenter
       x = 0: y=0

       for t = 1 to 20
           xnew = x*x-y*y+ca
           ynew = 2*x*y+cb
           x=xnew:y=ynew
           magnitudesquared=x*x+y*y
           ms = magnitudesquared
           if (magnitudesquared > 100) break
           //if(magnitudesquared < 100) then : color 0,0,0 : dot xcoord, ycoord : end if
       next t
       ms = ms+1
       if(ms > 250) then
       	    color 32,64,mod(ms,255)
            dot xcoord, ycoord
            dot xcoord, 400- ycoord
        elseif (ms > 150) then
            color mod(ms,255),64,32
            dot xcoord, ycoord
            dot xcoord, 400-ycoord
        else
            color 0,0,0
            dot xcoord, ycoord
            dot xcoord, 400-ycoord
        end if
    next ycoord
next xcoord

 

その他参考になるサンプルプログラムを公開しているサイト

その他いろんなサイトで、サンプルプログラムを見つけることができます。

公式デモ

Yabasic公式ページ内にあるyabasicのソースコード内にある
demo.yab を実行すると、
素数調査&テキスト横スクロールデモ、
グラフィックデモ、三角錐回転デモ
が見られます。

 

yabasic-examples

https://github.com/spartrekus/yabasic-examples

サインカーブ表示デモとテトリスが含まれています
(テトリスは解像度の関係で下部分が表示されていないので別途調整が必要です)
(2か所ほど数字を変えれば調整できますので、挑戦してみてください。)
(ヒント: 縦20行->17行にすれば、Window最前面化せずとも表示できます。)

 

Rosetta Code(YaBasic)

https://rosettacode.org/wiki/Category:Yabasic

いろんな言語でのサンプルプログラムが刑されていますが、YaBasicだけで大量のサンプルがあります(今回サンプルとして実行したものもここサイトのものをベースにしているものがあります)。

参考(PS2版YaBASIC)

PS2版YaBasicについて

ネット上で探すと、PS2用のyabasicソースもみつかりますが、
一部PS2専用に追加されている命令が使われているようで、Brainuxで利用可能でX11版では動きませんでした。

これは、PS2で追加されたBASIC命令がいくつかあるためです。
特にsetrgb命令がが頻出するようです(色のパレット変更命令ぽい?)。

ただ、Brainで利用可能なX1ポート版では未対応で、一時期本家に取り込むかという話はあったようですが、X11などでは実装は難しいとのことでペンディングになっているようです。

https://github.com/marcIhm/yabasic/issues/39
// Additions introduced with the PS2 version
void triangle(struct command *cmd);
void gtriangle(struct command *cmd);
void setrgb(struct command *cmd);
void setdrawbuf(struct command *cmd);
void setdispbuf(struct command *cmd);

PS2用のBasicをWin32ポートに移植したものや、
javascript実装したもの(Web上で実行できます)もあるので、
こちらで動かすことはできそうです。

Win32移植版
https://sourceforge.net/projects/win32yabasic

Javascript実装
https://www.mrdictionary.net/yabasic

 

PS2用ゲームプログラムについて

PS2用YaBasicソース

Yabasic for PS2

Yabasic for PS2 : Free Download, Borrow, and Streaming : Internet Archive

昔はPS2のゲーム機加税回避のため、一部の国でプログラミング言語を梱包したことがあるようで、その際に梱包されたのがこのYabasicの移植版だったそうです。

先ほどの通り、特殊な命令が追加されています。

上記のリックから、Ps2用のYaBasicソースが入手できます。
ただ、一部特殊な命令が使われているのと、Window解像度が640×512になっていることが多いので、ゲームレイアウト的にも厳しいものもあるかもしれません。
(Brainuxの解像度は縦480ですが、Windowの枠を考えるとを実質440-450くらいです。)

———-

Win32 PS2 YaBasic Samples

https://win32yabasic.sourceforge.net/samples.html

PS2版YaBasicのWindows移植版のサンプルプログラムです。
特に、「rotating_triangle」というグラフィックデモをBrainで動かしてみたかったのですが、
PS2版で追加された専用命令をメインで使用しているため、断念しました
(下の画像はJavascript実装上で実行したものです。)。

 

 

 

 

BasiC-256を試す

プログラミング学習用のBASIC動作環境とのことです。

標準では、GUI表示されるウインドウの中に、
・エディタ部分、
・テキスト出力エリア、
・グラフィック出力エリア
が入っています。
また、変数確認エリアも追加できます。

ただ実行するだけでなく、デバック実行として、1行ずつ実行していくことも出来ます。
この際には」、変数確認エリアを見ながら確認することも出来るので、学習に役立つでしょう

〇 basic-256 (basic256)  子供向けの教育用BASICプログラミング環境

BASIC-256は、誰でも(特に中学生・高校生)にコンピュータプログラミングの基礎を教えられるように設計された、使いやすいBASICバージョンです。gosub、for/next、gotoといった伝統的な制御構造を採用しており、子どもたちがプログラムのフロー制御の仕組みを簡単に理解できます。グラフィックモードが組み込まれており、数分で画面に絵を描くことができます。
また、楽しい演習を通してプログラミングの概念を紹介する、詳細で分かりやすいチュートリアルも用意されています。

https://packages.debian.org/bullseye/basic256
https://basic256.org/

起動:basic256

ドキュメントも日本語はありませんが、用意されており、
このページにサンプルプログラムも紹介されています。
https://doc.basic256.org/doku.php

YaBasicと比べると遅いですが、実行結果の確認は楽です。

Brainで実行する場合は、Basic-256が統合環境のため、
各ウィンドウが小さくなってしますが、学習用途であれば何とかなるかもしれません。
グラフィックウィンドウについては、エディタ、テキスト出力エリア、グラフィックを同時に出力した場合で、調整すれば、縦幅170くらいは表示できそうです。
(グラフィックウィンドウについては、縮小化表示もできます[1/2(half),1/4(quarter))
出力結果をPDFで出力することも出来ます。

 

サンプルプログラムについて

サンプルプログラムとしては、以下からソースプログラムをダウンロードすれば、
中に入っていました(.kbsファイル)

https://sourceforge.net/projects/kidbasic/files
basic256_2.0.99.10.orig.tar.gz

solar_system.kbs

snowflakes.kbs

rainbow.kbs

spriteslice.kbs

ring_01.kbs

 

 

その他参考になるサンプルプログラムを公開しているサイト


ドキュメントに掲載されているサンプルプログラム

https://doc.basic256.org/doku.php?id=start

spinner.kbs  針が動いて1-10がランダムに選ばれます。

gamesballons.kbs 大量の風船が上に浮かんでいきます(がBrain上だとめっちゃ遅いです。)

CopyCat.kbs サイモン的記憶ゲーム(実行には一部修正が必要)

mobius.kbs アニメーション化されたメビウスの輪(スムーズに回転します)

morie.kbs モアレ模様が表示されます。

square.kbs スクエア・スパイラル

jagged.kbs Jagged Depths 三角形を使ってカラフルな円形を表示します。(1/2表示)

 

Rosetta Code(BASIC256)

https://rosettacode.org/wiki/Category:BASIC256

いろんな言語でのサンプルプログラムが刑されていますが、BASIC-256だけで大量のサンプルがあります。

マンデルブロート集合描画
https://rosettacode.org/wiki/Mandelbrot_set#BASIC256
(全部表示されるまでに、1時間以上かかります。)

 

Basic Bits – Copy paste & run

https://basic256.blogspot.com

BASIC-256で動作する各種プログラムを公開されています。
グラフィックデモの他に、いくつかのゲームも含まれています。

Views: 275

カテゴリー: Brain, Brainux, debian, Linux, ツール パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です