結局遊べるところまで完成させてしまいました。短期集中連載第2弾とでも呼びましょうか。
これと全く同じものをHSPコンテスト2007へ投稿しました。ので、いつも通り利用・改造・転載など自由ですが、これの改造をHSPコンテスト2007へ投稿することはご遠慮ください。
関連:stick命令をgetkey命令で実装する
fujidigさんによるバグの指摘#include "hsptv.as"
// 独自stick定義モジュール
#undef stick
#module modStick
// getkeyキーコード
#const GETKEY_LEFT 37
#const GETKEY_UP 38
#const GETKEY_RIGHT 39
#const GETKEY_DOWN 40
#const GETKEY_Z 'Z'
#const GETKEY_X 'X'
#deffunc _initStick
dim KEY_CODE, 6
KEY_CODE(0) = GETKEY_X, GETKEY_Z, GETKEY_DOWN, GETKEY_RIGHT, GETKEY_UP, GETKEY_LEFT
return
#deffunc _stick var vTarget, int NO_TRIGGER, int CHECK_MODE, local tmp
vTarget = 0
repeat 6; = length(KEY_CODE) // start.ax軽量化のために定数化
getkey tmp, KEY_CODE(cnt)
vTarget = vTarget << 1 | tmp
loop
if (CHECK_MODE == WIN_ACTIVE_CHECK_ON) & (ginfo_act == -1){
// HSPウィンドウがアクティブでない
prev = vTarget
vTarget = 0
} else {
tmp = vTarget
vTarget &= (-1 ^ prev) | NO_TRIGGER
prev = tmp
}
return
#define global stick(%1, %2=0, %3=1) _stick %1, %2, %3
#global
_initStick // 配列の初期化
// 独自stick定義モジュールここまで
#const global BLOCK_SIZE 32
#const global BLOCK_HSIZE BLOCK_SIZE / 2
#const global BLOCK_COLOR_MAX 8
#const global AREA_WIDTH 10
#const global AREA_HEIGHT 15
#const global AREA_WIDTH2 AREA_WIDTH * BLOCK_SIZE
#const global AREA_HEIGHT2 BLOCK_SIZE * AREA_HEIGHT
#const global AREA_X ( 640 - AREA_WIDTH2 ) / 2
#const global AREA_Y ( 480 - AREA_HEIGHT2 ) / 2
#const HIGHSCORE_MAX 6
#enum STATE_NORMAL = 1
#enum STATE_BLINK
#enum STATE_GAMEOVER
#module
//
// 指定した色でブロックを描く
#deffunc draw_block int x, int y, int c, int mode
hsvcolor 191 * c / BLOCK_COLOR_MAX, 255, 255 - 155 * ( mode != 0 )
boxf AREA_X + BLOCK_SIZE * x, AREA_Y + BLOCK_SIZE * y, AREA_X + BLOCK_SIZE * ( x + 1 ) - 2, AREA_Y + BLOCK_SIZE * ( y + 1 ) - 2
return
//
// エリアを再描画
#deffunc draw_area var map
color
boxf AREA_X, AREA_Y, AREA_X + AREA_WIDTH2 - 1, AREA_Y + AREA_HEIGHT2 - 1
repeat AREA_HEIGHT
y = cnt
repeat AREA_WIDTH
p = peek( map, y * AREA_WIDTH + cnt )
if p : draw_block cnt, y, p
loop
loop
return
//
// チェックされた行を塗りつぶす
#deffunc blink_sellines var check
repeat AREA_HEIGHT
if peek( check, cnt ) {
boxf AREA_X, AREA_Y + BLOCK_SIZE * cnt, AREA_X + AREA_WIDTH2 - 1, AREA_Y + BLOCK_SIZE * ( cnt + 1 ) - 1
}
loop
return
//
// テトリミノを描く
#deffunc draw_tetrimino int block_type, int block_color, int _x, int _y, int mode
repeat 4
y = _y + cnt
if ( AREA_HEIGHT <= y )|( y < 0 ) : continue
_cnt = cnt
repeat 4
x = _x + cnt
if ( AREA_WIDTH <= x ) : break
if block_type >> ( _cnt * 4 + cnt ) & 1 {
draw_block x, y, block_color + 1, mode
}
loop
loop
return
//
// マップにブロックを固定
#deffunc fix_to_map var map, int block_type, int block_color, int _x, int _y
repeat 4
y = _y + cnt
_cnt = cnt
repeat 4
x = _x + cnt
if block_type >> ( _cnt * 4 + cnt ) & 1 {
if (x < 0)|(AREA_WIDTH <= x) : continue
if (y < 0)|(AREA_HEIGHT <= y) : continue
poke map, y * AREA_WIDTH + x, block_color + 1
}
loop
loop
return
//
// 消せる行をチェックし、変数へ結果を返す
#deffunc check_del_lines var map, var check
ret = 0
repeat AREA_HEIGHT
i = 1
_cnt = cnt
repeat AREA_WIDTH
if peek( map, _cnt * AREA_WIDTH + cnt ) == 0 {
i = 0
break
}
loop
poke check, cnt, i
ret += i
loop
return ret
//
// nLine行目を消し、上にあるラインを下へ落とす
#deffunc del_line var map, int nLine
; if ( nLine < 0 ) | ( AREA_HEIGHT <= nLine ) : return -1
if nLine > 0 {
memcpy map, map, nLine * AREA_WIDTH, AREA_WIDTH, 0
}
memset map, 0, AREA_WIDTH, 0
return; 0
//
// 指定した行をすべて削除
#deffunc del_sellines var map, var check
i = AREA_HEIGHT - 1
repeat AREA_HEIGHT, 1
if peek( check, AREA_HEIGHT - cnt ) {
del_line map, i
} else {
i--
}
loop
return; 0
//
// テトリミノが壁やブロックと衝突するか検出
#defcfunc hit_check var map, int block_type, int _x, int _y
ret = 0
repeat 4
y = _y + cnt
_cnt = cnt
repeat 4
x = _x + cnt
if block_type >> ( _cnt * 4 + cnt ) & 1 {
if ( x < 0 ) | ( AREA_WIDTH <= x ) | ( AREA_HEIGHT <= y ) {
ret = 1
break
}
if y >= 0 : if peek( map, y * AREA_WIDTH + x ) {
ret = 1
break
}
}
loop
if ret : break
loop
return ret
#global
cls 1
randomize
hsptv_up -1, ""
dim block_type, 4, 7 // Zが時計回り
block_type( 0, 0 ) = $0660, $0660, $0660, $0660 // ■
block_type( 0, 1 ) = $2222, $00F0, $4444, $0F00 // |
block_type( 0, 2 ) = $0270, $0232, $0072, $0262 // ┤
block_type( 0, 3 ) = $0360, $0462, $06C0, $4620 // s
block_type( 0, 4 ) = $0630, $0264, $0C60, $2640 // z
block_type( 0, 5 ) = $2260, $0470, $0644, $0E20 // 「
block_type( 0, 6 ) = $4460, $0740, $0622, $02E0 // └
dim high_score, HIGHSCORE_MAX
sdim ranker_name, 50, HIGHSCORE_MAX
sdim map, AREA_WIDTH * AREA_HEIGHT
sdim line_check, AREA_HEIGHT
sqarea_x = AREA_X, AREA_X + AREA_WIDTH2, AREA_X + AREA_WIDTH2, AREA_X
sqarea_y = AREA_Y, AREA_Y, AREA_Y + AREA_HEIGHT2, AREA_Y + AREA_HEIGHT2
;pos ginfo_winx : mes "Gameover"
;gameover_width = ginfo_mesx : gameover_height = ginfo_mesy
#const gameover_width 64
#const gameover_height 18
#const fall_limit 17
gmode GMODE_ALPHA, , , 192
*restart
gosub *reload_highscore
memset map, 0, AREA_WIDTH * AREA_HEIGHT
next_type = rnd(7)
state = STATE_NORMAL
score = 0
gosub *create_new_tetrimino
*main
stick keys, 8
if state == STATE_BLINK {
state_limit--
if state_limit == 0 {
state = STATE_NORMAL
del_sellines map, line_check
gosub *create_new_tetrimino
}
}
if state == STATE_GAMEOVER {
if state_limit : state_limit--
if state_limit == 1 : hsptv_up score, ""
if ( state_limit == 0 ) & ( keys >> 4 & 1 ) : goto *restart
}
if state == STATE_NORMAL {
gosub *move_tetrimino
}
gosub *draw
wait 2
goto *main
*draw
redraw 0
draw_area map
gosub *draw_score
gosub *draw_next
if state == STATE_NORMAL {
gosub *draw_ghost
draw_tetrimino block_type( moving_rot, moving_type ), moving_type, moving_x, moving_y, 0
}
if state == STATE_BLINK {
c = 255 * ( state_limit / 3 \ 2 )
color c, c, c
blink_sellines line_check
}
if state == STATE_GAMEOVER {
color
gsquare -1, sqarea_x, sqarea_y
x = AREA_X + ( AREA_WIDTH2 - gameover_width ) / 2
y = AREA_Y + ( AREA_HEIGHT2 - gameover_height ) / 2
color 100, 100, 100
pos x+2, y+2
mes "Gameover"
color 255, 255, 255
pos x, y
mes "Gameover"
if ( state_limit == 0 ) {
pos x-50, y+40 : mes "push Z key to restart"
}
}
redraw 1
return
*draw_next
color
boxf BLOCK_HSIZE, BLOCK_HSIZE, BLOCK_HSIZE * 9 - 1, BLOCK_HSIZE * 11 - 1
pos BLOCK_HSIZE, BLOCK_HSIZE
draw_tetrimino block_type( 0, next_type ), next_type, -4, 1, 0
return
*draw_score
color
boxf BLOCK_HSIZE, BLOCK_SIZE * 6, BLOCK_HSIZE * 9 - 1, BLOCK_HSIZE * 29 - 1
color 255, 255, 255
pos BLOCK_HSIZE + 6, BLOCK_SIZE * 6 + 9
mes strf( "score:%08d", score )
mes "--------------"
repeat HIGHSCORE_MAX
mes "" + ( cnt + 1 ) + ":" + ranker_name( cnt )
mes strf( " %08d", highscore(cnt) )
loop
return
*move_tetrimino
if state != STATE_NORMAL : return
// 横方向の移動
next_moving_x = moving_x + ( keys >> 2 & 1 ) - ( keys & 1 )
if hit_check( map, block_type( moving_rot, moving_type ), next_moving_x, moving_y ) == 0 {
moving_x = next_moving_x
}
// 縦方向の移動
fall_count += 1 + 3 * ( keys >> 3 & 1 )
if fall_count >= fall_limit {
fall_count = 0
if hit_check( map, block_type( moving_rot, moving_type ), moving_x, moving_y + 1 ) == 0 {
moving_y++
} else {
// これ以上落下できないので、今の位置に固定
fix_to_map map, block_type( moving_rot, moving_type ), moving_type, moving_x, moving_y
gosub *check_delete
}
}
if keys & 2 {
moving_y = ghost_y
fall_count = fall_limit
}
// 回転処理
if keys & %110000 {
next_rot = moving_rot + (keys >> 4 & 1) - (keys >> 5 & 1) & 3
if hit_check( map, block_type( next_rot, moving_type ), moving_x, moving_y ) == 0 {
moving_rot = next_rot
// fall_count--
}
}
return
*check_delete
check_del_lines map, line_check
if stat {
score += stat * stat * 10
state = STATE_BLINK
state_limit = 12
} else {
gosub *create_new_tetrimino
}
return
*draw_ghost
repeat
if hit_check( map, block_type( moving_rot, moving_type ), moving_x, moving_y + cnt ) {
ghost_y = moving_y + cnt - 1
break
}
loop
if ghost_y > moving_y {
draw_tetrimino block_type( moving_rot, moving_type ), moving_type, moving_x, ghost_y, 1
}
return
*create_new_tetrimino
moving_x = AREA_WIDTH / 2 - 2// 動かしているテトリミノの位置(左上)
moving_y = -2
moving_rot = 0 // 動かしているテトリミノの回転
moving_type = next_type // 動かしているテトリミノの種類(兼色の種類)
next_type = rnd(7)
if hit_check( map, block_type( moving_rot, moving_type ), moving_x, moving_y ) {
// ゲームオーバー
state = STATE_GAMEOVER
state_limit = 20
gosub *reload_highscore
}
return
*reload_highscore
repeat HIGHSCORE_MAX
hsptv_getrank highscore(cnt), ranker_name(cnt), s, cnt
loop
return
2007年8月12日日曜日
ちっちゃなテトリス
2007年8月11日土曜日
テトリミノを表示する
段階的学習!がちょっと面白そうだったので作成。
こうしたテクニックはショートプログラムでも利用できそうです。#const global BLOCK_SIZE 24
#const global BLOCK_COLOR_MAX 8
#const TETRIMINO_TYPE_MAX 7
#module
//
// 指定した色でブロックを描く
#deffunc draw_block int x, int y, int c
hsvcolor 191 * c / BLOCK_COLOR_MAX, 255, 255
boxf BLOCK_SIZE * x, BLOCK_SIZE * y, BLOCK_SIZE * ( x + 1 ) - 2, BLOCK_SIZE * ( y + 1 ) - 2
return
//
// テトリミノを描く
#deffunc draw_tetrimino int tetrimino_pattern, int block_color, int _x, int _y
repeat 4
y = _y + cnt
_cnt = cnt
repeat 4
x = _x + cnt
if tetrimino_pattern >> ( _cnt * 4 + cnt ) & 1 {
draw_block x, y, block_color
}
loop
loop
return
#global
// テトリミノパターンの準備
dim tetrimino_pattern, 4, TETRIMINO_TYPE_MAX
tetrimino_pattern( 0, 0 ) = $0033, $0033, $0033, $0033 // □
tetrimino_pattern( 0, 1 ) = $2222, $00F0, $2222, $00F0 // |
tetrimino_pattern( 0, 2 ) = $0232, $0072, $0262, $0270 // ┤
tetrimino_pattern( 0, 3 ) = $0036, $0231, $0036, $0231 // s
tetrimino_pattern( 0, 4 ) = $0063, $0132, $0063, $0132 // z
tetrimino_pattern( 0, 5 ) = $0047, $0322, $0071, $0113 // ┘
tetrimino_pattern( 0, 6 ) = $0017, $0223, $0074, $0311 // └
tetrimino_rotation = 0
tetrimino_type = 0
game_speed = 30
need_to_draw = 1
title "←・→でテトリミノの種類を変更"
*main
gosub *calc
gosub *draw
wait 2
goto *main
*calc
stick keys
v = ( keys >> 2 & 1 ) - ( keys & 1 )
if v {
// テトリミノの種類を変更
need_to_draw = 1
tetrimino_type += v
if tetrimino_type < 0 {
tetrimino_type = TETRIMINO_TYPE_MAX - 1
} else : if tetrimino_type >= TETRIMINO_TYPE_MAX {
tetrimino_type = 0
}
}
count++
if count == game_speed {
// テトリミノの回転
count = 0
need_to_draw = 1
tetrimino_rotation = ( tetrimino_rotation + 1 ) & 3
}
return
*draw
if need_to_draw {
need_to_draw = 0
redraw 0
color : boxf
draw_tetrimino tetrimino_pattern( tetrimino_rotation, tetrimino_type ), tetrimino_type, 0, 0
redraw 1
}
return
2007年8月8日水曜日
バイナリデータの検索
本家BBSに投稿した、とっても基本的な線形検索のアルゴリズム。わざとモジュール化していません。
// 文字列でやっているが、文字列以外のバイナリデータでも原理は同じ。
sTarget = "Hot Soup Processor" // 検索されるバイナリデータ(この中から検索するバイナリデータを探す)
sSerch = "oce" // 検索するバイナリデータ
// ここから検索処理。
// バイナリデータではstrlenは使えないので、何らかの方法で大きさを調べてください。
repeat strlen( sTarget ) - ( strlen( sSerch ) - 1 )
_cnt = cnt : iResult = cnt
repeat strlen( sSerch )
if peek( sTarget, _cnt + cnt ) != peek( sSerch, cnt ) { // peekで1バイトずつ比較する
iResult = -1
break
}
loop
if ( iResult >= 0 ) : break // 見つかったので検索終了
loop
// 検索処理ここまで。
if ( iResult >= 0 ) {
// バイナリデータが見つかった場合
sdim sMarker, strlen( sTarget ) + 1
memset sMarker, ' ', strlen( sTarget )
memset sMarker, '^', strlen( sSerch ), iResult // 見つけた文字列の部分にマークする
mes sTarget
mes sMarker
mes sSerch + "を" + iResult + "バイトめに見つけました。"
mes "instr()の結果(" + instr( sTarget, 0, sSerch ) + ")と一緒でしょ?"
} else {
// バイナリデータが見つからなかった場合
mes "見つかりませんでした。"
}
stop
2007年8月4日土曜日
HSファイルからHTMLヘルプを作成する
HSP3.1から同梱されなくなったHTMLヘルプを作成するスクリプト。
命令一覧は作成しません。
祝・50投稿ヽ(´▽`)ノよくよく考えたらHHXのDBにはABC順に記録されているので、配列を使う必要は全くありませんでした。
もしEXE化する機会があれば処理方法を再度考え直してみたいと思います。
改良版をこちらのページから入手できます。
関連:HSファイルからHTMLヘルプを作成する(2)// hsファイルからHTMLヘルプを作成
#include "../hsphelp/src/hhx_db.hsp"
#module
// 関数名・命令名からidを得る
#defcfunc get_id str name, local s
s = name
if ( peek( s, 0 ) < 'a' ) | ( 'z' < peek( s, 0 ) ) : s = strmid( s, 1, strlen( s ) - 1 )
return "s_" + s
// 関数名・命令名からファイルの通し番号(独自に定義)を得る
// help_a.htmlを0、help_b.htmを1、…help_sp.htmを26とする
#defcfunc get_filenum str name, local s, local p
s = name
p = peek( s, 0 )
if ( 'A' <= p ) & ( p <= 'Z' ) : p -= 'A' - 'a'
if ( 'a' <= p ) & ( p <= 'z' ) {
return p - 'a'
} else {
return 'z' - 'a' + 1
}
// 通し番号からファイル名を得る
#defcfunc get_filename int num
if ( 0 <= num ) & ( num <= 'z' - 'a' ) {
return "help_" + strf( "%c", num + 'a' ) + ".htm"
} else {
return "help_sp.htm"
}
#global
chdir dir_exe + "/hsphelp"
gosub *load_db // HHXのDBからデータをロードする
gosub *init // 前準備
gosub *make_html_files // HTMLファイルを作成する
gosub *make_css_file // CSSファイルを作成する
dialog "finish"
end
*load_db
HHX_init_load_db
if HHX_currentset_sum() ! HHX_diskset_sum() {
mes "rebuilding db..." // HSファイルに何かしらの変更が加わったため、DBを再構築
HHX_init_rebuild_db DBR_WRITEDB
} else {
HHX_init_extract_db
}
return
*init
// a ~ zと特殊文字(_, #)用のファイルを用意
sdim file, 1024, 'z' - 'a' + 2
dim file_offset, 'z' - 'a' + 2
// HTMLのヘッダをそれぞれのファイルに書き込む
buf = {"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"ja\" lang=\"ja\">
<head>
\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=Shift_JIS\" />
\t<meta http-equiv=\"Content-Language\" content=\"ja\" />
\t<link rel=\"stylesheet\" type=\"text/css\" href=\"hsphelp.css\" />
\t<title>HSP command help</title>
</head>
<body>
\t<h1>HSP command help</h1>\n"}
l = strlen( buf )
repeat 'z' - 'a' + 2
file( cnt ) = buf
file_offset( cnt ) = l
loop
return
*make_html_files
db_num = HHX_select_all() // すべての命令・関数を検索対象とする
repeat db_num
c = HHX_get_next()
db_name = hhxdata( c, C_NAME ) // 命令・関数名
file_num = get_filenum( db_name ) // この命令が記録されるHTMLの通し番号(独自に定義したもの)
// 見出し(h2タグ)
buf = "\t<h2 id=\"" + get_id( db_name ) + "\" class=\"keyword_name\">" + db_name + " " + hhxdata( c, C_PRM ) + "\t\t[" + hhxdata( c, C_SUMMARY ) + "]</h2>\n"
// パラメータ
if hhxdata( c, C_PRM2 ) != "" {
buf += "\t\t<p class=\"prm\">" + hhxdata( c, C_PRM2 ) + "</p>\n"
}
// 説明文
if hhxdata( c, C_INST ) != "" {
buf += "\t\t<h3>説明</h3><p class=\"inst\">" + hhxdata( c, C_INST ) + "</p>\n"
}
// 備考
if hhxdata( c, C_NOTE ) != "" {
buf += "\t\t<h3>備考</h3><p class=\"note\">" + hhxdata( c, C_NOTE ) + "</p>\n"
}
// 参照
if hhxdata( c, C_HREF ) != "" {
buf += "\t\t<h3>参照</h3><ul class=\"href\">"
i = 0 : l = strlen( hhxdata( c, C_HREF ) )
repeat
getstr s, hhxdata( c, C_HREF ), i, ' '
i += strsize
buf += "\t\t\t<li><a href=\"" + get_filename( get_filenum( s ) ) + "#" + get_id( s ) + "\">" + s + "</a></li>\n"
if l <= i : break
loop
buf += "\t\t</ul>"
}
// 水平線(次の項目との区切り)
buf += "\n\t<hr>\n\n"
// 配列に保存
l = strlen( buf )
file( file_num ) += buf
file_offset( file_num ) += l
; title str( 100 * double( cnt ) / db_num ) + "% finished..."
; await 1
loop
// ファイルをディスクに保存
repeat 'z' - 'a' + 2
file( cnt ) += "</body></html>"
file_offset( cnt ) += strlen( "</body></html>" )
bsave get_filename( cnt ), file( cnt ), file_offset( cnt )
loop
return
*make_css_file
buf = {"body {
background-color : #f0e0d0 ;
}
h2 {
color : #000080 ;
font-size : large ;
font-weight : bold ;
white-space : pre ;
}
h3 {
font-weight : bold ;
}
p.prm {
color : #000080 ;
font-size : small ;
white-space : pre ;
margin-left : 70px;
}
p.inst {
margin-left : 70px;
white-space : pre ;
}
p.note {
margin-left : 70px;
}
ul.href {
margin-left : 70px;
}"}
bsave "hsphelp.css", buf, strlen( buf )
return
2007年7月30日月曜日
弾むリング
モジュール変数によるキャラクタの管理。#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月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と同じフォルダに入れる必要があります。

