akaneutils.lua
akaneutils.lua
ユーティリティ関数集です。
----------------------------------------------------------- -- @file akaneutils(lua) -- @brief 茜ちゃんによるユーティリティ集や -- @author 琴葉茜(さとうけい) ----------------------------------------------------------- ----------------------------------------------------------- -- 引数なしの関数を作るよ<br> -- CCのparallel APIに渡したりするのに便利やで -- -- @param func 元の関数 -- @param ... 関数に渡す引数 -- @return 作った関数 ----------------------------------------------------------- function getNoArgFunc(func, ...) local args = { ... } -- ...のままではクロージャで参照できんからテーブルに入れるよ if #args < 1 then return func -- 引数がなければそのまま返す end return function() return func(unpack(args)) -- argsを参照できるのはクロージャだからやで end end ----------------------------------------------------------- -- テーブルを上書きするよ<br> -- baseをoverで上書きするよ -- luaのテーブルは参照渡しだから、関数呼び出し元の方のテーブルも上書きされてるよ -- -- @param base 上書きされるテーブル -- @param over 上書きするテーブル ----------------------------------------------------------- function overwrite(base, over) for k, v in pairs(over) do base[k] = v -- テーブル上書きや! 以上! end end ----------------------------------------------------------- -- テーブルにイベントハンドラを追加するよ<br> -- 追加前に登録されてたハンドラもちゃんと呼ぶよ -- いまんとこ追加されたハンドラを削除する方法は無いよ -- CCのイベントシステム使わん場合の簡易な方法やな -- @param table [in/out]ハンドラを登録するテーブル -- @param key [in]登録対象のキー -- @param handler [in]登録するイベントハンドラ ----------------------------------------------------------- function addHandler(table, key, handler) local org_handler = table[key] local new_handler = handler if type(org_handler) == 'function' then -- すでにハンドラが登録されてたら new_handler = function(...) -- 元のハンドラと追加するハンドラ両方呼ぶ関数を作るよ org_handler(...) handler(...) end end table[key] = new_handler -- ハンドラ登録や! end ----------------------------------------------------------- -- ファイルを書き込む準備をするよ -- いまんとこ具体的には必要なディレクトリがなければ作る、ってだけやけどな -- @param path [in]書き込む予定のファイルのパス ----------------------------------------------------------- function prepareToWrite(path) local dir = fs.getDir(path) if not fs.exists(dir) then -- ディレクトリが存在するか見るで fs.makeDir(dir) -- 無いから作るよ end end ----------------------------------------------------------- -- 文字列をセパレータで分割する、イテレータ関数を作って返すよ -- セパレータが省略されると','を使うよ -- @param str [in]分割する文字列 -- @param separator [in]セパレータ・区切り文字。省略時は',' -- @return イテレータ関数 ----------------------------------------------------------- function stringSplitter(str, separator) separator = separator or ',' -- 省略時はカンマを使うで local init = 1 return function() if not init then return nil end -- 終わりや local sep_head, sep_tail, col_head, col_tail sep_head, sep_tail = string.find(str, separator, init, true) -- セパレータを探すよ if sep_head then -- 見つかったか? col_head, col_tail = init, sep_head - 1 -- 見つかったよ! init = sep_tail + 1 -- 次はセパレータの次の文字から探すよ else col_head, col_tail = init, -1 -- 見つからんかった init = nil -- 次はもうないよ end return string.sub(str, col_head, col_tail) -- 分割や! end end ----------------------------------------------------------- -- セパレータで区切られた文字列を分割するよ -- セパレータが省略されると','を使うよ -- strがnilの場合はnilを返すよ -- @param str [in]分割する文字列 -- @param separator [in]セパレータ・区切り文字。省略時は',' -- @return 分割された文字列を格納した配列 ----------------------------------------------------------- function splitString(str, separator) if not str then return nil end local result = {} -- 結果を入れる配列や for column in stringSplitter(str) do -- 分割するよ result[#result + 1] = column end return result end ----------------------------------------------------------- -- テキストファイルを読んで1行ずつ返す、イテレータ関数を作って返すよ -- 第二戻り値でopen中のファイルハンドルも返すで -- ファイルの最後まで読み込まないとファイルクローズしないから -- forの途中で抜け出す場合は、そっちでファイルクローズしないとあかんよ -- @param path [in]csvファイルのパス -- @return イテレータ -- @return ファイルハンドル ----------------------------------------------------------- function fileEachLine(path) -- ファイルがなければnilを返すだけの関数を返すよ if not fs.exists(path) then return (function() return nil end) end local h = fs.open(path, 'r') assert(h, 'fileEachLine cant open : '.. path) -- イテレータ関数 local function iterator() local line = h.readLine() -- 次の行を読むよ if not line then -- ファイルはもう終わりか? h.close() h = nil end return line, h end return iterator, h end ----------------------------------------------------------- -- csvファイルを読んでカラムの配列を返す、イテレータ関数を作って返すよ -- ファイルのクローズに関してはfileEachLine()と同じやで -- セパレータが省略されると','を使うよ -- @param path [in]csvファイルのパス -- @param separator [in]セパレータ・区切り文字。省略時は',' -- @return イテレータ -- @return ファイルハンドル -- @see fileEachLine ----------------------------------------------------------- function csvEachLine(path, separator) separator = separator or ',' local each_line, h = fileEachLine(path) -- イテレータ関数 local function parser() return splitString(each_line(), separator), h end return parser, h end
turi_lib.lua
turi_lib.lua
外部ファイルの取り込みが記述されてるだけのものです。
なんじゃこりゃと思うかもしれませんが、こういうのも一般的です。
os.loadAPI('/lib/apis/application') os.loadAPI('/lib/automate/jidoturi')
turi_startup.lua
turi_startup.lua
turiのスタートアッププログラムです。 startupの中で、
shell.run('/start/turi_startup')
のように呼び出すことを想定しています。
ものすごく眠い時に書いたやつをそのまま使っていて酷いですが、直す予定もないです。
----------------------------------------------------------- -- turi_startup.lua -- 自動釣りプログラムのスタートアップ -- @author 琴葉茜(さとうけい) ----------------------------------------------------------- os.loadAPI('/lib/apis/application') os.loadAPI('/lib/apis/const') os.loadAPI('/lib/apis/identify') os.loadAPI('/lib/apis/turtlefuel') application.turtleInit('turi_startup') ----------------------------------------------------------- -- プログラム引数処理 ----------------------------------------------------------- local args = { ... } local config_path = args[1] or 'turi_config' -- 第一引数はコンフィグファイル名や ----------------------------------------------------------- -- コンフィグファイル読み込み ----------------------------------------------------------- local config = application.loadConfig(config_path) ----------------------------------------------------------- -- 釣りをする方向に水ブロックがあるか ----------------------------------------------------------- local function isWater(direction) local success, data = turtleapis.INSPECT[direction]() if identify.isWaterBlock(data) then return true end return false end local search_water = { [const.FORWARD] = function() for i=1, 4 do if isWater(const.FORWARD) then return true end turtle.turnRight() end return false end, [const.UP] = function() return isWater(const.UP) end, [const.DOWN] = function() return isWater(const.DOWN) end, } if not search_water[config.turi.dir_fishing]() then -- 水ブロックは見つからんかった… return false end shell.run('turi')
jidoturi.lua
jidoturi.lua
自動釣りクラス
----------------------------------------------------------- -- jidoturi.lua -- 自動釣りAPI -- @author 琴葉茜(さとうけい) ----------------------------------------------------------- os.loadAPI('/lib/apis/akaneutils') os.loadAPI('/lib/apis/turtleapis') os.loadAPI('/lib/apis/turtlefuel') os.loadAPI('/lib/apis/identify') os.loadAPI('/lib/apis/simattyau') ----------------------------------------------------------- -- 自動釣りオブジェクトを作って返すよ<br> -- つり関数としまっちゃおうね関数はここに入るよ -- -- オブジェクトは釣りをした回数、釣れた回数を覚えてるよ -- -- @param setting 自動釣りオブジェクトの設定テーブル -- @return 自動釣りオブジェクト ----------------------------------------------------------- function new(setting) -- テーブル作成。デフォルト値も設定するよ ----------------------------------------------------------- -- @class table -- @name turi -- @description 自動釣りオブジェクト -- 自動でひたすら釣りするよ。釣ったものはチェストにしまうよ -- 焼ける魚とソレ以外でしまうチェストを分けられるよ -- 燃料が減ったら補給するよ -- @field hokyu 自動補給管理オブジェクト -- @field simattyau アイテム収納管理オブジェクト -- @field dir_fishing 釣りする方向 -- @field dir_store_fish 焼ける魚をしまうチェストの方向 -- @field dir_store_other 焼ける魚以外をしまうチェストの方向 -- @field wait_fishing 釣りの待機時間 -- @field wait_check_slot インベントリスロット毎の確認待機時間 -- @field end_fishing 釣り終了時に呼ばれるイベントハンドラ -- @field stats_auto_load 生成時に統計情報を自動で読み込むかどうか -- @field stats_save_add 統計情報保存時に追加モードで書き込むかどうか -- @field stats_result_path 統計情報ファイルのパス -- @field stats_items_path 釣れたアイテム情報ファイルのパス ----------------------------------------------------------- local turi = { hokyu = turtlefuel.new(), simattyau = simattyau.new(), dir_fishing = const.FORWARD,-- 釣りをする方向や dir_store_fish = const.UP, -- 魚をしまう方向や dir_store_other = const.DOWN, -- 魚以外をしまう方向や wait_fishing = 30, -- 釣りの待ち時間(秒数)や wait_check_slot = 1, -- しまっちゃおうねチェックの待ち時間(秒数)や stats_auto_load = false, stats_save_add = false, stats_result_path = 'turi.csv', stats_items_path = 'turi_items.csv', } -- クロージャOOP local self = turi -- private local tried = 0 -- 釣りした回数やで local success = 0 -- 釣れた回数やで local start_time -- 釣りを始めた時刻(os.clock()) ----------------------------------------------------------- -- 釣りを始める関数だよ<br> -- 釣り回数(self.tried)はまだカウントアップしないで ----------------------------------------------------------- function turi.startFishing() return turtleapis.ATTACK[self.dir_fishing]() -- 釣るよ end ----------------------------------------------------------- -- 釣り上げる関数だよ<br> -- ここで釣れた回数(self.success)をカウントアップするよ -- 釣り回数(self.tried)も釣り上げた時点でカウントアップするで ----------------------------------------------------------- function turi.endFishing() local result = turtleapis.DIG[self.dir_fishing]() -- 釣り上げるよ tried = tried + 1 -- 釣り上げたらまず、釣り回数をカウントアップするで if result then success = success + 1 -- 釣れたら釣れた回数をカウントアップや! end self.onEndFishing(result) -- 「釣り上げたで!」イベント発生 return result end ----------------------------------------------------------- -- 「釣り上げたで!」イベントを起こすよ<br> -- イベントと言ってもturiではCCのイベントシステムは使わんで -- 登録されたイベントハンドラを直接呼ぶよ -- @param result [in]釣りの結果 ----------------------------------------------------------- function turi.onEndFishing(result) local handler = self.end_fishing if not handler then return end handler(self, result) end ----------------------------------------------------------- -- タートルが釣りするよ<br> -- -- @param wait [in]釣りの待ち時間(秒数)や。省略時はself.waitが使われるよ ----------------------------------------------------------- function turi.turi(wait) wait = wait or self.wait_fishing while true do -- メインループや print('turude') self.startFishing() -- 釣り開始やで sleep(wait) -- ちょっと待つよ if self.endFishing() then -- 釣り上げるで print('tureta') else print('turen katta') end end end ----------------------------------------------------------- -- しまっちゃおうねAPIに渡す分類コールバック関数だよ<br> -- -- スロットを調べて、魚じゃなければチェストにしまうよ -- 焼ける魚とそれ以外でしまうチェストを分けるで -- 魚の場合はスタックがいっぱいな場合だけしまうよ -- @param slot_no [in]対象スロット番号 -- @param force [in]trueの場合はスタックいっぱいじゃなくてもしまうよ -- @return しまったらture / しまわなかったらfalse ----------------------------------------------------------- function turi.bunrui(slot_no, force) local item_detail = turtle.getItemDetail(slot_no) -- 対象のアイテム情報やで if not item_detail then return false end -- スロットが空ならなにもしないよ local direction = self.dir_store_other -- アイテムをしまう先 if identify.isFish(item_detail) then -- 魚やろか? -- 魚の場合、スタックいっぱいやなかったら何もしないで if not force and turtle.getItemSpace(slot_no) ~= 0 then return false end if identify.isRoastableFish(item_detail) then -- この魚、焼けるか? direction = self.dir_store_fish -- 焼ける魚ならこっちのチェストや end end print('slot '.. slot_no ..' wo simau yo!') -- しまうで~ return direction end ----------------------------------------------------------- -- 持っとるアイテムをチェストにしまうよ<br> -- -- インベントリスロットを順番に見ていって、 -- アイテムがあったらチェストにしまうよ -- 焼ける魚とそれ以外でしまうチェストを分けるで -- 魚の場合はスタックがいっぱいな場合だけしまうよ -- @param wait [in]1スロット処理するごとの待機時間やで ----------------------------------------------------------- function turi.simattyaoune(wait) wait = wait or self.wait_check_slot while true do -- メインループや for i = 1, 16 do -- タートルのインベントリスロットを順番に見てくよ self.simattyau.simau(self.bunrui, i) sleep(wait) end end end ----------------------------------------------------------- -- 持っとるアイテム全部をチェストにしまうよ<br> -- -- インベントリスロットを順番に見ていって、 -- アイテムがあったらチェストにしまうよ -- 焼ける魚とそれ以外でしまうチェストを分けるで -- 魚の場合はスタックがいっぱいな場合だけしまうよ ----------------------------------------------------------- function turi.simattyaouneAll() local bunrui = self.bunrui for i = 1, 16 do -- タートルのインベントリスロットを順番に見てくよ self.simattyau.simau( function(slot_no) return bunrui(slot_no, true) end, i ) end end ----------------------------------------------------------- -- 自動で釣りするよ<br> -- parallel.waitForAnyを使って自動で釣りを繰り返すよ -- 追加したいコルーチンを引数で渡せるよ -- @param ... 追加実行したいコルーチン(可変数) ----------------------------------------------------------- function turi.doFishing(...) -- 釣り実行 parallel.waitForAny( self.turi, self.simattyaoune, self.hokyu.hokyu, ... ) end ----------------------------------------------------------- -- 釣りを始めてからの経過時間を返すよ<br> -- まだ釣りを始めてなければ0を返すよ ----------------------------------------------------------- function turi.getTimeElapsed() if not start_time then return 0 end return os.clock() - start_time end ----------------------------------------------------------- -- 釣った回数を返すよ ----------------------------------------------------------- function turi.getTriedCount() return tried end ----------------------------------------------------------- -- 釣れた回数を返すよ ----------------------------------------------------------- function turi.getSuccessCount() return success end ----------------------------------------------------------- -- 統計情報をリセットするよ -- 経過時間・釣った回数・釣れた回数をリセットするよ ----------------------------------------------------------- function turi.resetStats() tried, success = 0, 0 start_time = os.clock() end ----------------------------------------------------------- -- 統計情報を(csv)ファイルに書き込むよ -- @param result_path [in]統計ファイルパス -- @param items_path [in]アイテムファイルパス ----------------------------------------------------------- function turi.saveStats(result_path, items_path) result_path = result_path or self.stats_result_path items_path = items_path or self.stats_items_path akaneutils.prepareToWrite(result_path) -- 書き込み準備や local mode = 'w' if self.stats_save_add then mode = 'a' end local h = fs.open(result_path, mode) -- ファイルオープン -- 釣り結果をcsv出力するよ h.writeLine(string.format('%d,%d,%d,%d,%d', self.wait_fishing, -- 釣り待機時間の設定値 self.getTriedCount(), -- 釣り回数 self.getSuccessCount(), -- 釣れた回数 self.getTimeElapsed(), -- 経過時間(秒) self.hokyu.getTotalUsage() -- 消費燃料(FL) )) h.close() -- ファイルクローズ -- 釣れたアイテムをcsv出力するよ self.simattyaouneAll() -- まず釣れたアイテムを全部しまっちゃうよ self.simattyau.saveStats(items_path) -- しまったアイテムをcsv出力や end ----------------------------------------------------------- -- 統計情報(csv)ファイルを読み込むよ -- @param result_path [in]統計ファイルパス -- @param items_path [in]アイテムファイルパス ----------------------------------------------------------- function turi.loadStats(result_path, items_path) result_path = result_path or self.stats_result_path items_path = items_path or self.stats_items_path self.resetStats() -- 統計ファイルを読み込むよ -- 複数行あった場合は最後の行を読み込むねん local result for columns in akaneutils.csvEachLine(result_path) do if #columns == 5 then result = columns end end if result then -- wait_fishingは読み込まないよ tried = tonumber(result[2]) success = tonumber(result[3]) start_time = os.clock() - tonumber(result[4]) self.hokyu.addUsage(tonumber(result[5])) end -- アイテムcsvを読み込むよ self.simattyau.loadStats(items_path) end -- 引数で渡された設定テーブルで上書き if setting then akaneutils.overwrite(turi, setting) end -- 統計情報初期化 self.resetStats() if self.stats_auto_load then self.loadStats() end return self end
turi_config.lua
turi_config.lua
コンフィグファイルですが実態はLuaのソースコードそのものです。
ここでオーバーライドする関数を記述してしまうのは暴挙なのかアリなのか。
----------------------------------------------------------- -- turi_config -- 自動釣りプログラムの設定ファイル -- @author 琴葉茜(さとうけい) ----------------------------------------------------------- local config = {} local turi = {} local hokyu = {} local save = {} ------------------------------------------------------------------------------- -- 動作設定 ここから -- 方向は、[forward / up / down / right / left / back]のどれかを使ってね ------------------------------------------------------------------------------- ----------------------------------------------------------- -- 釣り設定 ----------------------------------------------------------- ------------------------------------- -- 釣りをする方向(水ブロックの方向) turi.dir_fishing = 'forward' ------------------------------------- -- 焼ける魚をしまうチェストの方向 -- (bunruiをオーバーライドする場合はこれは使われないよ) turi.dir_store_fish = 'down' ------------------------------------- -- 焼ける魚以外をしまうチェストの方向 -- (bunruiをオーバーライドする場合はこれは使われないよ) turi.dir_store_other = 'down' ------------------------------------- -- 釣りの待ち時間 turi.wait_fishing = 25 ------------------------------------- -- 統計情報を自動読込するかどうか turi.stats_auto_load = true ------------------------------------- -- 統計情報保存時に追加モードで書き込むかどうか turi.stats_save_add = false ------------------------------------- -- 釣り結果出力ファイルのパス turi.stats_result_path = '/stats/turi.csv' ------------------------------------- -- 釣り結果出力ファイルのパス turi.stats_items_path = '/stats/turi_items.csv' ----------------------------------------------------------- -- 燃料補給設定 ----------------------------------------------------------- ------------------------------------- -- 燃料チェストの方向 hokyu.direction = 'right' ------------------------------------- -- 燃料確認間隔(秒) hokyu.wait = 60 ------------------------------------- -- 燃料補給閾値 -- Fuel levelがこの数値未満になったら補給するよ hokyu.threashold = 100 ------------------------------------- -- 燃料十分量 -- 補給時、Fuel levelがこの数値以上になったら補給を完了するよ hokyu.enough = 100 ----------------------------------------------------------- ------------------------------------- -- 釣りの最大回数 -- 指定回数釣りしたら止まるで -- nilまたはfalseを設定すると無制限に釣りを繰り返すよ config.turi_limit = 1000 ----------------------------------------------------------- -- 釣り結果を保存するファイル ----------------------------------------------------------- ------------------------------------- -- 出力頻度。釣りを何回したら出力するか save.frequency = 1 ------------------------------------- -- 釣りオブジェクトの走査間隔(秒数) save.interval = 10 ----------------------------------------------------------- -- gomi_bunrui チェスト設定 ----------------------------------------------------------- ------------------------------------- -- ゴミ箱の方向 -- 皮ブーツとか、チェストが山盛りになるやつはゴミ箱行きやで local dir_store_gomi = 'up' ------------------------------------- -- 釣果チェストの方向 -- ゴミ以外は全部こっちに入れるよ local dir_store_other = 'down' ------------------------------------------------------------------------------- -- 動作設定 ここまで ------------------------------------------------------------------------------- ----------------------------------------------------------- -- 自動釣りアイテム分類関数オーバーライド ----------------------------------------------------------- ----------------------------------------------------------- -- アイテムがゴミかどうか調べるよ -- 長時間放置が前提だから -- 皮ブーツとか釣り竿はチェストが溢れんようにゴミ扱いやで ----------------------------------------------------------- local function kore_gomika(item_detail) -- 革ブーツ・釣り竿、水入り瓶、サドルならゴミや for _i, v in ipairs { 'isLeatherBoots', 'isFishingRod', 'isWaterPotion', 'isSaddle', } do if identify[v](item_detail) then return true end end return false end ----------------------------------------------------------- -- しまっちゃおうねAPIに渡す分類コールバック関数やで -- この関数で自動釣りAPIのアイテム分類関数をオーバーライドするよ -- -- スロットを調べて、ゴミアイテムならゴミ用チェスト行きや -- ゴミでも魚でもなければ釣果用チェストにしまうで -- 魚の場合はスタックがいっぱいなら釣果用チェストにしまうよ -- -- @param slot_no [in]対象スロット番号 -- @param force [in]trueの場合はスタックいっぱいじゃなくてもしまうよ -- @return しまったらture / しまわなかったらfalse ----------------------------------------------------------- local function gomi_bunrui(slot_no, force) local item_detail = turtle.getItemDetail(slot_no) -- 対象のアイテム情報やで if not item_detail then return false end -- スロットが空ならなにもしないよ -- ゴミチェック if kore_gomika(item_detail) then print('gomibako ikiya') return dir_store_gomi -- コイツはゴミ箱行きや end if identify.isFish(item_detail) then -- 魚やろか? -- 魚の場合、スタックいっぱいやなかったら何もしないで if not force and turtle.getItemSpace(slot_no) ~= 0 then return false end end print('slot '.. slot_no ..' wo simau yo!') -- しまうで~ return dir_store_other end turi.bunrui = gomi_bunrui ----------------------------------------------------------- turi.hokyu = turtlefuel.new(hokyu) config.turi = turi config.save = save return config
turi.lua (part √2)
turi.lua
自動釣りプログラムturiのメイン部分です。
自動釣り機能自体はjidoturi.luaなどの他ファイルに記述されています。
本ファイルでは自動釣りクラスの準備と実行、そして自動釣りクラスで追加実行される、定期的な統計ファイル保存コルーチンと終了判定コルーチンの定義を行っています。
----------------------------------------------------------- -- turi.lua -- 自動釣りプログラム -- @author 琴葉茜(さとうけい) ----------------------------------------------------------- dofile('/lib/turi_lib') application.turtleInit('turi') ----------------------------------------------------------- -- プログラム引数処理 ----------------------------------------------------------- local args = { ... } local config_path = args[1] or 'turi_config' -- 第一引数はコンフィグファイル名や ----------------------------------------------------------- -- コンフィグファイル読み込み ----------------------------------------------------------- local config = application.loadConfig(config_path) ----------------------------------------------------------- -- result_file定義ブロック ----------------------------------------------------------- local result_file = config.save do -- クロージャOOPや local self = result_file -- 出力済みの釣り回数 self.last = 0 ----------------------------------------------------------- -- 釣り結果を出力するで -- @param turi [in]自動釣りオブジェクト -- @param force [in]trueなら回数に関係なく書き込むよ ----------------------------------------------------------- function result_file.write(turi, force) -- 書き込むのは釣り何回かに1回だけやで local tried = turi.getTriedCount() if not force and (tried % self.frequency ~= 0 or tried <= self.last) then return end print('tureta item csv wo save suruyo!') turi.saveStats() -- 書き込むよ self.last = tried -- 最後に書き込んだ釣り回数を覚えとくよ end ----------------------------------------------------------- -- 自動釣りの結果保存用コルーチン -- @param turi [in]自動釣りオブジェクト ----------------------------------------------------------- function result_file.saveResult(turi) while true do sleep(self.interval) self.write(turi) end end end ----------------------------------------------------------- -- 釣り終了判定コルーチン -- @param turi [in]自動釣りオブジェクト ----------------------------------------------------------- function checkExit(turi) repeat sleep(turi.wait_fishing - 1) -- 釣り1回につき1回動いて欲しいねん -- 釣り終了判定や until config.turi_limit and turi.getTriedCount() >= config.turi_limit end ----------------------------------------------------------- -- main ----------------------------------------------------------- -- 自動釣りオブジェクト生成 local turi = jidoturi.new(config.turi) -- 自動釣りで一緒に動かすコルーチンのリストを作るよ local coroutines = { akaneutils.getNoArgFunc(result_file.saveResult, turi), } if config.turi_limit then -- 釣り回数制限があるときだけ追加するよ coroutines[#coroutines + 1] = akaneutils.getNoArgFunc(checkExit, turi) end -- 釣り実行 print('turi suruyo!! ('.. turtlefuel.getFuelLevelString() ..')') turi.doFishing(unpack(coroutines)) -- 終わり print(string.format('%d kai turi sitasi tomaru yo!', turi.getTriedCount())) print(string.format('%d kai tureta de!', turi.getSuccessCount())) result_file.write(turi, true) -- 最後に統計ファイル書き出すよ