itachiCPU ver5
大分改善。CPU。
新しいデッキ追加してなくてごめん。
速度とかはだいぶ良くなったはず。
判断もそこそこになったはず。
どうぞ。
「itachiScript_v5.zip」をダウンロード
さて、
次はどうしようかなぁ
| 固定リンク
| コメント (0)
| トラックバック (0)
大分改善。CPU。
新しいデッキ追加してなくてごめん。
速度とかはだいぶ良くなったはず。
判断もそこそこになったはず。
どうぞ。
「itachiScript_v5.zip」をダウンロード
さて、
次はどうしようかなぁ
| 固定リンク
| コメント (0)
| トラックバック (0)
えーはい。
2.12仕様でCPU作りました。
ホードのパフォーマンスが多少良くなってると思いたい。
あと新デッキ追加。
ろくにテストしてないからたぶん弱い。
っていうか、デッキタイプが冒険しすぎた感が・・・ゲフンゲフン
ダウンはこちら
「itachiScript_v4.zip」をダウンロード
まだまだいろいろもさく中
バグとかあったら報告してくれると嬉しいです。
| 固定リンク
| コメント (2)
| トラックバック (0)
戦闘関連でまだまだ改善余地があったのでいろいろ修正。
他、デッキ内容も弄りました。
これでそれなりに攻防が出来るはず!!!!
どぞー
「itachiScript_v3.zip」をダウンロード
よーし次は新デッキだ><
| 固定リンク
| コメント (0)
| トラックバック (0)
いろいろ指摘いただいた部分を修正。
そこそこ戦える感じになったカナー?
主にホードが。
って分けで修正版CPU「itachiScript.zip」をダウンロード
なにか違和感を見つけたら報告していただけるとうれしーです。
でわ
| 固定リンク
| コメント (1)
| トラックバック (0)
って分けで作ってみた。
こちら→「itachiScript.zip」をダウンロード
うーん・・・よわい・・・
まーちょこちょこ修正していくよ!
とりあえずエラーは出なさそうなのでどーぞ
| 固定リンク
| コメント (2)
| トラックバック (0)
【実践~最低限動作のCPUを作る~】
前回のAIスクリプトについて★マークの部分だけ編集すれば
CPUは問題なく動作すると書きました。
ってわけで、
まずはその最低限動作するCPUを作ってみます。
関数の説明とかは公式リファレンスを見よ。
ちなみに、
「スキン設定用iniファイル」と「CPUスクリプト」は出来ているものとします。
もちろんskin直下にディレクトリも作ってある感じで。
ここでのメインは「AIスクリプト」の編集です。
~編集その前に~
luaの記述についてある程度書いておいたほうがいいかもしれない。
AI記述する上で最低限使うやつだけ紹介していきます。
<記述基礎>
・命令文の最後に「;」を記述する。メンドイけど忘れずに。
・文字列はダブルクォートで囲む感じなのか?
・文字列結合は「..」で行なう感じなのか?
例)
out("はろわ" .. "(ハローワーク)") ;
→「はるわ(ハローワーク)」って出力される。
<変数定義>
・型はあまり意識する必要なし。ABCD独自のクラスは意識しまくれ。
・「nil」は空と言う意味。NULLとかと同じだとえばいい気がする。
・関数内で完結する変数は「local」って指定する。
・なんかインクリメントできないみたい。めんでぇ
例)
local testvalue = nil ;
→関数内で完結する変数「testvalue」を定義し、値を「nil(空)」にする。
<テーブル型>
・配列とかそこらへん全部テーブル型で処理される
・{}で囲んで複数値を指定する
・INDEXは「1」からみたい
・参照は[]でINDEX指定する感じ
・INDEXは文字でも出来るみたい。数字のヤツとは別物みたい。
・#をつけて参照すると要素数が参照できるぽい
例)
local testtable = {123, 567, nil, "TESTEST"} ;
testtable["abc"] = 9999 ;
↓
testtable[2] → 「567」
#testtable → 「4」
testtable["abc"] → 「9999」
<メンバ変数・メンバ関数>
・メンバ変数は{クラス}.{メンバ変数名}で参照するみたい
・メンバ関数は{クラス}:{メンバ関数}で使用するみたい
・クラスは当然インスタンス化しておく必要がある感じ
例)
local cpu = Player(ID.CPU) ; -- Playerクラスインスタンス
cpu.PID → メンバ変数「PID」参照
cpu:GetHP() → メンバ関数「GetHP()」使用
<条件文>
・記述は、if (条件) then ~ elseif (条件) then ~ else ~ end ;
・比較演算子の等号は「==」、不等号は「~=」なところが注意
<繰り返し文>
・記述は、for 変数=開始値 , 終了値 do ~ end ;
・あんまり注意点はないわ
とりあえずここら辺だけ覚えておけばおk。
もっと細かい説明はLuaリファレンスを見てください。
----------------------------------------------------------
では、ABCD_AIの記述に参ります。
①AI_INFOの編集
まずはAI_INFOを編集します。
っていってもデッキの名前と説明文書けばいいだけです。適当で良いです。
余裕がある人は笑いを取ることを目指そう。
これは関数じゃないのでreturnとかもしないで良いです
②CreateDeckの編集
関数です。returnはデッキ内容そのものですので、
return後の値指定で直接記述しちゃいます。
記述方法はCardData関数を使用します。
「*」記号でデッキ投入枚数も指定できるのでラクチンです。
↓↓こんな感じで↓↓
return {
-- デッキ内のカードリスト設定
CardData("BT_001J") * 20 , -- 炎のクリスタル
CardData("BT_002J") * 10 , -- 水のクリスタル
CardData("BT_003J") * 10 , -- 風のクリスタル
} ;
※40~100枚になるよう注意しませう
③InitCPUの編集
ここではCPUの基本動作を指定します。
きちんとAIを組みたかったらここでの動作指定は一切しません。
でも今回は簡単CPU作成!なのでここでの指定に頼り切ります。
で、動作指定ですが「Regist系」の関数を用いて動作を定義します。
Regist系は基本下記の3種類。
デッキに投入したカードにあわせて記載していきます。
・RegistCardUse(Card card , int type , int value , table arg)
→カード詠唱の設定です。対象を指定するカードとかは使用できないぽい
・RegistAttack(Card card , int type , int value , table arg)
→クリーチャー攻撃設定です。カードごとに個別に攻撃条件を指定できる
・RegistBlock(int type , table arg)
→クリーチャーブロック設定です。指定したタイプにのっとってブロックする
↓↓こんな感じで↓↓
-- 炎のクリスタル使用設定
RegistCardUse(CardData(EX.BT , 001) , USE_TYPE.BASIC_CRYSTAL , 10 , nil) ;
-- クリーチャーブロック設定(先手優先で)
RegistBlock(BLOCK_TYPE.FIRST_ATK , nil) ;
-- クリーチャーアタック設定
RegistAttack(CardData() , ATTACK_TYPE.AUTO , 30 , nil) ;
④GameOverの編集
これは空スクリプトでも結構書いてある場所です。
メッセージ部分だけ書き換えてくれればおk。
⑤ExecCPUの編集
メインです。戻り値にTrueかFalse返さなきゃいけないのに注意。
(なんか動作起こしたらTrue返すんだよ!)
しかし、今回の簡単CPUではあんまり使いません。
今回ここで定義するのは次の動作のみです。
・対象を指定するソーサリーの詠唱
・スキルの使用
・ドローストックの使用
このうち、ドローストックについてはもう記述してあります。
あとはソーサリーとスキルです。
スキルについてはタイプによって動作を分けたりする必要があってメンドイので
ここでは指定しない。簡単CPUなんだからスキルなんて高等なことしないの!!
つーわけで、
ソーサリーの詠唱ロジックだけ紹介します。
結構複雑っていうか面倒な手順踏んでる。別関数化したほうがいいかもネン
↓↓こんな感じ↓↓
-- 手札に存在するか検索
local cpu = Player(ID.CPU) ;
local hands = {} ; -- 手札定義
local num = cpu:GetHand(hands) ; -- 手札取得
local tgtcard = CardData("BT_012J") ; -- 検索するカード(せっかくだから火炎弾で)
for i=1 , #hands do -- 手札分ループ
if(hands[i].Ex==tgtcard.Ex) and (hands[i].CID==tgtcard.CID) then -- EXとCIDで検索HITチェック
if(hands[i]:CanCast(ID.CPU)) then -- 詠唱可能かチェック
local tgtclist = hands[i]:GetTargetable(ID.CPU) ; -- 対象リストを取得
if (tgtclist~=nil) then -- 対象リストがnil(空)でない場合
local tgtcid = math.random(#tgtclist) ; -- 対象リストからランダムで1つ選ぶ
if (hands[i]:Cast(ID.CPU,{tgtclist[tgtcid]})) then -- 詠唱動作指定
result = true ; -- ExecCPU関数の戻り値指定
end ;
break ; -- ループ脱出
end ;
end ;
end ;
end ;
⑥CheckReDrawの編集
Trueを返したらリドローする。
リドローの指針を条件指定しておいて、リドロー指定する。
特に無視して常にfalseを返すのでもいい。リドローしないだけだから。
一応クリスタル0個だったらリドローみたいなロジックだけ書いておく
といっても上のソーサリー詠唱とあんま変わらんかったわ。
↓↓こんな感じ↓↓
-- ReDraw条件
local cpu = Player(ID.CPU) ;
local hands = {} ; -- 手札定義
local num = cpu:GetHand(hands) ; -- 手札取得
local tgtcard = CardData("BT_001J") ; -- 検索するカード(炎のクリスタル)
local tgtcnt = 0 ; -- 検索HIT数
for i=1 , #hands do -- 手札分ループ
if(hands[i].Ex==tgtcard.Ex) and (hands[i].CID==tgtcard.CID) then -- EXとCIDで検索HITチェック
tgtcnt = tgtcnt + 1 ; -- カウントアップ
end ;
end ;
if (tgtcnt==0) then -- 0個だったらリドロー
ret = true ;
end ;
⑦SelectBlockの編集
ブロッククリーチャーの選択です。
ブロッククリーチャーはdestBlockに格納し、
戻り値はカウンタークリーチャーになります。
プレイヤーがブロック側の時に編集しないよう注意!
とはいえ、RegistBlockを指定していればほとんど書くことありません。
なので、カウンターしたい時だけ編集します。
適当なロジック例を出しておきます。
↓↓こんな感じ↓↓
local counter = nil ;
local cpu = Player(ID.CPU) ;
if(attack:GetController()==ID.CPU) then
-- CPU攻撃
-- 基本何もしない(勝手にプレイヤーのブロッククリーチャーを指定しない)
else
-- CPUブロック
--
local cres = {} -- クリーチャー
local num = cpu:GetCreature(cres) ; -- クリーチャー取得
for i=1 , #cres do -- クリーチャー分ループ
local c = Creature(cres[i]) ; -- クリーチャーインスタンス生成
if(c:CanAttack(true)) then -- カウンターモードで攻撃可能チェック
counter = cres[i] ; -- 攻撃可能ならカウンターに
break ; -- ループ脱出
end ;
end ;
end ;
return counter ;
⑧SelectBattleSpell編集
使用するバトルスペルを返します。
使わなければ何も返す必要なし。
まぁ一応ロジック例を出しておく。
↓↓こんな感じ↓↓
local ret = nil ;
local cpu = Player(ID.CPU) ;
-- 攻撃側によって使用バトルスペルを設定する
if(attack:GetController()==ID.CPU) then
-- CPUが攻撃
-- 攻撃時のやつまで書くのははメンドイからパス
else
-- CPUがブロック
--
local hands = {} ; -- 手札定義
local num = cpu:GetHand(hands) ; -- 手札取得
local tgtcard = CardData("BT_057J") ; -- 検索するカード(突然死で)
for i=1 , #hands do -- 手札分ループ
if(hands[i].Ex==tgtcard.Ex) and (hands[i].CID==tgtcard.CID) then -- EXとCIDで検索HITチェック
if(hands[i]:CanCast(ID.CPU)) then -- 詠唱可能かチェック
if(cpu:GetHP()<=10) then -- 自HP10以下の時のみ突然死を使う。
ret = handc ;
end ;
end ;
end ;
end ;
end ;
return ret ;
!!!!!!!ここまでで完成!!!!!!!
----------------------------------------------------------
じゃー早速動かしてみます。
「SkinSelector.exe」で作ったやつをぶっこんで、
ABCD本体起動して、「OfflineDuel」を選べば出てくるはず。
後は対戦するだけです。
エラーが出たら泣いてエラー箇所を探します。
エラー記述に行数が出てたりするのでそれを参考にします。
まぁ大体記述ミスとかそこらへんだと思うよ。
DP()関数でデバッグプリントを指定している場合、
本体の「config.ini」の「DebugConsole = 0」を1にすれば見れる。
んでもって「DebugOutLog = 0」を1にすればファイル出力もしてくれる。
ちょーうれしい。
あと、手軽に構文チェックを行ないたい場合、
空想具現化プログラミングさんのところからLua5.1.3(lua.org版)を落として
コマンドプロンプトで
.\lua5.1\bin\luac5.1.exe {luaソースファイル}
ってやれば構文チェックしてくれる。
ちょーべんり。
こんなとこですかね。
慣れてきたら独自の条件での動作を追加していってみてくださいな。
以上。
| 固定リンク
| コメント (0)
| トラックバック (0)
CPUスクリプトについて解説のような覚書を書こうと思います。
スクリプト作成に関する個をとまとめながら
気付いたことをチョコチョコ補足で書いていくんで、
あまり参考にならない記事になりそう。
興味ある人はどうぞ。
【CPUスクリプト基本構造】
□スキン設定用iniファイル(Sample:index.ini)
│
└□CPUスクリプト(Sample:HogeCPU.lua)
│
└□デッキAIスクリプト(Sample:Deck1AI.lua)
【CPU作成大筋の手順】
[1]ABCD本体のskinフォルダ内にCPU用のフォルダを作成する
例:ABCDX_02_11\skin\hogescript
→「hogescript」フォルダを新規作成
[2]必要なファイルをぶちこむ
・スキン設定用iniファイル
・CPUスクリプト
・デッキAIスクリプト
・CPUで使う画像とかスキン設定画面用のSS画像とか
【CPU作成~スキン設定用iniファイル編~】
最初に設定用のiniファイルを作成します。
iniファイルなので必要事項を埋めればいいだけです。楽勝。
【CPU作成~CPUスクリプト編~】
CPUスクリプトのファイルを作成します。
ここも基本動作ではなくCPUの定義のみなので楽勝です。
編集部分も「CPU名」と「デッキ」と「画像」の3箇所のみ。
→詳細は公式リファレンス
【CPU作成~デッキAIスクリプト編~】
さて、一番の肝です。
ここから本格的にスクリプトを作成していきます。
luaについてあまり習熟していないのでluaについての深い説明は省きます。
あくまでABCDのCPUスクリプトに特化した説明にしようと思います。
ですので最低限のプログラム知識を持っている前提で進めます。
感覚的にJavaとかC++とかやったことあるならダイジョブそうだよ。
~AI基本構造~
ABCDのスクリプトは「関数」を定義します。
関数はABCD本体が動作する際にそれぞれのタイミングで呼び出され、実行されるようです。
関数内で指定した動作は関数が返った後にABCD本体で実行され、CPU動作となる。みたい。
叩き台用に「空スクリプト」を用意しておきました→参考DL:空スクリプト「EmpScript.zip」
関数定義だけしてあって中身すっからかんのファイルです。
ABCD本体付属のサンプルスクリプトは参考になりますが
CPU作成ソースとしては若干扱いにくいので
この空スクリプトを編集する前提でこれから話しを進めていきます。
さて、
定義するべき関数は下記の通りです。
以下のリストには呼び出されるタイミングも<>←この中に記載しておきます。
ABCDのAIスクリプトはこれらの関数全てと「AI_INFO」を定義することで完了します。
★AI_INFO :AIに関する情報や処理間隔を定義<起動時にロード>
★CreateDeck :CPUデッキ内容を定義<起動時に呼び出し>
・CreatePlayerDeck:プレイヤーデッキ内容を定義。通常はNIL指定<起動時に呼び出し>
・OpenDeckSelect :デッキ選択時処理<デッキ選択時に呼び出し>
・InitializeGame :画像を読込・初期化<初回対戦時だけ呼び出し>
・FinalizeGame :読込画像を解放<対戦終了時に呼び出し>
★InitCPU :対戦初期処理<毎対戦開始時に呼び出し>
★GameOver :対戦終了処理<勝敗決定時に呼び出し>
・ShuffleLib :CPUデッキの並びを操作。NIL指定でシャッフル<シャッフル時に呼び出し>
・ShufflePlayerLib :プレイヤーデッキの並びを操作。NIL指定でシャッフル<シャッフル時に呼び出し>
★ExecCPU :CPUAIメイン処理<処理間隔毎に呼び出し>
★CheckReDraw :リドローのチェック<処理間隔毎リドロー可能時に呼び出し>
★SelectBlock :ブロッククリーチャー選択<戦闘フェイズ開始後に呼び出し>
★SelectBattleSpell:バトルスペル選択<戦闘フェイズでブロック指定後に呼び出し>
★マークがついてる部分は編集必須です。
通常対戦のCPUを作るならば他はデフォルトのままでも問題ありません。
細かい説明は公式リファレンスを見たほうが良いです。
次から簡単なCPUを作る要領で個別に解説していきます。
| 固定リンク
| コメント (0)
| トラックバック (0)
最近のコメント