nR10ロール(2):戻り値をオブジェクトにしてみる
海月歩空様より頂いたコメントを参考に、というかほぼコピペで(すいません)、Rダイススクリプトの改変を試みてみました。
スクリプト本体は以下に。
スクリプト
//Rダイス呼び出し部 function event::onChannelText(prefix, channel, text) { //結果返却用オブジェクト var achieve = new Object(); //結果返却用オブジェクト内結果文字列用配列 achieve.array = new Array(); //結果返却用オブジェクト内達成値 achieve.value = 0; if (text.match(/#\d+R\d+/ig)){ //該当文字列を配列matchedTextに格納 var matchedText = text.match(/#(\d+)R(\d+)/i); //サブファンクションに飛ばす achieve = renegadeDice(matchedText[1],matchedText[2]); //結果を出力 for (i=0; i < achieve.array.length; i++){ send(channel, prefix.nick + ':' + achieve.array[i] ); } } } //Rダイス計算部 function renegadeDice(diceNumber, critNumber) { var diceRolled = 0; //ダイス1個振った結果 var faceDice = 10; //ダイスの面数(DXなので10面で固定) var criticalDice; //クリットしたダイスの個数をカウント var preAchieveValue = 0; //プレ達成値 var achieveValue = 0; //達成値 var achieveString = ""; //達成値が出るまでの過程の文字列 var count = 0; //結果返却用オブジェクト var achieve = new Object(); //結果返却用オブジェクト内結果文字列用配列 achieve.array = new Array(); //結果返却用オブジェクト内達成値 achieve.value = 0; do { //変数のリセット criticalDice = 0; preAchieveValue = 0; achieveString = diceNumber + 'R' + critNumber + '=['; //ダイス振るループ開始 for (var i = 0; i < diceNumber; i++){ //ダイス振る diceRolled = parseInt(Math.random() * faceDice)+ 1; //ダイスの出目がCRT値を上回ったかチェック if (diceRolled >= critNumber){ criticalDice++; preAchieveValue = 10; } else if (preAchieveValue < diceRolled){ preAchieveValue = diceRolled; } //振った結果のダイス目を文字列としてachieveStringに記録 achieveString += diceRolled + ','; } //一通り振ったところで結果を格納 achieveValue += preAchieveValue; achieveString = achieveString.substr(0, (achieveString.length - 1)) + ']=' + achieveValue; //ファンブル処理 if (preAchieveValue == 1 && count == 0){ achieveString += ' Fumble!!'; criticalDice = 0; } //クリティカル処理 if (criticalDice !== 0){ achieveString += ' Critical!!'; diceNumber = criticalDice; } //achieveオブジェクトの配列に達成値を出すまでの文字列を格納 achieve.array.push(achieveString); count++; } while (criticalDice !== 0); achieve.value = achieveValue; //結果オブジェクト返却 return(achieve); }
すいませんほんとに言われたとおりの書きかえです。
でもすごく分かりやすかったです。ありがとうございます。
実行結果
通常。
23:03 (ten-you) #1r10
23:03 (ten-you) ten-you:1R10=[5]=5
ファンブル。
23:03 (ten-you) #1r10
23:03 (ten-you) ten-you:1R10=[1]=1 Famble!!
クリティカル。
23:13 (ten-you) #5r7
23:13 (ten-you) ten-you:5R7=[4,9,3,7,7]=10 Critical!!
23:13 (ten-you) ten-you:3R7=[4,2,7]=20 Critical!!
23:13 (ten-you) ten-you:1R7=[10]=30 Critical!!
23:13 (ten-you) ten-you:1R7=[5]=35
当たり前だけど、やっぱりクリティカル値が1下がるとそれだけで全然クリティカル率が変わりますな。
var achieve = new Object();
オブジェクトを作る、という命令。リファレンスで見かけたことはあったのですが、いったいいつ使うものなのかさっぱり見当もついてませんでした。
その一方で、「ファンクションの戻り値が一つしか返せなくて不便だーprefixオブジェクトみたいに複数返せないかなー」と嘆いていた不思議。
海月歩空様ありがとうございます。
pushメソッド
もうひとつ初めて知ったのが「push」メソッド。
概要
与えられた要素を追加することによって配列を変異させ、その配列の新しい長さを返します。
Array.prototype.push() - JavaScript | MDN
配列にあとから要素を追加するメソッドだったんですね。
追記
function event::onChannelText(prefix, channel, text) { //結果返却用オブジェクト var achieve = new Object(); //結果返却用オブジェクト内結果文字列用配列 achieve.array = new Array(); //結果返却用オブジェクト内達成値 achieve.value = 0; if (text.match(/#\d+R\d+/ig)){ //該当文字列を配列matchedTextに格納 var matchedText = text.match(/#(\d+)R(\d+)/i); //サブファンクションに飛ばす achieve = renegadeDice(matchedText[1],matchedText[2]); //結果を出力 for (i=0; i < achieve.array.length; i++){ send(channel, prefix.nick + ':' + achieve.array[i] ); } } }
の
//結果返却用オブジェクト var achieve = new Object(); //結果返却用オブジェクト内結果文字列用配列 achieve.array = new Array(); //結果返却用オブジェクト内達成値 achieve.value = 0;
の部分。
オブジェクトの受け取りだから必要かと思って書いてましたが、以下のように省略してもOKでした。
function event::onChannelText(prefix, channel, text) { if (text.match(/#\d+R\d+/ig)){ //該当文字列を配列matchedTextに格納 var matchedText = text.match(/#(\d+)R(\d+)/i); //サブファンクションに飛ばす var achieve = renegadeDice(matchedText[1],matchedText[2]); //結果を出力 for (i=0; i < achieve.array.length; i++){ send(channel, prefix.nick + ':' + achieve.array[i] ); } } }
サブファンクションに飛ばす時に初めてvarつけて変数として宣言してます。
これで十分動きました。柔軟だなあ。