2010年02月28日

limechat2でjavascript作成(アリアンロッドのランダムダンジョン簡易版スクリプト)

javascript好きの皆さんこんばんは!
検索でブログ見に来ていただいている大半が、
ライムチャットとスクリプト絡みであることに最近気が付いた、海月歩空です。

というわけで、あまり書いていないなぁ、と思ったので、
久しぶりにスクリプト作成を行います。

ざっくり適当に書いていくので、
もっといい書き方はあると思いますよ!

後、過去作っている関数も使っているので、なんだろうこれ、
みたいになったら、過去も参照してください。

というか、ですね。
これ、いったん9割書き終わっていたんですよ。
それも、スクリプト作成しながら、ノリノリで。
でも、なんか瞬間停電がおきたらしく、
ぶっつりとデータが消えちゃいました……。
絶望した!

そんな悲しみに暮れているので、
本気で適当に書いています。
(説明とか)
後で見直したら、っていうか今見ても、
ここ直したいなぁ、というところがあるので、
ちょっと使ってみたい、とか、
この人はこうやって書いているのかと参考にしたい人向けです。

さて、今回はなにを作ったかというと、
アリアンロッドTRPGのランダムダンジョン用スクリプトです。
ただし、私はランダムダンジョンのデータを持っていません!
というわけで、簡易版となります。
プレイヤーとして参加したときの感覚から作っているので、
マップデータや扉も選択できる機能があればもっと便利になるんでしょうが、
データがないことには始まらない。

そのうち買ったら修正版……とかになるかなぁ。

さてさて。
簡易版って言うのはどんな機能? と思われますか?
ざっくり説明すると、トランプを混ぜて引いて、表示。
これくらいの機能です。

わお、ざっくり!

実際、それくらいしか作っていないので、書き用もないんですが!
細かい内容としては、いつもの適当仕様があったんですが、
やっぱり無くなってしまったので、更に適当にいきます。
・「探索準備[9]」で全てを未使用に変更後、
エース以外を8枚分とエースを1枚分をその階層で使用するモノとしてチェックする。
・「次のエリアへ」で、一回前に表示したモノを使用済みとし、
その階層で使用するものから無作為に一枚表示。
・「次の階層へ[9]」で、その階層で使用した・するモノを使用済みにし、エースのみ未使用に戻し、
未使用のエース以外を8枚分とエースを1枚分をその階層で使用するモノとしてチェックする。
・探索準備と次の階層へは、[]が無い場合、デフォルトの数字になる。
位でしょうか。

後、重要な要素として、トランプなので、使用したかどうかを記憶しておく必要があります。
(未使用だとか使用済みだとかというところですね)
エース以外は、同じのがでないようにする仕組みだけなら、配列とかでもいいのでしょうが、
回線切断なども含めて考えると、外部ファイルを使用して記録するのがいいでしょう。

というわけで、作ってみた結果が以下の通りです。
1個目は、前作ったダイスの基本関数を拡張したもの。
ファイル名:diceRoll.js

/******************************************************
ダイス基本関数

基本説明
ダイス個数回分、ダイス面数で指定されたダイスを振り、
ダイスの振った結果をオブジェクトとして返却する。

in
diceNum:ダイス個数(正数)
diceFace:ダイス面数(正数)

out
ダイス結果object
[
array:ダイス結果配列(Array)
sum:ダイス結果合計値
]
*******************************************************/
function diceRoll(diceNum, diceFace)
{
//返却用ダイスobject
var dice = new Object();
//返却用ダイス結果合計値
dice.sum = 0;
//返却用ダイス結果配列
dice.array = new Array();

if (diceNum <= 0 || diceFace <= 0)
{
dice.array.push(0);
return(dice);
}

//ダイス個数分、ダイス面数で指定されたダイスを振る。
for (var i = 0; i < diceNum; i++)
{
//ダイスを振った結果をダイス結果配列に。
dice.array.push(rand(diceFace));

//ダイスを振った結果を合計値に足していく。
dice.sum += dice.array[i];
}

//結果返却
return(dice);
}

//乱数関数ファイル読み込み
var fileObj = openFile("mt.js");
if (fileObj) {

try
{
var fileStr = fileObj.readAll();
fileObj.close();
eval(fileStr);
var mt1 = new MersenneTwister();
var myRand = function () {return mt1.next();};
log("mt.js読み込み成功");
}
catch(e)
{
var myRand = function () {return Math.random();};
log("mt.jsファイル読み込み失敗");
}
} else {
var myRand = function () {return Math.random();};
log("mt.jsファイルオープン失敗");
}

/*
ランダム関数

引数
num : 乱数範囲1-numの最大値
返却値
int数値
*/
function rand(num)
{
return(Math.floor(myRand() * num) + 1);
}

ここで取り込んでいる乱数関数ファイルというのは、
メルセンヌツイスターです。
こちらのサイトのメルセンヌツイスターのjsファイルがあれば、
取り込んでメルセンヌ関数のランダムになります。
無くても標準のランダム関数がロードされます。
個人的趣味の仕様ですね。

次はランダムダンジョンスクリプトのファイル。
ファイル名:ランダムダンジョン.js

/*******************************************************
ランダムダンジョンスクリプト機能

一意のID
表示項目(ハート 1等)
トランプの状態(未使用:0、階層選択状態:1、使用中:2、使用済:3)
スートのエースかどうかの区分(エースで無い:0、ある:1)
以上4項目をカンマ区切りで記述したものが複数行存在するtrump.txtを操作し、
ランダムダンジョン処理を行う。
********************************************************/
//文字列入力処理
function event::onChannelText(prefix, channel, text)
{

var drowCount;
var area;

//関数呼び出しワード
if (text.match(/^探索準備(\[(\d+)\])?([  ].*)?$/i))
{

drowCount = RegExp.$2;

if (drowCount == "")
{
drowCount = 6;
}

//初期化関数、階層関数呼び出し
if (setUpDungeon() && drawDungeon(drowCount))
{
//メッセージ
send(channel, "OK!");
}
else
{
//メッセージ
send(channel, "BAD SETTING!");
}
}

//関数呼び出しワード
if (text.match(/^次の階層へ(\[(\d+)\])?([  ].*)?$/i))
{

drowCount = RegExp.$2;

log(drowCount);
if (drowCount == "")
{
drowCount = 6;
}

if (drawDungeon(drowCount))
{
//メッセージ
send(channel, "OK!");
}
else
{
//メッセージ
send(channel, "BAD SETTING!");
}
}

//関数呼び出しワード
if (text.match(/^次のエリアへ([  ].*)?$/i))
{

if (reverseDungeon())
{
if ((area = dispDungeon()) != null)
{
//メッセージ
send(channel, "next area :" + area);
}
else
{
//メッセージ
send(channel, "this floor is over.");
}
}
else
{
//メッセージ
send(channel, "BAD SETTING!");
}
}


}

/******************************************************
↓初期読み込み処理↓
******************************************************/
//ダイス関数ファイル読み込み
var fileObj = openFile("diceRoll.js");
if (fileObj) {
try
{
var fileStr = fileObj.readAll();
fileObj.close();
eval(fileStr);
}
catch(e)
{
log("diceRoll.jsファイル読み込み失敗");
}
} else {
log("diceRoll.jsファイルオープン失敗");
}

/******************************************************
↑初期読み込み処理↑
******************************************************/

/******************************************************
トランプテキスト読み込み関数

基本説明
trump.txtを読み込み、文字列を返却する。
in
なし

out
テキストデータ/null
*******************************************************/
function readTrumpTxt()
{
try
{
var fileObj = openFile("trump.txt", true);
var fileStr = fileObj.readAll();
fileObj.close();

//結果返却
return(fileStr);
}
catch(e)
{
return(null);
}
}


/******************************************************
トランプテキスト書き込み関数

基本説明
trump.txtに文字列を書き込む。
in
テキストデータ

out
true/false
*******************************************************/
function writeTrumpTxt(trumpTxt)
{
try
{
var fileObj = openFile("trump.txt", false);
fileObj.write(trumpTxt);
fileObj.close();

//結果返却
return(true);
}
catch(e)
{
return(false);
}
}

/******************************************************
初期化関数

基本説明
初期化
in
なし

out
true/false
*******************************************************/
function setUpDungeon()
{
try
{
//変数設定
var trumpData = "";

//ファイル読み込み
if ((trumpData = readTrumpTxt()) == null)
{
//結果返却
return(false);
}

//データ初期化
trumpData = trumpData.replace(/(\d+,[^,]+,)\d(,\d)/g, "$10$2");

//ファイル書き込み
if (writeTrumpTxt(trumpData))
{

//結果返却
return(true);
}
return(false);
}
catch(e)
{
return(true);
}
}

/******************************************************
ダンジョン階層設定関数

基本説明
現在、エース以外で未使用以外のモノを使用済みに変更し、
エースを未使用状態に戻し、
エース以外からdrawCount-1個、無作為に階層選択状態に変更し、
エースを1個無作為に階層選択状態に変更する。
in
drawCount : その階層に使用するトランプの枚数

out
true/false
*******************************************************/
function drawDungeon(drawCount)
{
try
{
//変数設定
var trumpData = "";

var reg;
var result;
var idArray;
var idData;
var idNum;

//ファイル読み込み
if ((trumpData = readTrumpTxt()) == null)
{
//結果返却
return(false);
}

//エース以外で未使用以外の状態のモノを、使用済に変更する
trumpData = trumpData.replace(/(\d+,[^,]+,)[12](,0)/g, "$13$2");

//エースを未使用に戻す
trumpData = trumpData.replace(/(\d+,[^,]+,)\d(,1)/g, "$10$2");

//エース以外の未使用を抽出し、配列へ
reg = new RegExp(/(\d+),[^,]+,0,0/g);
idArray = new Array();
while((result = reg.exec(trumpData)) != null)
{
idArray.push(RegExp.$1);
}

//未使用が設定件数より少ないのでエラー
if (idArray.length < drawCount - 1)
{
return(false);
}

//エース以外からdrawCount-1個、無作為に階層選択状態に変更
for (var i = 0; i < drawCount - 1; i++)
{
idData = rand(idArray.length) - 1;
idNum = idArray[idData];
rep = new RegExp("(" + idNum + ",[^,]+,)0(,0)");
trumpData = trumpData.replace(rep, "$11$2");
idArray.splice(idData, 1);
}

//エースの未使用を抽出し、配列へ
reg = new RegExp(/(\d+),[^,]+,0,1/g);
idArray = new Array();
while((result = reg.exec(trumpData)) != null)
{
idArray.push(RegExp.$1);
}

//エースから1個、無作為に階層選択状態に変更
idData = rand(idArray.length) - 1;
idNum = idArray[idData];
rep = new RegExp("(" + idNum + ",[^,]+,)0(,1)");
trumpData = trumpData.replace(rep, "$11$2");
idArray.splice(idData, 1);

//ファイル書き込み
if (writeTrumpTxt(trumpData))
{

//結果返却
return(true);
}
return(false);
}
catch(e)
{
return(true);
}
}

/******************************************************
ダンジョン進行関数

基本説明
現在、使用中のモノを使用済みに変更し、
階層選択状態のモノから無作為に使用中状態に変更する。
in
なし

out
true/false
*******************************************************/
function reverseDungeon()
{
try
{
//変数設定
var trumpData = "";

var reg;
var result;
var idArray;
var idData;
var idNum;

//ファイル読み込み
if ((trumpData = readTrumpTxt()) == null)
{
//結果返却
return(false);
}

//使用中状態のモノを、使用済に変更する
trumpData = trumpData.replace(/(\d+,[^,]+,)2(,\d)/g, "$13$2");

//階層選択状態を抽出し、配列へ
reg = new RegExp(/(\d+),[^,]+,1,\d/g);
idArray = new Array();
while((result = reg.exec(trumpData)) != null)
{
idArray.push(RegExp.$1);
}

//階層選択状態から1個、無作為に使用中状態に変更
idData = rand(idArray.length) - 1;
idNum = idArray[idData];
rep = new RegExp("(" + idNum + ",[^,]+,)1(,[01])");
trumpData = trumpData.replace(rep, "$12$2");
idArray.splice(idData, 1);

//ファイル書き込み
if (writeTrumpTxt(trumpData))
{
//結果返却
return(true);
}
return(false);
}
catch(e)
{
return(true);
}
}

/******************************************************
ダンジョン表示関数

基本説明
現在、使用中の表示項目を返却する。
in
なし

out
文字列/null
*******************************************************/
function dispDungeon()
{
try
{
//変数設定
var trumpData = "";

var reg;
var result;
var trumpStr;

//ファイル読み込み
if ((trumpData = readTrumpTxt()) == null)
{
//結果返却
return(null);
}

//使用中状態を抽出
reg = new RegExp(/\d+,([^,]+),2,\d/);
if ((result = reg.exec(trumpData)) != null)
{
trumpStr = RegExp.$1;
return(trumpStr);
}

return(null);
}
catch(e)
{
return(null);
}
}


そして読み込むトランプのファイル。
ファイル名:trump.txt

1,スペード 1,1,1
2,スペード 2,0,0
3,スペード 3,0,0
4,スペード 4,0,0
5,スペード 5,0,0
6,スペード 6,0,0
7,スペード 7,1,0
8,スペード 8,1,0
9,スペード 9,0,0
10,スペード 10,0,0
11,スペード 11,1,0
12,スペード 12,0,0
13,スペード 13,1,0
14,ハート 1,0,1
15,ハート 2,0,0
16,ハート 3,0,0
17,ハート 4,0,0
18,ハート 5,0,0
19,ハート 6,0,0
20,ハート 7,0,0
21,ハート 8,0,0
22,ハート 9,0,0
23,ハート 10,0,0
24,ハート 11,0,0
25,ハート 12,0,0
26,ハート 13,1,0
27,クローバー 1,0,1
28,クローバー 2,2,0
29,クローバー 3,0,0
30,クローバー 4,0,0
31,クローバー 5,0,0
32,クローバー 6,0,0
33,クローバー 7,0,0
34,クローバー 8,0,0
35,クローバー 9,0,0
36,クローバー 10,0,0
37,クローバー 11,0,0
38,クローバー 12,0,0
39,クローバー 13,0,0
40,ダイヤ 1,0,1
41,ダイヤ 2,1,0
42,ダイヤ 3,0,0
43,ダイヤ 4,0,0
44,ダイヤ 5,0,0
45,ダイヤ 6,0,0
46,ダイヤ 7,0,0
47,ダイヤ 8,1,0
48,ダイヤ 9,0,0
49,ダイヤ 10,0,0
50,ダイヤ 11,0,0
51,ダイヤ 12,0,0
52,ダイヤ 13,0,0

うん、これはただのCSVっぽいファイルですね。

※rand()や読み込んでいる説明なしにテキスト、読み込みの処理などは、
過去のブログ記事を参照してください。

今回のこだわりは、「CSV風味のテキストを正規表現で操作する仕組み」です。
たぶん普通なら配列などで操作するところを、
(例えばカンマ区切りを切ったりはったり、使用・未使用を別配列に入れたり)
置き換えやらマッチングやらで解決!
(配列も一部使っていますが)

地味に、ただの文字列変数でやれているあたりがセクシィです。
(自画自賛気味)

個人的には、もう少し改良の余地があるので
(2回3回同じようなことをしている部分があるのは、別にまとめられるはず)
そこがちょっと不満ですが、最初配列でやろうとしたときに時間がかかりすぎて、
気力がとぎれてしまったので今回はここまでにしておきます。

本当は地形データも組み込みたくなってきたのに手元に本が無いから、
完全に完成しないし、いいか! なんて思ってないんですよ!
(ぶっちゃけた!?)

では、今回のまとめと前回までのスクリプトを圧縮してここに上げておきます
必要があれば使ってみてください。
登録の仕方や使い方が解らないよ、とかの声があれば今度それ用の記事でも作ります。
他の場所でちゃんと説明しているサイトがいっぱいあるから、
それを参照した方が早いし正確なんですけどね!
(ぶっちゃけすぎです)

それではスクリプト大好き海月歩空でした!
posted by 海月歩空 at 11:37| Comment(0) | TrackBack(0) | プログラム
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/35736597
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック