mac socks
Mac で svn/svk を socks 化する方法がない…… tsocks うごかないしなぁ
MacPorts インストールしなおしたらうごいた。
けど、DNS をやっぱりローカル解決しててだめだ。hosts かけばいいかなぁ
hosts に SSH サーバ先から見たレポジトリの IP 書いて sudo lookupd -flushcache したらいけた
Mac で svn/svk を socks 化する方法がない…… tsocks うごかないしなぁ
MacPorts インストールしなおしたらうごいた。
けど、DNS をやっぱりローカル解決しててだめだ。hosts かけばいいかなぁ
hosts に SSH サーバ先から見たレポジトリの IP 書いて sudo lookupd -flushcache したらいけた
これはなんか Ruby と似た感じで実装できる。
local itr = coroutine.wrap(function ()
local i = 1
while true do
coroutine.yield(i)
i = i + 1
end
end)
for i in itr do
print(i)
if i > 10 then break end
endfor in にはイテレータ関数を与える。coroutine.wrap はファンクションを与えるとコルーチン (thread) を生成してそれを resume する関数を返す。
yield の引数が呼び出し元に返って、in の前の変数に代入される。(多値かえして多重代入もできる)
os.execute ができるなら、cscript とか ruby ( cscript のが標準だからよさげ) よんでなんかするかはできそう。
スタンドアロンの Lua だと os.execute("dir /B > tmp") とかやると tmp に保存される。os.tmpname() と組みあわせればできそう。でも RO 組みこみの Lua がこれをいつまでやらせてくれるかは謎。
http://lab.lowreal.net/trac/browser/c/ro/AI/Main.lua?rev=735#L347
してみた。コルーチンの使いかたがよくわかってなくて、callcc みたいに使ってるけど、なんか面白い使いかたないかなぁ。
「コマンドを予約」しておくと、次の AI ループ (RO がわから 140ms ごとによびだされる) のときにコマンドに対応した関数がよばれるようにしてある。http://lab.lowreal.net/trac/browser/c/ro/AI/Main.lua?rev=735#L34
で、
COMMAND[101] = "StepMotion"でコマンドを定義して、self.resCmds:push({101}) でキューにつっこんでる。なんかダサい。
でもって onStepMotion がよばれるので、onStepMotion には coroutine を resume する関数をいれとく。coroutine.wrap をするとまさにその関数をつくってくれるのでそのまま代入。あとはループ中で条件判断をしつつ呼び出しを RO にかえしてあげて、処理を継続させてる。ループで書けるのはわかりやすいけど、コルーチン自体がわかりにくい感じだ。
Lua では getfenv, setfenv (function env?) という関数を使って環境を取得したり、セットしたりできる。
これは JavaScript における「変数オブジェクト」にアクセスできるイメージかな
a = loadstring([[
function hoge ()
print("hoge", fuga)
end
]])
local env = {}
-- copy env
for i, v in pairs(_G) do
env[i] = v
end
setfenv(a, env)
a() -- セットした環境で実行する
env.hoge() -- hoge, nil
env.fuga = "fuga"
env.hoge() -- hoge, fugaこうすると閉じたところで実行できる。サンドボックスみたいなのが作れそうなのでつくってみよう。
あるいは、
function foo (aaa, bbb)
local localvariable = "aaa"
for i, v in pairs(getfenv(1)) do
print(i, v) -- この関数の変数とその値を列挙
end
end
foo()
copy env って書いたけど、コピーされずに参照がそのままつっこまれてる。というか再帰的にテーブルをコピーしないとだめだ。
でも Lua は os.cd とかないから、ファイル書きこみとかされるとうまくいかないなぁ。io.open をフックしたらできるかな。
io._orig_open = io.open
io.open = function (filename, mode)
return io._orig_open("/tmp/"..filename, mode)
endでふつうにうまくいった。
似非シェルを作ってみた。
http://lab.lowreal.net/test/RO_AI_shell.PNG
ファイルの読みかき以外はできないので、コマンドを送るようのファイルと、結果を書くファイルふたつを使って ruby プロセスと通信
e は生の eval みたいなもの。i は return をつけただけ。
でも Lua はグローバルで評価されてしまうっぽい。(setfenv は上位変数は見れない?)
でもこれ便利っぽい。うんこソースになってしまったけど実装してよかった
> i Actor.players():map(function(i) return i.id end):join() 1111, 2222, 3333
とか見れるようになる。
Lua 云々はこれのためにやっていたやつです。
公式配布のもの (ROのインストールディレクトリの AI 以下) は最小限の機能が最小限の実装で書かれていて、そのままだと読みにくく、書きかえにくい。
なので、とりあえずデフォルトのAIの機能を移植するかたちで、書きやすように OOP 化しはじめてみた ( http://lab.lowreal.net/trac/browser/c/ro/AI/ )
デフォルトの Util.lua にある List テーブルがなぜかクラスではないので List.lua として分離し、ruby っぽいメソッドをいくつか追加した。
l = List.new(1, 2, 3)
l:join() --> "1, 2, 3"
l1 = List.new(4, 5, 6)
l2 = l + l1
l2:map(function (i)
return i * i
end) --> 1, 4, 9, 16, 25, 36クラスの実装は http://subtech.g.hatena.ne.jp/cho45/20070502/1178092846 のまま。
GetDistance 系はダサいので、Actor クラスを作ってラップしてある (Actor.lua)。Actor クラスはモンスターやホムやプレイヤーに対して使えるクラス。
a1 = Actor.new(id)
a2 = Actor.new(other_id)
a1:distanceFrom(a2) > 3
a1:isInSight(a2) --> a2 が 20 セル以内にいるとき true
a1:isInAttackSight(a2) --> a2 が攻撃可能な範囲にいるとき true (今は単に 1 セル以内)
a1:isStand() --> a1 が立っているとき trueこれによって GetV を使わなくてすむはず。定数を何回も書くのがめんどいのでちょっと楽かなぁと思う。
Homun クラス (Homun.lua) は飼っているホムに使うクラス。Actor のサブクラスになっていて、Actor のメソッドはよべる。
h = Homun.new(myid)
h:owner() --> オーナーキャラ (つまり操作している自分のキャラ) を Actor インスタンスで取得
h:move(x, y) --> x, y に移動
h:attack(target) --> target を攻撃 (attack できる範囲にはいっていないと何もおきないと思う)スキル使うのはこれから実装する (AIばっかり書いててまだスキルがとれてない)
RO からは AI.lua が呼びだされる。こいつにはデバッグメッセージの出力と、本体でエラーをはいたときに RO のほうに伝達しないようにしてる (RO に伝達すると、ダイアログが表示されまくって Alt-F4 するしかない。さすが! 重力クオリティ!) AI.lua は Main.lua をロードして、Main 関数を実行する。
Main.lua には Main 関数と HogeAI クラスと reload 関数が定義されてる。
Main 関数では HogeAI クラスをインスタンス化して、RO から呼びだしがくるたびに、インスタンス化した AI クラスの act メソッドを呼びだしている。CurrentAI とかいうグローバル変数に突っ込んでいるのは、そのうち切りかえとかできたらなぁとか考えているからだけど、実装できるか謎い。
HogeAI は今つくってる劣化デフォルトAI で、やってることはデフォルト AI とそんな違いはないはず (実装してないのがいくつかある)。デフォルト AI の処理をとりあえず移植したら DefaultAI クラスにでもして、それのサブクラスを作ったらいいかなぁとか思ったけど、まだやってなくてわからない。
xpcall とかいう関数ふたつとってエラーキャッチする関数をみのがしてた!!
Try をつかいつづけるか悩む