モジュール変数によるキャラクタの管理。#module ring x, z, r, v_x, v_z, a_z, ang, a_ang, life, r_inner
#const DIV_NUM 14 // リングの分割数
#const LIFE_MAX 500 // 寿命の初期値
// 初期化
#modinit int _x, int _z, double _r, int _v_x, double _v_z, double _a_ang
x = _x : z = _z : r = _r : r_inner = 0.8 * r
v_x = _v_x : v_z = _v_z : a_z = -2.0
ang = 0.0 : a_ang = _a_ang
life = LIFE_MAX
return
// リングを動かす
#modfunc move
v_z += a_z
x += v_x : z += v_z
if ( z < r ) {
z = r * 2 - z
v_z = -v_z * 0.9
}
life -= 5
ang += a_ang
return
// リングを描く
#modfunc draw
gmode GMODE_ALPHA, , , limit(life , 0, 200)
repeat DIV_NUM
hsvcolor cnt * 191 / DIV_NUM, 255, 255
c = 3.14 * 2 * cnt / DIV_NUM + ang
gs_x = x + r * cos( c ), x + r * cos( c + g ), x + r_inner * cos( c + g ), x + r_inner * cos( c )
gs_y = ginfo_winy - z - r * sin( c ), ginfo_winy - z - r * sin( c + g ), ginfo_winy - z - r_inner * sin( c + g ), ginfo_winy - z - r_inner * sin( c )
gsquare -1, gs_x, gs_y
loop
return life <= 0
#global
g@ring = ( 3.14 * 2.0 ) / ( DIV_NUM@ring + 3 )
dimtype mod_ring, 5, 20
onclick gosub *make_ring
title "click to create rings"
*main
redraw 0
color : boxf
foreach mod_ring
move mod_ring( cnt ) // リングを移動させる
draw mod_ring( cnt ) // リングを描く
if stat : delmod mod_ring( cnt ) // リングが寿命を迎えていたら削除
loop
redraw 1
wait 3
goto *main
*make_ring
switch iparam
case 0
newmod mod_ring, ring, 0, rnd( 100 ) + 150, 60 + rnd( 50 ), rnd( 5 ) + 3, 0.0, -0.1
swbreak
default
newmod mod_ring, ring, ginfo_winx, rnd( 100 ) + 150, 60 + rnd( 50 ), rnd( 5 ) - 7, 0.0, 0.1
swbreak
swend
return
2007年7月30日月曜日
弾むリング
2007年7月29日日曜日
累乗根を求める
ニュートン・ラフソン法を用いて累乗根を求めるモジュール。
もちろん打ち切り誤差が発生します。// ニュートン・ラフソン法でxのn乗根を求める
#include "hspmath.as"
#module
#defcfunc radical_root double x, double n, local x_old, local x_new
x_new = x
repeat
x_old = x_new
x_new = ( n - 1.0 + x * pow@( x_old, -n ) ) * x_old / n
if ( absf( x_old - x_new ) < 0.00000000001 ) {
// ある程度の精度で演算を打ち切る
break
}
loop
return x_new
#global
repeat 3
pos cnt * 220, 0
up_cnt = cnt + 2
repeat 15, 2
mes strf( str( cnt ) + "の" + str( up_cnt ) + "乗根は%1.10f", radical_root( cnt, up_cnt ) )
loop
loop
stop
本家のBBSにあった「xの(1/n)乗がxのn乗根」という考え方を使えば、何と1行で記述できます。#define ctype radical_root( %1, %2 ) expf( logf( %1 ) / ( %2 ) )
2007年7月28日土曜日
(X)HTMLコンバータ β版公開
(X)HTMLコンバータのβ版ができました。よろしければお試しください。β1 ダウンロード(133KB)β2 ダウンロード(136KB)β3 ダウンロード(99KB)なおスクリプトの公開は正式版からとする予定です。
v1.0を公開しました。
変換スクリプトをこちらで公開しています。他のスクリプトはただいま整理中です。
β3からはHSPと同じフォルダに入れる必要があります。
(X)HTMLコンバータ (7) スクリプトの変換
HSP3のスクリプトを解析して(X)HTMLへ変換するスクリプト。これでバージョン1.0とします。
このスクリプト内で説明されていない変数などもありますが、変換の流れ程度はわかっていただけるかもしれません。
命令やラベルや数値などスペースを含まないものはstrmidで一気に解析してしまい、コメントや文字列などスペースを含むことができるものはpeekで1バイトずつ(オートマトンのように)変換しています。#uselib "kernel32.dll"
#cfunc global IsDBCSLeadByteEx "IsDBCSLeadByteEx" sptr, sptr
#const global CP_ACP 0
#const global EXPAND_SIZE 1024
#const global CR 0x0D
#const global LF 0x0A
#const global CRLF 0x0A0D
#enum STATE_NORMAL = 1
#enum STATE_COMMENT
#enum STATE_MULTILINE_COMMENT
#enum STATE_STRINGS
#enum STATE_MULTILINE_STRINGS
#module
#deffunc setConvertMode int i
convertMode = i
return
#deffunc addString str s, local l
l = strlen( s )
if ( rTextSize@ <= rTextPos@ + l ) {
// バッファをオーバーしてしまうので、拡張する
rTextSize@ += EXPAND_SIZE
memExpand rText@, rTextSize@
}
poke rText@, rTextPos@, s
rTextPos@ += l
return
// 単独タグ
#defcfunc _aloneTag str tagName, str className
if ( convertMode == REPLACEMODE_XHTML ) {
if ( className == "" ) {
return "<" + tagName + " />"
} else {
return "<" + tagName + " class=\"" + className + "\" />"
}
} else {
if ( className == "" ) {
return "<" + tagName + ">"
} else {
return "<" + tagName + " class=\"" + className + "\">"
}
}
// 終了タグ
#defcfunc endTag str tagName
return "</" + tagName + ">"
// 開始タグ
#defcfunc _startTag str tagName, str className, str idName, local s
if ( idName == "" ) {
s = ""
} else {
s = " id=\"" + idName + "\""
}
if ( className == "" ) {
return "<" + tagName + s + ">"
} else {
return "<" + tagName + " class=\"" + className + "\"" + s + ">"
}
// 文字がスペースかどうか(キーワードとして利用できない文字かどうか)調べる
#defcfunc is_space int iTarget, local iResult
if IsDBCSLeadByteEx( CP_ACP, iTarget ) : return 0
if ( '0' <= iTarget ) & ( iTarget <= '9' ) : return 0
if ( 'a' <= iTarget ) & ( iTarget <= 'z' ) : return 0
if ( 'A' <= iTarget ) & ( iTarget <= 'Z' ) : return 0
if ( iTarget == '_' ) : return 0
return 1
// 文字が数字かどうか調べる
#defcfunc is_number int iTarget
return ( '0' <= iTarget ) & ( iTarget <= '9' )
#global
#define ctype aloneTag( %1, %2 = "" ) _aloneTag( %1, %2 )
#define ctype startTag( %1, %2 = "", %3 = "" ) _startTag( %1, %2, %3 )
*convertText
setConvertMode replaceMode
gosub *loadDictionary // 変換用データベースの準備
gosub *beforeConvert // 変換の準備
gosub *convert // 変換の実行
gosub *afterConvert // 変換の後処理
gosub *deleteDictionary // データベースの削除
return
// 変換の準備
*beforeConvert
textSize = strlen( text )
rTextSize = textSize
sdim rText, rTextSize // ReplacedText
if ( sandwichMode == 1 ) & ( sandwichTag != "" ) {
if ( addIdMode ) {
// コマンドライン(ファイル名が格納されているはず)から
// ファイル名を取り出してidとする
rText = startTag( sandwichTag, sandwichClass, getpath( dir_cmdline, 8 ) )
} else {
rText = startTag( sandwichTag, sandwichClass )
}
}
rTextPos = strlen( rText )
x = 0
firstCharOfArea = 1 // ラベルの判定に使用
state = STATE_NORMAL
return
// 変換の実行
*convert
repeat
textPos = cnt
c = peek( text, textPos )
switch c
case 0
break
swbreak
case CR : case LF
// 改行
gosub *startNewLine
if ( strmid( text, textPos, 2 ) == "\n" ) {
continue textPos + 2
}
swbreak
case '/'
if ( strmid( text, textPos, 2 ) == "/*" ) & ( state == STATE_NORMAL ) {
// 複数行コメント開始
gosub *startMultiLineComment
addString "/*" : x += 2
continue textPos + 2
}
if ( strmid( text, textPos, 2 ) == "//" ) & ( state == STATE_NORMAL ) {
// 単一行コメント開始
gosub *startSingleLineComment
addString "//" : x += 2
continue textPos + 2
}
addString "/" : x++
swbreak
case '*'
if ( firstCharOfArea ) & ( state == STATE_NORMAL ) {
gosub *firstCharFinished
gosub *addLabel
continue textPos
}
if ( strmid( text, textPos, 2 ) == "*/" ) & ( state == STATE_MULTILINE_COMMENT ) {
// 複数行コメントの終了
addString "*/" : x += 2
gosub *endMultiLineComment
continue textPos + 2
}
addString "*" : x++
swbreak
case ';'
if ( state == STATE_NORMAL ) {
// 単一行コメント開始
gosub *startSingleLineComment
}
addString ";" : x++
swbreak
case '{'
if ( strmid( text, textPos, 2 ) == "{\"" ) & ( state == STATE_NORMAL ) {
// 複数行文字列の開始
gosub *startMultiLineStrings
addString "{\"" : x += 2
continue textPos + 2
}
addString "{" : x++
swbreak
case '"'
if ( state == STATE_NORMAL ) {
// 単一行文字列開始
gosub *startSingleLineStrings
addString "\"" : x++
continue
}
if ( state == STATE_STRINGS ) {
// 単一行文字列終了
addString "\"" : x++
gosub *endSingleLineStrings
continue
}
if ( strmid( text, textPos, 2 ) == "\"}" ) & ( state == STATE_MULTILINE_STRINGS ) {
addString "\"}"
gosub *endMultiLineStrings
continue textPos + 2
}
addString "\"" : x++
swbreak
case '\t'
if ( replaceTabs ) & ( state != STATE_STRINGS ) & ( state != STATE_MULTILINE_STRINGS ) {
// タブをスペースへ変換する
if replaceSpaces {
s = " "
} else {
s = " "
}
repeat tabWidth - ( x \ tabWidth )
addString s : x++
loop
} else {
addString "\t" : x += tabWidth - ( x \ tabWidth )
}
swbreak
case ' '
if replaceSpaces {
// 半角スペースを変換(文字列中・コメント中でも実行)
addString " "
} else {
addString " "
}
x++
swbreak
case ':'
// 文の区切れ
addString ":" : x++
if ( state == STATE_NORMAL ) : gosub *endLine
swbreak
case ',' : case '='
// パラメータの区切れ
addString strf( "%c", c ) : x++
if ( state == STATE_NORMAL ) : gosub *endArea
swbreak
case '\\'
if ( state == STATE_STRINGS ) | ( state == STATE_MULTILINE_STRINGS ) {
if ( strmid( text, textPos, 2 ) == "\\\\" ) | ( strmid( text, textPos, 2 ) == "\\\"" ) {
addString strmid( text, textPos, 2 ) : x += 2
continue textPos + 2
}
}
addString "\\" : x++
swbreak
case '&' : addString "&" : x++ : swbreak
case '<' : addString "<" : x++ : swbreak
case '>' : addString ">" : x++ : swbreak
default
// 命令・関数などキーワードの可能性
if IsDBCSLeadByteEx( CP_ACP, c ) {
// 2バイト文字の場合
// 現在のバージョンでは変数をマークアップしないので、
// このように扱ってもOK。
addString strmid( text, textPos, 2 ) : x += 2
continue textPos + 2
}
// 1バイト文字の場合
if ( state == STATE_NORMAL ) {
// 文字列中やコメント中でなければ、数値や命令・関数としてマークアップできるかどうか調べる
if ( is_number( c ) ) | ( c == '%' ) | ( c == '$' ) {
// 数値の挿入
gosub *addNumber
continue textPos
}
if ( is_space( c ) == 0 ) | ( c == '#' ) {
// 命令・プリプロセッサ・関数etc.の挿入
gosub *addWord
continue textPos
}
}
// 命令などを構成する文字列ではなかった場合(@,|,(,)など)
gosub *firstCharFinished
addString strf( "%c", c ) : x++
swbreak
swend
loop
return
// *****************************************************************
// 変換終了後処理
*afterConvert
if ( sandwichMode == 1 ) & ( sandwichTag != "" ) {
addString endTag( sandwichTag )
}
addString "\n"
text = rText
sdim rText, 4
return
// 変数の処理
*firstCharFinished
// 空白でない文字を取り出した場合
firstCharOfArea = 0
return
*endLine
// (マルチステートメントを含む論理的な)行の終了に伴う変数の変化
*endArea
// パラメータの終了に伴う変数の変化
firstCharOfArea = 1
return
// *****************************************************************
// 単行コメントの開始
*startSingleLineComment
state = STATE_COMMENT
if markupComments {
addString startTag( "span", CLASSNAME_COMMENT )
}
return
// コメント行を終了
*endSingleLineComment
state = STATE_NORMAL
if ( markupComments ) {
addString endTag( "span" )
}
return
// 複数行コメントの開始
*startMultiLineComment
state = STATE_MULTILINE_COMMENT
if ( markupComments ) {
addString startTag( "span", CLASSNAME_COMMENT )
}
return
// 複数行コメントの終了
*endMultiLineComment
state = STATE_NORMAL
if ( markupComments ) {
addString endTag( "span" )
}
return
// 単行文字列の開始
*startSingleLineStrings
state = STATE_STRINGS
if ( markupStrings ) {
addString startTag( "span", CLASSNAME_STRING )
}
return
// 単行文字列の終了
*endSingleLineStrings
state = STATE_NORMAL
if ( markupStrings ) {
addString endTag( "span" )
}
return
// 複数行文字列の開始
*startMultiLineStrings
state = STATE_MULTILINE_STRINGS
if ( markupStrings ) {
addString startTag( "span", CLASSNAME_STRING )
}
return
// 複数行文字列の終了
*endMultiLineStrings
state = STATE_NORMAL
if ( markupStrings ) {
addString endTag( "span" )
}
return
// *****************************************************************
// textPosの位置以降をラベルとして挿入
*addLabel
lLabel = textSize - textPos
repeat textSize - textPos - 1, textPos + 1
if ( textSize <= cnt ) {
lLabel = textSize - textPos
break
}
j = peek( text, cnt )
if ( IsDBCSLeadByteEx( CP_ACP, j ) ) : continue cnt + 2
if ( cnt == textPos + 1 ) & ( is_number( j ) ) {
lLabel = cnt - textPos
break
}
if is_space( j ) {
lLabel = cnt - textPos
break
}
loop
if ( markupLabels ) & ( 1 < lLabel ) {
addString startTag( "span", CLASSNAME_LABEL )
}
addString strmid( text, textPos, lLabel )
textPos += lLabel : x += lLabel
if ( markupLabels ) & ( 1 < lLabel ) {
addString endTag( "span" )
}
return
// textPosの位置以降を数字として挿入
*addNumber
if ( markupNumbers ) {
addString startTag( "span", CLASSNAME_NUMBER )
}
repeat -1, 1
j = peek( text, textPos + cnt )
if is_number( j ) | ( j == '.' ) {
continue
}
if ( cnt == 1 ) : if ( peek( text, textPos ) == '0' ) & (( j == 'x' ) | ( j == 'b' )) {
continue
}
if ( j == 'e' ) | ( j == 'E' ) {
if ( textPos + cnt + 1 < textSize ) {
n = peek( text, textPos + cnt + 1 )
if ( n == '+' ) | ( n == '-' ) : continue cnt + 2
}
continue
}
lNumber = cnt
break
loop
addString strmid( text, textPos, lNumber )
textPos += lNumber : x += lNumber
if ( markupNumbers ) {
addString endTag( "span" )
}
return
// 命令・関数・システム変数など
*addWord
repeat -1, 1
if textPos + cnt >= textSize {
dcKey = strmid( text, textPos, cnt )
break
}
if is_space( peek( text, textPos + cnt ) ) {
dcKey = strmid( text, textPos, cnt )
break
}
loop
dc -> "Exists" dcKey
if ( vret != 0 ) {
// 辞書に載っている文字列は適切なタグで囲む
dcVal = dc( "Item", dcKey )
if ( dcVal == DCVAL_COMMAND ) & ( markupCommands == 1 ) {
addString startTag( "span", CLASSNAME_COMMAND )
}
if ( dcVal == DCVAL_FUNCTION ) & ( markupFunctions == 1 ) {
addString startTag( "span", CLASSNAME_FUNCTION )
}
if ( dcVal == DCVAL_SYSVAL ) & ( markupSysvals == 1 ) {
addString startTag( "span", CLASSNAME_SYSVAL )
}
if ( dcVal == DCVAL_PREPROCESSOR ) & ( markupPreprocessors == 1 ) {
addString startTag( "span", CLASSNAME_PREPROCESSOR )
}
if ( dcVal == DCVAL_MACRO ) & ( markupMacros == 1 ) {
addString startTag( "span", CLASSNAME_MACRO )
}
addString dcKey
if (( dcVal == DCVAL_COMMAND ) & ( markupCommands == 1 )) | (( dcVal == DCVAL_FUNCTION ) & ( markupFunctions == 1 )) {
addString endTag( "span" )
}
if (( dcVal == DCVAL_SYSVAL ) & ( markupSysvals == 1 )) | (( dcVal == DCVAL_PREPROCESSOR ) & ( markupPreprocessors == 1 )) {
addString endTag( "span" )
}
if (( dcVal == DCVAL_MACRO ) & ( markupMacros == 1 )) {
addString endTag( "span" )
}
} else {
// 辞書に載っていない文字列はそのまま
addString dcKey
}
x += strlen( dcKey )
gosub *firstCharFinished
if ( dcVal == DCVAL_COMMAND ) : gosub *endArea
textPos += strlen( dcKey )
return
// *****************************************************************
// 新しい行の開始(マルチステートメントを除く、物理的に新しい行)
*startNewLine
if ( state == STATE_COMMENT ) : gosub *endSingleLineComment
; if ( state == STATE_STRINGS ) : state == STATE_NORMAL // 本来は必要ないはず
if addBrTags {
addString aloneTag( "br" )
}
addString "\n" : x = 0
gosub *endLine
return
// *****************************************************************
// 辞書の読み込み
*loadDictionary
newcom dc, "Scripting.Dictionary"
comres vret
dc( "compareMode" ) = 1 // 大文字小文字を区別しない
dcKey = 0
dcList = DCFILE_FUNCTIONS, DCFILE_SYSVALS, DCFILE_COMMANDS, DCFILE_PREPROCESSORS, DCFILE_MACROS
dcVal = DCVAL_FUNCTION, DCVAL_SYSVAL, DCVAL_COMMAND, DCVAL_PREPROCESSOR, DCVAL_MACRO
chdir dir_source + "/" + SAVE_FOLDER
notesel note
repeat length( dcList )
exist dcList( cnt )
if ( strsize < 0 ) : continue
noteload dcList( cnt )
_cnt = cnt
repeat notemax
noteget s, cnt
if ( s != "" ) {
dc -> "Add" s, dcVal( _cnt )
}
loop
loop
sdim note, 4
return
// 辞書の削除
*deleteDictionary
delcom dc
return
ラベルや変数をローワーキャメルケースで書いてきたのですが、やはりHSPユーザはアンダースコア区切りが多いようなのでそちらに変えようかな、と思っています。
2007年7月27日金曜日
円柱のHSV色空間
#include "d3m.hsp"
#include "hspda.as"
#const H_MAX 12
#const S_MAX 4
#const V_MAX 7
#const PANEL_MAX H_MAX * S_MAX * V_MAX
#const PANEL_SIZE 150 // パネル一辺の長さ
#const PANEL_DIST 200 // 同じ角度上のパネル同士の距離(左下の座標の間)
#const OBSERVER_R 2000 // 観測者の中心からの距離
#const double PI 3.1415
#const double ANG_SPEED 0.04 // 観測者の角速度
ct = 0.0
d3setcam OBSERVER_R, 0, V_MAX * 100, 0, 0, V_MAX * 100
*init
dim panel_h, PANEL_MAX : dim panel_s, PANEL_MAX : dim panel_v, PANEL_MAX // 色(HSV指定)
dim panel_r, PANEL_MAX : ddim panel_t, PANEL_MAX : dim panel_z, PANEL_MAX // パネルの位置 円柱座標系(パネルの左下の座標)
ddim panel_far, PANEL_MAX // 奥行き
repeat H_MAX : cnt1 = cnt
h = 191 * cnt / H_MAX // HSV の H
t = PI * 2.0 * cnt / H_MAX // 角度
repeat S_MAX : cnt2 = cnt
s = 256 * cnt / S_MAX // HSV の S
r = cnt * PANEL_DIST + PANEL_DIST / 2 // 中心からの距離
repeat V_MAX
v = 256 * cnt / V_MAX // HSV の V
i = cnt1 * S_MAX * V_MAX + cnt2 * V_MAX + cnt
panel_h( i ) = h : panel_s( i ) = s : panel_v( i ) = v
panel_r( i ) = r : panel_t( i ) = t : panel_z( i ) = cnt * PANEL_DIST
loop
loop
loop
observer_t = 0.0
*main
gosub *calc
gosub *draw
wait 2
goto *main
*calc
// 観測者の回転
observer_t += ANG_SPEED
if ( PI * 2.0 < observer_t ) : observer_t -= PI * 2.0
d3setlocal 0,0,0, cos( observer_t ),sin( observer_t ),0, -sin( observer_t ),cos( observer_t ),0, 0,0,1
// 奥行きを計算。遠くにあるものほどpanel_farは小さくなる
repeat PANEL_MAX
panel_far( cnt ) = cos( panel_t( cnt ) - observer_t ) * panel_r( cnt )
loop
// 小さい順(昇順)に並べ替え
sortval panel_far, 0
return
*draw
redraw 0
hsvcolor 0, 0, ( sin( observer_t ) + 1.0 ) * 128 : boxf
repeat PANEL_MAX
sortget i, cnt // 奥から数えてcnt番目のパネルのインデックス
x = cos( panel_t( i ) ) * panel_r( i ), cos( panel_t( i ) ) * ( panel_r( i ) + PANEL_SIZE ), cos( panel_t( i ) ) * ( panel_r( i ) + PANEL_SIZE ), cos( panel_t( i ) ) * panel_r( i )
y = sin( panel_t( i ) ) * panel_r( i ), sin( panel_t( i ) ) * ( panel_r( i ) + PANEL_SIZE ), sin( panel_t( i ) ) * ( panel_r( i ) + PANEL_SIZE ), sin( panel_t( i ) ) * panel_r( i )
z = panel_z( i ) + PANEL_SIZE, panel_z( i ) + PANEL_SIZE, panel_z( i ), panel_z( i )
hsvcolor panel_h( i ), panel_s( i ), panel_v( i )
d3square x, y, z
loop
redraw 1
return
2007年7月25日水曜日
(X)HTMLコンバータ (6) hsファイルから命令や関数等の一覧を作成
「hsファイルから関数一覧を作成」と同じ考え方ですが、HHX付属のモジュールを利用することで格段に効率UPしました。#include "../hsphelp/src/hhx_db.hsp"
#define HELP_DIR "hsphelp"
// ヘルプディレクトリの存在を確認
chdir dir_exe
dirlist s, HELP_DIR, 5
if stat == 0 : dialog "ヘルプディレクトリが見つかりません", 1 : end
chdir HELP_DIR
// データベースのロード
mes "loading..."
HHX_init_load_db
if HHX_currentset_sum() ! HHX_diskset_sum() {
mes "rebuilding db..."
HHX_init_rebuild_db DBR_WRITEDB
} else {
HHX_init_extract_db
}
// コンバータ用デーベースの作成
mes "making DB for (X)HTML-converter..."
db_num = HHX_select_all()
repeat db_num
c = HHX_get_next()
db_name = hhxdata( c, C_NAME )
db_group = hhxdata( c, C_GROUP )
db_prm = hhxdata( c, C_PRM )
if instr( db_group, 0, "プリプロセッサ命令" ) >= 0 {
; プリプロセッサ
notesel list_prepro
} else : if instr( db_group, 0, "システム変数" ) >= 0 {
; システム変数
notesel list_sysval
} else : if instr( db_group, 0, "マクロ" ) >= 0 {
; マクロ
notesel list_macro
} else : if db_prm = "" {
; 引数なし(命令)
notesel list_command
} else : if peek( db_prm ) = '(' {
; 関数型
notesel list_func
} else {
; 命令型
notesel list_command
}
noteadd db_name
loop
mes "finish."
2007年7月23日月曜日
(X)HTMLコンバータ (5) 複数行文字列を取得
{"で始まり"}で終わる複数行文字列を切りだして表示するスクリプト。
変換はだいたいこんな感じで行っています。
このスクリプトの場合コメント内文字列にも律儀に反応してしまいますが、コンバータではそうはなりません。
instr後にちゃっちゃと切りだしてしてしまえば良さそうなものですが、そうしていない理由は次のようなスクリプトに対応するためです。mes {"
この行で終わってはいけない\"}
この行で終わるべき\\"}
mes {"2バイト目が'\\'の2バイト文字には
反応しない→ソ"}
これに対して、複数行コメントの場合はこうした心配は必要ありません。// 複数行文字列を切りだすスクリプト
dialog "hsp;*.as;*.hss;*.hsh", 16
if stat == 0 : end
notesel buf
noteload refstr
bufSize = notesize
repeat bufSize
bufPos = cnt
c = peek( buf, bufPos )
if ( c == '{' ) & ( bufPos + 1 < bufSize ) {
if ( peek( buf, bufPos + 1 ) == '"' ) {
k = 0
repeat
ins = instr( buf, bufPos + k, "\"}" )
if ( ins < 0 ) {
k = bufSize - bufPos
break
}
repeat
j = peek( buf, bufPos + k + ins - cnt - 1 )
if j == '\\' : continue
if (( 129 <= j ) & ( j <= 159 )) | (( 224 <= j ) & ( j <= 252 )) {
j = cnt - 1
if ( j < 0 ) : j = 0
break
}
j = cnt
break
loop
k += ins + 2 // 2 = strlen( "\"}" )
if ( j \ 2 ) {
// まだ続く
continue
}
break
loop
s = strmid( buf, bufPos, k )
mes s
continue bufPos + k
}
}
loop
stop