りんご競争 (4)

さて、りんご競争の続きです。周辺部分ばかりに触れていて、なかなかゲーム本体にたどり着かない。なので、ここでもう一気に掲載してしまいます。ゲーム部分のスクリプトを。

Script Editor で開く

property racers : {2, 4, 6, 8, 10}
property laneCount : {0, 0, 0, 0, 0}
property racingLength : 39

set playerLane to "========================================|" & return
set playerLaneProperties to {size:14, font:"Monaco", color:{0, 0, 65535}}
set otherLane to "----------------------------------------|" & return
set laneProperties to {size:14, font:"Monaco", color:{0, 0, 0}}
set theRacer to "@" & return
set racerProperties to {size:14, font:"Monaco", color:{65535, 0, 0}}

tell application "TextEdit"
    activate
    close every document saving no

    display dialog "コースを選択(1から5の半角数字):" default answer ""
    set n to text returned of result as integer

    make new document at end of documents
    set name of window 1 to "Another Apple Race"

    set text of front document to ""

    repeat with i from 1 to 6
        if i is n or (i - 1) is n then
            make new paragraph at after last paragraph of text of front document with data playerLane with properties playerLaneProperties
        else
            make new paragraph at after last paragraph of text of front document with data otherLane with properties laneProperties
        end if
        if i < 6 then
            make new paragraph at after last paragraph of text of front document with data (i & theRacer) as text with properties racerProperties
        end if
    end repeat

    repeat with i from 1 to 5
        set item i of laneCount to 0
    end repeat

    set winningLane to 0
    set loopIndex to 0
    set high to 0
    repeat
        make new character at after character 1 of paragraph (item 1 of racers) of text of front document with data " " with properties racerProperties
        make new character at after character 1 of paragraph (item 2 of racers) of text of front document with data " " with properties racerProperties
        make new character at after character 1 of paragraph (item 3 of racers) of text of front document with data " " with properties racerProperties
        make new character at after character 1 of paragraph (item 4 of racers) of text of front document with data " " with properties racerProperties
        make new character at after character 1 of paragraph (item 5 of racers) of text of front document with data " " with properties racerProperties

        set racerIndex to random number from 1 to 5
        make new character at after character 1 of paragraph (item racerIndex of racers) of text of front document with data " " with properties racerProperties
        set item racerIndex of laneCount to (item racerIndex of laneCount) + 1
        set loopIndex to loopIndex + 1

        repeat with i from 1 to 5
            if (item i of laneCount) + loopIndex is greater than or equal to racingLength then
                if high < (item i of laneCount) + loopIndex then
                    set high to (item i of laneCount) + loopIndex
                    set winningLane to item i of racers
                end if
            end if
        end repeat

        if winningLane > 0 then exit repeat
    end repeat
end tell

2 年以上前に作成したものなので、見苦しい点はご容赦を。今となれば、なんでこんなことをしているのだろうと思う部分が散見されるのですが。

エラーのチェックしていません。なので、最初にダイアログでコース番号を聞かれますが、半角数字の 1 〜 5 以外を入力するとおかしくなります。ゲームエンジンは、オリジナルのりんご競争とほぼ同一です。変わっているのは、主に描画の部分です。また、Script Editor では、りんごマークを入力できないので変わりに「@」記号を使っています。@ マークが走ります。

TextEdit でなにが面倒かというと、特定の場所に文字を挿入することです。set 命令を使うよりも make 命令を使う方が簡単なのです。make 命令を使うと特定の場所を指定し、文字の属性も指定できます。

オリジナルのりんご競争では、レースを行う前に次のようなことをしています。

set text of window 1 to return & return & return & return & return & return & return & return & return & return & return & return & return & return & return

ゲームに必要な行数を入力しているんですね。もちろん、これをそのまま TextEdit で実行することは可能です。次にりんごが走るレーンを作るわけですが、この部分はオリジナルでは copy 命令を使って以下のようなことをしています。

copy "--------" to paragraph x of window 1

この window 1 を document 1 にすれば、TextEdit でも動きます。ただ、改行がなくなります。以下のスクリプトを実行するとよく分かります。

Script Editor で開く

tell application "TextEdit"
    activate
    set theText to ""
    repeat with i from 1 to 15
        set theText to theText & (i as Unicode text) & return
    end repeat
    set text of document 1 to theText
    delay 3
    repeat with i from 1 to 5
        copy "--------" to paragraph i of text of document 1
        delay 1
    end repeat
end tell

copy するたびに一行ずつ減っていくという何とも恐ろしいことになっています。これは、TextEdit の paragraph クラスが改行まで含むようになっているからなんですね。個人的な AppleScript の感覚からすると、奇妙な結果です。ですので、単純に set (copy)命令を使うと痛い目に遭います。AppleScript から行った変更は、「編集」メニューの「取り消し」が利かないですし。

これがどのスクリプタブル Cocoa アプリケーションでも同じ動作を行う、というのならまだいいのです。しかし、上記のスクリプトの対象アプリケーション(tell application "TextEdit" を tell application "CotEditor" に変える)を CotEditor にすると、エラーになります。また、QuoEdit なら期待通りの動き(15 行目まで改行を挿入し、その後、5行目までを変更)になります。

個人的な感覚でしかないのですが、Mac OS X 以前の AppleScript では、QuoEdit のような結果が基本的な動作だったと思います。が、それが Mac OS X の Cocoa アプリケーションでは通用しないことが多いのです。

AppleScript は、操作するアプリケーションによって利用できる命令やオブジェクト、または、結果が異なるから難しいという声を聞きますが、少なくとも Mac OS X 以前は基本的な部分はおおむね共通していたように思えます。しかし、Cocoa アプリケーションとなると基本的な部分すら異なるのです。これが、よけいに混乱に拍車をかけているような気がします。

例えば、save 命令。TextEdit では使えても Mail では使えない。というか、実装されていない。Safari では使えるが、表示されるシートのキャンセルボタンを押すとエラーになる。TextEdit の場合は、何も起きない。

tell application "TextEdit" -- Safari や Mail に変えてみると...
    save front document
end tell

save 命令は、Standard Suites に含まれている命令です。Standard Suites に含まれている命令は、全て AppleScript Language Guide でも解説されている基本的なコマンドばかりです。なのに、利用できたり、できなかったり。使えないものなら、用語説明に載せるな、と言いたい。

結果的に、Cocoa アプリケーションでは、基本的なクラスや命令でも使えるかどうかはいちいち確認しないといけないのです。また、利用できても結果がどうなるかはアプリケーション次第なのです。今までの経験を過信してはいけません。

また、以下のようにできそうでできないことも、なぜかできてしまいます。

Script Editor で開く

tell application "Mail"
    selection
    properties of attribute runs of content of item 1 of result
end tell

結果が返ってくるからといって、その結果が正しいものとは限りません。上記の結果は、明らかに間違っています。

Cocoa アプリケーションの場合、Apple より Apple 以外のソフトウェアの方がスクリプティング対応に時間をかけていたりします。それもこれも Apple 純正のソフトウェアが以上のようなむちゃくちゃな実装を行っているからです。Apple のソフトウェアが一定の基準をもって AppleScript に対応していれば、それを参考にして基本機能を実装することもできるのですが...。

0 件のコメント :

コメントを投稿