第三回でアイテムをいじりましたが、今回はそれとは別の路線です。あのときは大文字・小文字に続いて「記号」を使いましたが、やはりお先真っ暗な方法です。そこで、もっと建設的な方法をとってみましょう。
それはつまり、数字で表す方法です。というのも、現行の方法では、アイテムは「aのアイテム」とか「Vのアイテム」というような情報を、プログラム側が「aは何番で、Vは何番で・・・」というように変換して処理していたわけです。それなら、最初から番号で表すようにしようということです。
例えば、今所持しているアイテムを「aとbとcとdとe」のように表しているとしたら、それを「10番と11番と12番と13番と14番」のように表すようにするということです。これなら、アイテムを何個追加しようが深く考える必要はありません。
さて、具体的にどうするかですが、この変更による大きな変更点は、今まで1つのアイテムにつき必ず1文字で表していたのを、数字で書くから2文字以上になる可能性があるということです。そこで、文字数とは別の視点で、複数のアイテムを記述した文字列を1つのアイテムずつに切り分けることが必要になってきます。
よく思いつくのは、「3,55,82,142,6,・・・」のように数字と数字の間を区切る方法です。それでもいいですが、今回は別の方法をとろうと思います。
というのも、珍走記では、既にこのように複数の数字をまとめて扱っている例があるのです。
それは、建物の管理です。珍走記では、あるプレイヤーが持つ家、ビル、工場、秘密基地を別々に管理しています。また、第一回で説明したように、マスには1つ1つ固有の数字あるのを利用して、例えば「●●さんの家は、何番と何番と何番の場所にある」「●●さんのビルは、何番と何番にある」のように管理しています。ここで、複数の数値を扱っているわけです。
さて、具体的な方法は、たとえば5番と10番と15番の場合、
+5++10++15+
と表されます。これは、「+5+」「+10+」「+15+」が並んだ形です。このように、「+数値+」を並べているのです。この方法の利点は、操作、特に1つ削除することが簡単だということです。たとえば、それから10番を消したいとき、「+10+」を探して消せば、「+5++15+」のようになり正常に5番と15番が残ります。他の方法だと、こうも簡単にいかないことも多いです。
今回、アイテムも、これと同じように番号で表すように改造してみましょう。
また、車についてもあわせて変更します。なぜなら、実はアイテムと車はひとまとめに扱われていて、アイテムデータのうち1〜9番目が車、10番目以降がアイテム・・・のようになっているからです。
第三回と同じように、1つずつファイルを見てみます。
まず、custom.cgiです。いろいろ細々とした処理があります。
sub ability
{
local($num,@others,$target,$tmp);
($num,@others)=@_;
return if $others[0]==0;
$target=int(rand($#others+1));
$target=$others[$target];
if($'user{"${num}_car"}==6 && rand(1)<0.7){
local($capacity);
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($'user{"${num}_car"});
if($'user{"${target}_move"}<=0 && $'user{"${target}_status"}!~/b/ && length($'user{"${target}_item"})>0 && length($'user{"${num}_item"})<$capacity){
local($pick);
$pick=substr($'user{"${target}_item"},int(rand(length($'user{"${target}_item"}))),1);
$'user{"${num}_item"}.=$pick;
$'user{"${target}_item"}=~s/$pick//;
($pick)=&lib'getprice($pick);
$'user{"${num}_alert"}.=$'user{"${target}_name"}."から$pickを吸い取りました。<br>";
$'user{"${target}_alert"}.=$'user{"${num}_name"}."に$pickを吸い取られました。<br>";
&lib'chat("<$num>は<$target>から<font color=\"brown\">$pick</font>を吸い取りました。");
}
}elsif($'user{"${num}_car"}==8 && rand(1)<0.5){
if($'user{"${target}_move"}<=0 && $'user{"${target}_status"}!~/b/){
local($prf,$pname);
$'user{"${target}_position"}=&lib'getrandom;
($pname,$tmp,$tmp,$prf)=&lib'getgraph($'user{"${target}_position"});
$prf=$lib'prfname[$prf];
$'user{"${num}_alert"}.=$'user{"${target}_name"}."を$prf $pnameまで吹っ飛ばしました。<br>";
$'user{"${target}_alert"}.=$'user{"${num}_name"}."に$prf $pnameまで吹っ飛ばされました。<br>";
&lib'chat("<$num>は<$target>を<font color=\"green\">$prf $pname</font>まで吹っ飛ばしました。");
}
}
return;
}
まず、これは、バキュームカーがアイテムを吸い取る処理と、戦車が車を吹っ飛ばす処理です。
車の種類を判定する処理について、「6」はバキュームカー、「8」は戦車ですが、これを"+6+"のように変更します。つまり、最終的に$'user{"${num}_car"}の中身は「+番号+」のような形にするということです。つまり、
if($'user{"${num}_car"}=="+6+" && rand(1)<0.7){
}elsif($'user{"${num}_car"}=="+8+" && rand(1)<0.5){
という具合です。
また、$pick=substr($'user{"${target}_item"},int(rand(length($'user{"${target}_item"}))),1);
の処理は、バキュームカーからアイテムを吸い取られる側の車が持つアイテムのうち、ランダムに1つ選ぶという処理です。現状の場合、アイテム1個につき1文字なので、簡単でした。今回は、そうはいかないので、splitで切り分けてみましょう。「++」で区切ります。「+5++10++15+」なら「+5」「10」「15+」に分かれますね。余計なものが入りますが、ただしく個数が分かります。つまり、その1行は、
local(@items);
@items = split(/\+\+/,$'user{"${target}_item"});
$pick = $item[int(rand(@items))];
$pick =~ s/\+//g;
$pick = "+" . $pick . "+";
$pickには、「+10+」のような「+」つきのアイテム1つが入っています。それにより、あとの処理と互換性をもたせることができます。
次に、下のほうのspecialサブルーチンの、
$'user{"${num}_alert"}.="パトカーに飲酒運転でつかまりました。車を没収されました。";
&lib'chat("<$num>はパトカーに<font color=\"red\">飲酒運転</font>でつかまりました。");
&lib'chat("車を<font color=\"red\">没収</font>されました。");
$'user{"${num}_car"}=9;
$'user{"${num}_work"}=~s/\([1-8]\)//g;
if($'user{"${num}_money"}>0){
$'user{"${num}_alert"}.="罰金で持ち金がなくなりました。";
&lib'chat("罰金で持ち金が<font color=\"red\">なくなり</font>ました。");
$'user{"${num}_money"}=0;
}
$'user{"${num}_alert"}.="<br>";
この部分にも修正が必要です。パトカーに車を没収されるとき、車のデータを書き換えますが、これを「+番号+」の書式に変換します。
$'user{"${num}_alert"}.="パトカーに飲酒運転でつかまりました。車を没収されました。";
&lib'chat("<$num>はパトカーに<font color=\"red\">飲酒運転</font>でつかまりました。");
&lib'chat("車を<font color=\"red\">没収</font>されました。");
$'user{"${num}_car"}="+9+";
$'user{"${num}_work"}=~s/\(\+[0-9]+\+\)//g;
if($'user{"${num}_money"}>0){
$'user{"${num}_alert"}.="罰金で持ち金がなくなりました。";
&lib'chat("罰金で持ち金が<font color=\"red\">なくなり</font>ました。");
$'user{"${num}_money"}=0;
}
$'user{"${num}_alert"}.="<br>";
このようになります。同様に、
$'user{"${num}_alert"}.="当たり屋にぶつけられました。車が壊れたのでチャリンコになりました。<br>";
&lib'chat("<$num>は当たり屋にぶつけられました。");
&lib'chat("車が壊れたので<font color=\"red\">チャリンコ</font>になりました。");
$'user{"${num}_car"}=9;
$'user{"${num}_status"}=~s/p//g;
$'user{"${num}_work"}=~s/\([1-8]\)//g;
の当たり屋に車を壊される処理も、
$'user{"${num}_alert"}.="当たり屋にぶつけられました。車が壊れたのでチャリンコになりました。<br>";
&lib'chat("<$num>は当たり屋にぶつけられました。");
&lib'chat("車が壊れたので<font color=\"red\">チャリンコ</font>になりました。");
$'user{"${num}_car"}="+9+";
$'user{"${num}_status"}=~s/p//g;
$'user{"${num}_work"}=~s/\(\+[0-9]+\+\)//g;
のように直します。次の死神に車を捨てられる処理も同様に直します。
}elsif($'user{"${num}_car"}!=9 && rand(1)<0.3){
$'user{"${num}_alert"}.="死神に車を捨てられました。車を失ったのでチャリンコになりました。<br>";
&lib'chat("<$num>は死神に車を捨てられました。");
&lib'chat("車を失ったので<font color=\"red\">チャリンコ</font>になりました。");
$'user{"${num}_car"}=9;
$'user{"${num}_work"}=~s/\([1-8]\)//g;
これは、
}elsif($'user{"${num}_car"}!="+9+" && rand(1)<0.3){
$'user{"${num}_alert"}.="死神に車を捨てられました。車を失ったのでチャリンコになりました。<br>";
&lib'chat("<$num>は死神に車を捨てられました。");
&lib'chat("車を失ったので<font color=\"red\">チャリンコ</font>になりました。");
$'user{"${num}_car"}="+9+";
$'user{"${num}_work"}=~s/\(\+[0-9]+\+\)//g;
のようになります。
さて、今度は
}elsif($special==4 && $'user{"${num}_status"}!~/b/){
local(@specials,$i);
if(length($'user{"${num}_item"})>=3 && rand(1)<0.2){
$'user{"${num}_alert"}.="死神にアイテムを全部捨てられました。<br>";
&lib'chat("<$num>は死神に<font color=\"red\">アイテムを全部</font>捨てられました。");
$'user{"${num}_item"}='';
という部分にも修正が必要です。これは死神がアイテムを全て捨てる処理ですが、「アイテムを3つ以上持っている」という条件がついています。これも同じように配列化して数を数えます。
}elsif($special==4 && $'user{"${num}_status"}!~/b/){
local(@specials,$i,@items);
@items = split(/\+\+/,$'user{"${num}_item"});
if(@items>=3 && rand(1)<0.2){
$'user{"${num}_alert"}.="死神にアイテムを全部捨てられました。<br>";
&lib'chat("<$num>は死神に<font color=\"red\">アイテムを全部</font>捨てられました。");
$'user{"${num}_item"}='';
さらに、天使の処理も修正します。
}elsif($special==5){
local(@specials,$i);
if(rand(1)<0.3){
$'user{"${num}_alert"}.="天使が".$'user{"${num}_name"}."券を10枚くれました。<br>";
&lib'chat("<$num>は天使に".$'user{"${num}_name"}."券を<font color=\"red\">10枚</font>もらいました。");
for($i=0; $i<10; $i++){
$'user{"${num}_ticket"}.=$num.",";
}
}elsif($'user{"${num}_item"} ne '' && length($'user{"${num}_item"})<=int($capacity/2) && rand(1)<0.4){
これは、天使がアイテムを倍増する際に数をチェックしているものです。同様に、
}elsif($special==5){
local(@specials,$i,@items);
@items = split(/\+\+/,$'user{"${num}_item"});
if(rand(1)<0.3){
$'user{"${num}_alert"}.="天使が".$'user{"${num}_name"}."券を10枚くれました。<br>";
&lib'chat("<$num>は天使に".$'user{"${num}_name"}."券を<font color=\"red\">10枚</font>もらいました。");
for($i=0; $i<10; $i++){
$'user{"${num}_ticket"}.=$num.",";
}
}elsif($'user{"${num}_item"} ne '' && @items<=int($capacity/2) && rand(1)<0.4){
のようにします。これで、custom.cgiの修正は終了です。
次に修正するのは、eventi.cgiです。これは、アイテムショップの処理です。あちこちにアイテムの総数を数える処理が出てくるので、
&lib'err(1,-2) if($form{'code'} ne $user{"${num}_code"});
&lib'err(22,-2) if($user{"${num}_move"}>0);
($pname,$px,$py,$prf,$ptype,$popt)=&lib'getgraph($user{"${num}_position"});
&lib'err(19,-2) if $ptype ne 'i';
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($user{"${num}_car"});
に1行追加して
&lib'err(1,-2) if($form{'code'} ne $user{"${num}_code"});
&lib'err(22,-2) if($user{"${num}_move"}>0);
($pname,$px,$py,$prf,$ptype,$popt)=&lib'getgraph($user{"${num}_position"});
&lib'err(19,-2) if $ptype ne 'i';
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($user{"${num}_car"});
@myitems = split(/\+\+/,$user{"${num}_item"});
としておきましょう。これも上と同じ修正です。@itemsとしないのは、実はこの変数名は下のほうで既に使われているからです。
まず、
if($form{'buy'} ne ''){
($mname,$mprice)=&lib'getprice($form{'buy'});
&lib'err(19,-2) if($popt!~/${form{'buy'}}/ || $user{"${num}_money"}<$mprice || length($user{"${num}_item"})>=$capacity);
$user{"${num}_money"}-=$mprice;
$user{"${num}_item"}.=$form{'buy'};
&lib'setuser(%user);
}elsif($form{'sell'} ne ''){
($mname,$mprice)=&lib'getprice($form{'sell'});
&lib'err(14,-2) if $user{"${num}_item"}!~/${form{'sell'}}/;
$user{"${num}_money"}+=$mprice/2;
$user{"${num}_item"}=~s/${form{'sell'}}//;
&lib'setuser(%user);
}
の部分を修正します。これは、アイテムを買う処理と売る処理です。最終的に、$form{'buy'}や$form{'sell'}にも「+番号+」のような形でアイテムの番号が入っているというようにしましょう。
上と同じ修正で、
if($form{'buy'} ne ''){
($mname,$mprice)=&lib'getprice($form{'buy'});
&lib'err(19,-2) if($popt!~/\Q${form{'buy'}}\E/ || $user{"${num}_money"}<$mprice || @myitems>=$capacity);
$user{"${num}_money"}-=$mprice;
$user{"${num}_item"}.=$form{'buy'};
@myitems = split(/\+\+/,$user{"${num}_item"});
&lib'setuser(%user);
}elsif($form{'sell'} ne ''){
($mname,$mprice)=&lib'getprice($form{'sell'});
&lib'err(14,-2) if $user{"${num}_item"}!~/\Q${form{'sell'}}\E/;
$user{"${num}_money"}+=$mprice/2;
$user{"${num}_item"}=~s/\Q${form{'sell'}}\E//;
@myitems = split(/\+\+/,$user{"${num}_item"});
&lib'setuser(%user);
}
となります。
その後は、アイテム一覧を表示する処理です。
print <<EOM;
<center>
<table border=0>
<tr><td colspan=3 bgcolor="#FFFF77" nowrap><center><b>持ち金:$user{"${num}_money"}万円 最大積載量:$capacity</b></center></td></tr>
EOM
print"<tr><td colspan=3 bgcolor=\"#FF7777\"><center><b>これ以上持てません!!</b></center></td></tr>\n" if(length($user{"${num}_item"})>=$capacity);
print"<tr><td colspan=3 bgcolor=\"#CCFFCC\"><center>買う</center></td></tr>\n";
@items=split(//,$popt);
foreach $item(@items){
($mname,$mprice,$explain)=&lib'getprice($item);
print <<EOM;
<form action="eventi.cgi" method="POST">
<input type="hidden" name="buy" value="${item}">
<input type="hidden" name="user" value="$num">
<input type="hidden" name="code" value="${form{'code'}}">
<tr><td bgcolor="#CCCCFF">${mname}</td><td bgcolor="#FFFFCC">${mprice}万円</td><td bgcolor="#FFCCCC">
EOM
if($user{"${num}_money"}>=$mprice && length($user{"${num}_item"})<$capacity){
print"<input type=\"submit\" value=\"買う\" onClick=\"flag=1\">";
}
print" <a href=\"javascript:alert('$explain')\"><font color=\"#000000\">?</font></a></td></tr></form>\n";
}
if($user{"${num}_item"} ne ''){
print <<EOM;
<tr><td colspan=3 bgcolor=\"#CCFFCC\"><center>売る</center></td></tr>
EOM
@items=split(//,$user{"${num}_item"});
foreach $item(@items){
($mname,$mprice,$explain)=&lib'getprice($item);
$mprice/=2;
print <<EOM;
<form action="eventi.cgi" method="POST">
<input type="hidden" name="sell" value="${item}">
<input type="hidden" name="user" value="$num">
<input type="hidden" name="code" value="${form{'code'}}">
<tr><td bgcolor=\"#CCCCFF\">${mname}</td><td bgcolor=\"#FFFFCC\">${mprice}万円</td><td bgcolor="#FFCCCC"><input type="submit" value="売る" onClick=\"flag=1\"> <a href=\"javascript:alert('$explain')\"><font color=\"#000000\">?</font></a></td></tr>
</form>
EOM
}
}
ここに、とりあえず上と同じ修正を施します。しかし、他にもまだすべきことがあります。
それは、店のアイテムをひとつずつリストにして表示するところです。「@items = ...」の行で店のアイテムを1つずつ切り分けて配列にしていますが、この方法に変更が必要です。今までと同じようにsplitで切り分けるのですが、ひとつひとつの要素が正しく「+番号+」の形をしている必要があります。そこで、最初と最後の要素について形を整えます。
また、もっと下に自分の所持しているアイテムを表示する処理があるので、ここも同様にします。
まとめると、次のようになります。
print <<EOM;
<center>
<table border=0>
<tr><td colspan=3 bgcolor="#FFFF77" nowrap><center><b>持ち金:$user{"${num}_money"}万円 最大積載量:$capacity</b></center></td></tr>
EOM
print"<tr><td colspan=3 bgcolor=\"#FF7777\"><center><b>これ以上持てません!!</b></center></td></tr>\n" if(@myitems>=$capacity);
print"<tr><td colspan=3 bgcolor=\"#CCFFCC\"><center>買う</center></td></tr>\n";
@items = split(/\+\+/,$popt);
if(@items > 0){
$items[0] =~ s/\+//g;
$items[$#items] =~ s/\+//g;
}
foreach $item(@items){
$item = "+" . $item . "+";
($mname,$mprice,$explain)=&lib'getprice($item);
print <<EOM;
<form action="eventi.cgi" method="POST">
<input type="hidden" name="buy" value="${item}">
<input type="hidden" name="user" value="$num">
<input type="hidden" name="code" value="${form{'code'}}">
<tr><td bgcolor="#CCCCFF">${mname}</td><td bgcolor="#FFFFCC">${mprice}万円</td><td bgcolor="#FFCCCC">
EOM
if($user{"${num}_money"}>=$mprice && @myitems<$capacity){
print"<input type=\"submit\" value=\"買う\" onClick=\"flag=1\">";
}
print" <a href=\"javascript:alert('$explain')\"><font color=\"#000000\">?</font></a></td></tr></form>\n";
}
if($user{"${num}_item"} ne ''){
print <<EOM;
<tr><td colspan=3 bgcolor=\"#CCFFCC\"><center>売る</center></td></tr>
EOM
@items = split(/\+\+/,$user{"${num}_item"});
if(@items > 0){
$items[0] =~ s/\+//g;
$items[$#items] =~ s/\+//g;
}
foreach $item(@items){
$item = "+" . $item . "+";
($mname,$mprice,$explain)=&lib'getprice($item);
$mprice/=2;
print <<EOM;
<form action="eventi.cgi" method="POST">
<input type="hidden" name="sell" value="${item}">
<input type="hidden" name="user" value="$num">
<input type="hidden" name="code" value="${form{'code'}}">
<tr><td bgcolor=\"#CCCCFF\">${mname}</td><td bgcolor=\"#FFFFCC\">${mprice}万円</td><td bgcolor="#FFCCCC"><input type="submit" value="売る" onClick=\"flag=1\"> <a href=\"javascript:alert('$explain')\"><font color=\"#000000\">?</font></a></td></tr>
</form>
EOM
}
}
そして、eventc.cgiも修正します。これは、カーショップの処理です。
まず、
if($form{'buy'} ne ''){
($mname,$mprice)=&lib'getprice($form{'buy'});
&lib'err(19,-2) if($popt!~/${form{'buy'}}/ || $user{"${num}_money"}<$mprice);
$user{"${num}_money"}-=$mprice;
$user{"${num}_car"}=$form{'buy'};
$user{"${num}_status"}=~s/p//g;
$user{"${num}_work"}=~s/\([1-8]\)//g;
&lib'setuser(%user);
print <<EOM;
<center>
新しい車は<img src="${lib'imgdir}/car${form{'buy'}}${color}.gif"><b>$mname</b>です!<br>
EOM
を修正します。修正すべきは最後から2番目の行で、この行は、$user{"${num}_work"}の内容を変更しています。この変数は、目的地から一番遠かった際にチャリンコになったとき、もともと乗っていた車が保存してあるもので、他の人が一番遠くてペナルティを受けたときに、ここの情報を利用して車が返してもらえます。新しく車を買ったらもうこの情報は不要なので、なくしているというわけです。この中身も、「+番号+」のような形に変更します。つまり、
if($form{'buy'} ne ''){
($mname,$mprice)=&lib'getprice($form{'buy'});
&lib'err(19,-2) if($popt!~/\Q${form{'buy'}}\E/ || $user{"${num}_money"}<$mprice);
$user{"${num}_money"}-=$mprice;
$user{"${num}_car"}=$form{'buy'};
$user{"${num}_status"}=~s/p//g;
$user{"${num}_work"}=~s/\(\+[0-9]+\+\)//g;
&lib'setuser(%user);
$carnum = $form{'buy'};
$carnum =~ s/\+//g;
print <<EOM;
<center>
新しい車は<img src="${lib'imgdir}/car$carnum${color}.gif"><b>$mname</b>です!<br>
EOM
のように変更します。ちなみに、この変数には、他にもさまざまな情報が入っています。
次に、
print <<EOM;
<center>
<table border=0>
<tr><td colspan=5 bgcolor="#FFFF77" nowrap><center><b>持ち金:$user{"${num}_money"}万円</b></center></td></tr>
<tr><td bgcolor="#FFCCCC"><center>車種</center></td><td bgcolor="#CCFFCC" nowrap>速度</td><td bgcolor="#CCCCFF" nowrap>積載量</td><td bgcolor="#FFFFCC"><center>価格</center></td><td bgcolor="#FFCCCC"></td></tr>
EOM
@cars=split(//,$popt);
foreach $car(@cars){
($mname,$mprice,$speed,$capacity)=&lib'getprice($car);
print <<EOM;
<form action="eventc.cgi" method="POST">
<input type="hidden" name="buy" value="${car}">
<input type="hidden" name="user" value="$num">
<input type="hidden" name="code" value="${form{'code'}}">
<tr><td bgcolor="#FFCCCC" nowrap><img src="${lib'imgdir}/car${car}${color}.gif">${mname}</td><td bgcolor="#CCFFCC"><center>${speed}</center></td><td bgcolor="#CCCCFF"><center>${capacity}</center></td><td bgcolor="#FFFFCC" nowrap>${mprice}万円</td><td bgcolor="#FFCCCC">
EOM
if($user{"${num}_money"}>=$mprice){
print"<input type=\"submit\" value=\"買い換える\" onClick=\"flag=1\">";
}
print"</td></tr></form>\n";
}
print"</table>\n";
}
の部分も変更します。これは、売っている車の一覧で、上のeventi.cgiと変更するところは似ています。
ただ、車はその画像を表示するため、多少違った処理が必要になってきます。
print <<EOM;
<center>
<table border=0>
<tr><td colspan=5 bgcolor="#FFFF77" nowrap><center><b>持ち金:$user{"${num}_money"}万円</b></center></td></tr>
<tr><td bgcolor="#FFCCCC"><center>車種</center></td><td bgcolor="#CCFFCC" nowrap>速度</td><td bgcolor="#CCCCFF" nowrap>積載量</td><td bgcolor="#FFFFCC"><center>価格</center></td><td bgcolor="#FFCCCC"></td></tr>
EOM
@cars=split(/\+\+/,$popt);
if(@cars > 0){
$cars[0] =~ s/\+//g;
$cars[$#cars] =~ s/\+//g;
}
foreach $car(@cars){
local $carnum;
$carnum = $car;
$car = "+" . $car . "+";
($mname,$mprice,$speed,$capacity)=&lib'getprice($car);
print <<EOM;
<form action="eventc.cgi" method="POST">
<input type="hidden" name="buy" value="${car}">
<input type="hidden" name="user" value="$num">
<input type="hidden" name="code" value="${form{'code'}}">
<tr><td bgcolor="#FFCCCC" nowrap><img src="${lib'imgdir}/car${carnum}${color}.gif">${mname}</td><td bgcolor="#CCFFCC"><center>${speed}</center></td><td bgcolor="#CCCCFF"><center>${capacity}</center></td><td bgcolor="#FFFFCC" nowrap>${mprice}万円</td><td bgcolor="#FFCCCC">
EOM
if($user{"${num}_money"}>=$mprice){
print"<input type=\"submit\" value=\"買い換える\" onClick=\"flag=1\">";
}
print"</td></tr></form>\n";
}
print"</table>\n";
}
join.cgiも変更が必要です。これは、参加者の新規登録の処理ですが、最初の車を乗用車に設定する部分を変更します。つまり、
$user{"${i}_car"}=1;
を
$user{"${i}_car"}="+1+";
というようにします。join.cgiはこれだけです。
login.cgiは、最初のログイン画面です。車の画像を表示したりするあたりで処理の変更が必要になりますね。これは、カーショップの処理と似ています。
if($flag==1){
$printed.="+$maxnum+";
($carname)=&lib'getprice($user{"${maxnum}_car"});
$carimg="<img src=\"".$lib'imgdir."/car".$user{"${maxnum}_car"}.$user{"${maxnum}_color"}.".gif\" alt=\"$carname\">";
$statusimg=$user{"${maxnum}_status"};
$statusimg=~s/([a-z])/<img src=\"${lib'imgdir}\/status$1\.gif\" alt=\"${statusname{$1}}\">/g;
$prizeimg=$user{"${maxnum}_prize"};
$prizeimg=~s/([a-z])/<img src=\"${lib'imgdir}\/prize$1\.gif\" alt=\"${prizename{$1}}\">/g;
print <<EOM;
<tr><td bgcolor="#DDDDFF"><center>$number位</center></td><td bgcolor="#FFDDDD"><center><a href="main.cgi?user=$maxnum"><font color="black">${user{"${maxnum}_name"}}</font></a></center></td><td bgcolor="#FFDDDD"><center>$carimg<br><font size=1>$carname</font></center></td><td bgcolor="#FFDDDD"><center>$statusimg</center></td><td bgcolor="#FFDDDD"><center>$maxmoney万円</center></td><td bgcolor="#FFDDDD"><center>$maxprf $maxpname</center></td><td bgcolor="#FFDDDD"><center>約${mindist}km</center></td><td bgcolor="#FFAAAA"><center>$maxprop万円</center></td><td bgcolor="#FFDDDD"><center>$prizeimg</center></td></tr>
EOM
$number++;
}
これが、
if($flag==1){
$printed.="+$maxnum+";
($carname)=&lib'getprice($user{"${maxnum}_car"});
local($carnum);
$carnum = $user{"${maxnum}_car"};
$carnum =~ s/\+//g;
$carimg="<img src=\"".$lib'imgdir."/car".$carnum.$user{"${maxnum}_color"}.".gif\" alt=\"$carname\">";
$statusimg=$user{"${maxnum}_status"};
$statusimg=~s/([a-z])/<img src=\"${lib'imgdir}\/status$1\.gif\" alt=\"${statusname{$1}}\">/g;
$prizeimg=$user{"${maxnum}_prize"};
$prizeimg=~s/([a-z])/<img src=\"${lib'imgdir}\/prize$1\.gif\" alt=\"${prizename{$1}}\">/g;
print <<EOM;
<tr><td bgcolor="#DDDDFF"><center>$number位</center></td><td bgcolor="#FFDDDD"><center><a href="main.cgi?user=$maxnum"><font color="black">${user{"${maxnum}_name"}}</font></a></center></td><td bgcolor="#FFDDDD"><center>$carimg<br><font size=1>$carname</font></center></td><td bgcolor="#FFDDDD"><center>$statusimg</center></td><td bgcolor="#FFDDDD"><center>$maxmoney万円</center></td><td bgcolor="#FFDDDD"><center>$maxprf $maxpname</center></td><td bgcolor="#FFDDDD"><center>約${mindist}km</center></td><td bgcolor="#FFAAAA"><center>$maxprop万円</center></td><td bgcolor="#FFDDDD"><center>$prizeimg</center></td></tr>
EOM
$number++;
}
というようになります。
さて、ここから先が大変なところです。lib.cgiは、細々とした処理の詰め合わせのようなものです。データの読み込みとかもこのlib.cgiが担当しています。
sub getprice
{
local($index);
if(ord($_[0])>=97){
$index=ord($_[0])-87;
}elsif(ord($_[0])>=65){
$index=ord($_[0])-29;
}elsif((ord($_[0])>=48)&&(ord($_[0])<=57)){
$index=$_[0];
}elsif(ord($_[0])>=33){
$index=ord($_[0])+29;
}
return(split(/\,/,$item[$index]));
}
は、アイテムを表す文字列を引数に受け取り、その情報を取得する関数です。重要なのは、前はアイテム(や車)は今まで文字で表されていて、それを番号に変換しているというところです。今回それを直接番号で表すように変更するので、ここがまるまる変わります。ちなみに、このソースには第三回の変更が施されていますが、これはどうでもいいです。
sub getprice
{
local($index);
$index = $_[0];
$index =~ s/\+//g;
$index = int($index);
return(split(/\,/,$item[$index]));
}
このようになります。すっきりしましたね。これはとても重要な変更ですが、lib.cgiの変更は実はここだけです。
item.cgiは、実際にアイテムを使ったときの処理です。まず、23行目あたりの、
&lib'err(14,-2) if($user{"${num}_item"}!~/$item/);
の行を修正します。これは正規表現のパターンの中で変数を使うと、それが直接パターンになります。今まではアイテムが1文字だったから、そのアイテムが含まれているか確認できましたが、今回「+番号+」の形にしたので、パターンに記号が含まれています。ここで、その記号を無効化するには、「\Q 〜 \E」で囲みます。つまり、
&lib'err(14,-2) if($user{"${num}_item"}!~/\Q$item\E/);
こうなります。
基本的に、正規表現でアイテムの変数を使っているときは同様に修正する必要が出てきます。33行目あたりの
$user{"${num}_item"}=~s/$item//;
も同様に
$user{"${num}_item"}=~s/\Q$item\E//;
とします。さらに、500行目付近の
$user{"${num}_item"}=~s/$item//;
も同様に
$user{"${num}_item"}=~s/\Q$item\E//;
とします。
さて、この後から、「$item=~/[ 〜 ]/」という形が出てきます。それは、$itemに、[ 〜 ]の中で列挙したアイテムがあるかどうかを判定しているのですが、それはアイテムがひとつ1文字で表されていたからこのような書き方が可能であったもので、この書き方を変える必要があります。
具体的な方法は、アイテム1つを表すのは、英数字1文字から「+番号+」の形に変わったので、そうする必要があります。しかし、例えば3番と5番と10番の場合を判定したい場合、「+3++5++10+」のようにするだけではだめです。それぞれを「|」で区切る必要があります。つまり、その場合「+3+|+5+|+10+」となります。[ 〜 ]は不要になります。
例えば、40行目付近の
$item=~/[bdfvZ]/
の場合、a〜zが10〜35、A〜Zが36〜61であることを踏まえて、
$item=~/\+11\+|\+13\+|\+15\+|\+31\+|\+61\+/
となります。つまり、11番と13番と15番と31番と61番のうちどれかというわけですね。
親切に全部列挙すると、
$item=~/[s]/
↓
$item=~/\+28\+/
$item=~/[ijkmnprwxyzABCDEFGIKMNOPQTVWY]/
↓
$item=~/\+18\+|\+19\+|\+20\+|\+22\+|\+23\+|\+25\+|\+27\+|\+32\+|\+33\+|\+34\+|\+35\+|\+36\+| (略)
ここまで書いて気づいたと思います。分かりづらいことこの上ありません。そこで、今回は関数を作って使います。
lib.cgiの最後(「1;」より前)にこれを追加しておきましょう。
sub matchitem
{
local($item, $i, $flg);
$item = $_[0];
$item =~ s/\+//g;
$item = int($item);
$flg = 0;
for($i=1; $i<@_; $i++){
if($item == $_[$i]){
$flg = 1;
last;
}
}
return $flg;
}
これは、最初の引数にアイテムの文字列、2つめ以降の文字列に番号を渡すと、それらの番号のうち1つに当てはまれば1、当てはまらなければ0を返すというものです。これを利用して、
$item=~/[bdfvZ]/
↓
$item=~/\+11\+|\+13\+|\+15\+|\+31\+|\+61\+/
↓
&lib'matchitem($item, 11,13,15,31,61)
$item=~/[s]/
↓
$item=~/\+28\+/
↓
&lib'matchitem($item,28)
のように書けます。だいぶ見やすくなりましたね。
$item=~/[ijkmnprwxyzABCDEFGIKMNOPQTVWY]/
も、
&lib'matchitem($item,18,19,20,22,23,25,27,32,33,34,35,36,37,38,39,40,41,42,44,46,48,49,50,51,52,55,57,58,60)
となります。
以下同様に書きますが、数字がひとつだけなどの場合は、無理にmatchitemを使う必要もないと思います。
$item!~/[qtuHJU]/
↓
&lib'matchitem($item, 26,29,30,43,45,56)==0
$item=~/[Z]/
↓
&lib'matchitem($item,61)
$item=~/[rsT]/
↓
&lib'matchitem($item, 27,28,55)
$item=~/[ab]/
↓
&lib'matchitem($item, 10,11)
$item=~/[cd]/
↓
&lib'matchitem($item, 12,13)
$item=~/[ef]/
↓
&lib'matchitem($item, 14,15)
$item=~/g/
↓
&lib'matchitem($item, 16)
$item=~/[hs]/
↓
&lib'matchitem($item, 17,28)
$item=~/s/
↓
&lib'matchitem($item, 28)
$item=~/i/
↓
&lib'matchitem($item, 18)
$item=~/j/
↓
&lib'matchitem($item, 19)
$item=~/k/
↓
&lib'matchitem($item, 20)
$item=~/l/
↓
&lib'matchitem($item, 21)
$item=~/m/
↓
&lib'matchitem($item, 22)
$item=~/n/
↓
&lib'matchitem($item, 23)
$item=~/o/
↓
&lib'matchitem($item, 24)
$item=~/p/
↓
&lib'matchitem($item, 25)
$item=~/q/
↓
&lib'matchitem($item, 26)
$item=~/R/
↓
&lib'matchitem($item, 53)
$item=~/S/
↓
&lib'matchitem($item, 54)
$item=~/[tU]/
↓
&lib'matchitem($item, 29,56)
$item=~/U/
↓
&lib'matchitem($item, 56)
$item=~/[uv]/
↓
&lib'matchitem($item, 30,31)
$item=~/[wr]/
↓
&lib'matchitem($item, 32,27)
$item=~/r/
↓
&lib'matchitem($item, 27)
$item=~/[xyTY]/
↓
&lib'matchitem($item, 33,34,55,60)
$item=~/x/
↓
&lib'matchitem($item, 33)
$item=~/y/
↓
&lib'matchitem($item, 34)
$item=~/Y/
↓
&lib'matchitem($item, 60)
$item=~/[zABCDEF]/
↓
&lib'matchitem($item, 35,36,37,38,39,40,41)
$item=~/[ABCDEF]/
↓
&lib'matchitem($item, 36,37,38,39,40,41)
$item=~/G/
↓
&lib'matchitem($item, 42)
$item=~/H/
↓
&lib'matchitem($item, 43)
$item=~/I/
↓
&lib'matchitem($item, 44)
$item=~/J/
↓
&lib'matchitem($item, 45)
$item=~/K/
↓
&lib'matchitem($item, 46)
$item=~/L/
↓
&lib'matchitem($item, 47)
$item=~/M/
↓
&lib'matchitem($item, 48)
$item=~/N/
↓
&lib'matchitem($item, 49)
$item=~/O/
↓
&lib'matchitem($item, 50)
$item=~/P/
↓
&lib'matchitem($item, 51)
$item=~/Q/
↓
&lib'matchitem($item, 52)
$item=~/V/
↓
&lib'matchitem($item, 57)
$item=~/W/
↓
&lib'matchitem($item, 58)
$item=~/X/
↓
&lib'matchitem($item, 59)
さて、まだまだやることはあります。500行目付近
($wildname)=&lib'getprice($item);
$result=$wildname."が出てきました。<br>".$result;
$user{"${num}_item"}=~s/Z//;
で、アイテムを文字で表す「Z」があります。これは、
($wildname)=&lib'getprice($item);
$result=$wildname."が出てきました。<br>".$result;
$user{"${num}_item"}=~s/\+61\+//;
とする必要があります。
さて、今度は54行目あたりに、
if(&lib'matchitem($item,61)){
$wild=1;
$item=substr("aceghijklqtuwxyzABCDEFGHMNOPQUX",int(rand(31)),1);
}
という処理があります。第三回の改造をした人なら、
if(&lib'matchitem($item,61)){
$wild=1;
my($chrs) = "aceghijklqtuwxyzABCDEFGHMNOPQUX";
$item=substr($chrs,int(rand(length($chrs))),1);
}
のようになっていると思います。これは、第三回でも解説したように四次元ポケットの処理で、候補のアイテムの中から1つ選ぶ処理です。
改造後の処理は、アイテムの文字を列挙してその中から1つ選ぶようになっていますが、これを番号を列挙するようにしてみましょう。すると、
if(&lib'matchitem($item,61)){
$wild=1;
my(@nums) = (10,12,14,16,17,18,19,20,21,26,29,30,32,33,34,35,36,37,38,39,40,41,42,43,48,49,50,51,52,56,59);
$item="+" . $nums[int(rand(@nums))] . "+";
}
こうなります。
さらに、まだあります。けむりだまで、アイテムを盗む処理です。
}elsif(&lib'matchitem($item, 26)){
foreach(@target){
if(&probability($_)==1 && $user{"${_}_status"}!~/b/){
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($user{"${num}_car"});
if(rand(1)<0.5 && $user{"${_}_item"} ne '' && length($user{"${num}_item"})<=$capacity){
$pick=substr($user{"${_}_item"},int(rand(length($user{"${_}_item"}))),1);
$user{"${_}_item"}=~s/$pick//;
$user{"${num}_item"}.=$pick;
($pick)=&lib'getprice($pick);
}elsif($user{"${_}_money"}>0){
$pick=int(rand($user{"${_}_money"})/10)+1;
$user{"${_}_money"}-=$pick;
$user{"${num}_money"}+=$pick;
$pick.="万円";
}else{
next;
}
$result.=$user{"${_}_name"}."から$pickを盗みました。<br>";
$user{"${_}_alert"}.=$user{"${num}_name"}."に$pickを盗まれました。<br>";
&success(1,$_,"は<font color=\"brown\">$pick</font>を盗まれました。");
}
}
アイテムの数を数える処理と、アイテムをランダムに1つ抜き出して$pickに代入する処理があります。したがって、
}elsif(&lib'matchitem($item, 26)){
foreach(@target){
if(&probability($_)==1 && $user{"${_}_status"}!~/b/){
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($user{"${num}_car"});
local(@my_item);
@my_item = split(/\+\+/,$user{"${num}_item"});
if(rand(1)<0.5 && $user{"${_}_item"} ne '' && @my_item<=$capacity){
local(@target_item);
@target_item = split(/\+\+/,$user{"${_}_item"});
$pick = $target_item[int(rand(@target_item))];
$pick =~ s/\+//g;
$pick = "+" . $pick . "+";
$user{"${_}_item"}=~s/\Q$pick\E//;
$user{"${num}_item"}.=$pick;
($pick)=&lib'getprice($pick);
}elsif($user{"${_}_money"}>0){
$pick=int(rand($user{"${_}_money"})/10)+1;
$user{"${_}_money"}-=$pick;
$user{"${num}_money"}+=$pick;
$pick.="万円";
}else{
next;
}
$result.=$user{"${_}_name"}."から$pickを盗みました。<br>";
$user{"${_}_alert"}.=$user{"${num}_name"}."に$pickを盗まれました。<br>";
&success(1,$_,"は<font color=\"brown\">$pick</font>を盗まれました。");
}
}
のように直します。
また、サイコロ・1〜6が出るサイコロの処理も修正します。
$user{"${num}_work"}.="[$item]";
$nextdice=ord($item)-64;
$result.="次は$nextdiceが出ます。<br>";
もとは[ 〜 ]の中にA〜Fを入れる処理だったのですが、今回は、この書式を改め、1〜6の数字が入るようにしましょう。つまり、
$nextdice=$item;
$nextdice =~ s/\+//g;
$nextdice = int($nextdice) - 35;
$user{"${num}_work"}.="[$nextdice]";
$result.="次は$nextdiceが出ます。<br>";
このようにします。
伴って、dice.cgiも変更します。これは、サイコロを振ったときの処理です。
if($user{"${num}_work"}=~/\[([ABCDEF])\]/){
$dice=ord($1)-64;
$user{"${num}_work"}=~s/\[([ABCDEF])\]//g;
の部分は、
if($user{"${num}_work"}=~/\[([0-9]+)\]/){
$dice=int($1);
$user{"${num}_work"}=~s/\[([0-9]+)\]//g;
となります。
さらに、item.cgiではまだ修正箇所があります。
>if(rand(1)<$p && $user{"${_}_move"}<=0 && $user{"${_}_status"}!~/b/ && $user{"${_}_car"}!=9){
$user{"${_}_car"}=9;
$user{"${_}_work"}=~s/\([1-8]\)//g;
$result.=$user{"${_}_name"}."の車を破壊しました。<br>";
$user{"${_}_alert"}.=$user{"${num}_name"}."に車を破壊されました。<br>";
&success(1,$_,"は車を壊されて<font color=\"red\">チャリンコ</font>になりました。");
}
これは、爆弾と爆弾DXの処理で、車を壊して変更する処理があるので、修正します。
if(rand(1)<$p && $user{"${_}_move"}<=0 && $user{"${_}_status"}!~/b/ && $user{"${_}_car"}!="+9+"){
$user{"${_}_car"}="+9+";
$user{"${_}_work"}=~s/\(\+[0-9]+\+\)//g;
$result.=$user{"${_}_name"}."の車を破壊しました。<br>";
$user{"${_}_alert"}.=$user{"${num}_name"}."に車を破壊されました。<br>";
&success(1,$_,"は車を壊されて<font color=\"red\">チャリンコ</font>になりました。");
}
さらにさらに、自爆スイッチでチャリンコになる処理も同じように修正が必要です。
$user{"${num}_car"}=9;
$user{"${num}_work"}=~s/\([1-8]\)//g;
$result.=$user{"${num}_name"}."は爆発で車を失いチャリンコになりました。<br>";
&success(0,$num,"は爆発で車を失い<font color=\"red\">チャリンコ</font>になりました。");
を、
$user{"${num}_car"}="+9+";
$user{"${num}_work"}=~s/\(\+[0-9]+\+\)//g;
$result.=$user{"${num}_name"}."は爆発で車を失いチャリンコになりました。<br>";
&success(0,$num,"は爆発で車を失い<font color=\"red\">チャリンコ</font>になりました。");
とします。
そして、千里眼も修正します。相手の持っているアイテムを一覧表示するアイテムです。
$t=$target[0];
@items=split(//,$user{"${t}_item"});
$result.=$user{"${t}_name"}."の持っているアイテムは";
if($user{"${t}_item"} ne ''){
foreach(@items){
($iname)=&lib'getprice($_);
$result.=",".$iname;
}
}else{
$result.="何もありません。";
}
$result.="<br>";
今までと同じように、
$t=$target[0];
@items = split(/\+\+/,$user{"${t}_item"});
$result.=$user{"${t}_name"}."の持っているアイテムは";
if($user{"${t}_item"} ne ''){
foreach(@items){
$_ =~ s/\+//g;
$_ = "+" . $_ . "+";
($iname)=&lib'getprice($_);
$result.=",".$iname;
}
}else{
$result.="何もありません。";
}
$result.="<br>";
のようにします。
交換権の処理を変更します。
}elsif($item =~ /\+45\+/){
$t=$target[0];
if(&probability($t)==1 && $user{"${t}_status"}!~/b/ && $user{"${num}_car"}!=$user{"${t}_car"}){
($user{"${num}_car"},$user{"${t}_car"})=($user{"${t}_car"},$user{"${num}_car"});
$user{"${num}_work"}=~s/\([1-8]\)//g;
$user{"${t}_work"}=~s/\([1-8]\)//g;
$result.=$user{"${t}_name"}."と車を交換しました。<br>";
$user{"${t}_alert"}.=$user{"${num}_name"}."に車を交換させられました。<br>";
&success(1,$t,"と<font color=\"red\">車を交換</font>しました。");
}
workを変更する処理があります。
}elsif($item =~ /\+45\+/){
$t=$target[0];
if(&probability($t)==1 && $user{"${t}_status"}!~/b/ && $user{"${num}_car"}!=$user{"${t}_car"}){
($user{"${num}_car"},$user{"${t}_car"})=($user{"${t}_car"},$user{"${num}_car"});
$user{"${num}_work"}=~s/\(\+[0-9]+\+\)//g;
$user{"${t}_work"}=~s/\(\+[0-9]+\+\)//g;
$result.=$user{"${t}_name"}."と車を交換しました。<br>";
$user{"${t}_alert"}.=$user{"${num}_name"}."に車を交換させられました。<br>";
&success(1,$t,"と<font color=\"red\">車を交換</font>しました。");
}
のようになります。
main.cgiは、移動とそれに伴う処理を担当する、メイン処理の部分です。item.cgiでは似たような作業が延々と続きましたが、こっちはさまざまな作業があります。
まず、
if($user{"${_}_car"}!=9){
($bcname)=&lib'getprice(9);
$user{"${_}_work"}=~s/\([1-8]\)//g;
$user{"${_}_work"}.="(".$user{"${_}_car"}.")";
$user{"${_}_car"}=9;
$user{"${_}_status"}=~s/p//g;
$user{"${_}_alert"}.="一番遅かったので車が$bcnameになりました。<br>";
&lib'chat("一番遅かった<${_}>は車が$bcnameになりました。");
}
の部分です。ここでworkが出てきていたりするので、次のように直します。
if($user{"${_}_car"}!="+9+"){
($bcname)=&lib'getprice("+9+");
$user{"${_}_work"}=~s/\(\+[0-9]+\+\)//g;
$user{"${_}_work"}.="(".$user{"${_}_car"}.")";
$user{"${_}_car"}="+9+";
$user{"${_}_status"}=~s/p//g;
$user{"${_}_alert"}.="一番遅かったので車が$bcnameになりました。<br>";
&lib'chat("一番遅かった<${_}>は車が$bcnameになりました。");
}
同様に、その少し後ろにある
for($j=1; $j<=$user{'lastnum'}; $j++){
if($user{"${j}_password"} ne '' && $rnd!~/\+$j\+/ && $user{"${j}_car"}==9){
if($user{"${j}_work"}=~/\(([1-8])\)/){
$user{"${j}_car"}=$1;
$user{"${j}_status"}=~s/p//g;
$user{"${j}_work"}=~s/\([1-8]\)//g;
($carname)=&lib'getprice($user{"${j}_car"});
$user{"${j}_alert"}.="$carnameを取り戻しました。<br>";
}
}
}
も、
for($j=1; $j<=$user{'lastnum'}; $j++){
if($user{"${j}_password"} ne '' && $rnd!~/\+$j\+/ && $user{"${j}_car"}==9){
if($user{"${j}_work"}=~/\((\+[0-9]+\+)\)/){
$user{"${j}_car"}=$1;
$user{"${j}_status"}=~s/p//g;
$user{"${j}_work"}=~s/\(\+[0-9]\+\)//g;
($carname)=&lib'getprice($user{"${j}_car"});
$user{"${j}_alert"}.="$carnameを取り戻しました。<br>";
}
}
}
となります。
その少し前に、
$user{"${num}_work"}.="t";
$user{"${num}_work"}.="e" if $user{"${num}_car"}==9;
とあるので、これも
$user{"${num}_work"}.="t";
$user{"${num}_work"}.="e" if $user{"${num}_car"}=="+9+";
とします。
次に、さらに後ろの道の駅の処理を変更します。アイテムを拾う処理があるからですね。
}else{
my($chrs) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!";
$value = substr($chrs,int(rand(length($chrs))),1);
($itemname)=&lib'getprice($value);
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($user{"${num}_car"});
if(length($user{"${num}_item"})<$capacity){
$user{"${num}_item"}.=$value;
$user{"${num}_alert"}.=$itemname."を拾いました。<br>";
}else{
$user{"${num}_alert"}.=$itemname."を拾いましたが持ち切れないので捨てました。<br>";
}
}
これは第三回の改造をした後のソースで、第三回の改造をしていない人は、最初の何行かが違いますが、問題ありません。今回番号にしたことで、「10番から61番」のような方法で拾うアイテムを選ぶのは容易です。そこで、このようにします。
}else{
$value = "+" . int(rand(62-10)+10) . "+";
($itemname)=&lib'getprice($value);
($tmp,$tmp,$tmp,$capacity)=&lib'getprice($user{"${num}_car"});
local(@my_item);
@my_item = split(/\+\+/,$user{"${num}_item"});
if(@my_item<$capacity){
$user{"${num}_item"}.=$value;
$user{"${num}_alert"}.=$itemname."を拾いました。<br>";
}else{
$user{"${num}_alert"}.=$itemname."を拾いましたが持ち切れないので捨てました。<br>";
}
}
この62というのは、アイテムの総数です。アイテムの最後の「Z」が61番目だから、こうなりますね。ただ、0番目は使われないデータで、1から9番目は車のデータなので、拾うアイテムは10番目以降だから、このようにしています。新しいアイテムを追加した場合、ここをそれにあわせて変更しないとそのアイテムが拾えません。
まだあります。その下の、飲酒時にアイテムを捨てる処理です。
if($user{"${num}_item"} ne '' && rand(1)<0.4){
$cut=substr($user{"${num}_item"},int(rand(length($user{"${num}_item"}))),1);
$user{"${num}_item"}=~s/$cut//;
($itemname)=&lib'getprice($cut);
$user{"${num}_alert"}.="酔った勢いで".$itemname."を捨てました。<br>";
アイテムを1つ選んで捨てるという処理で、前と似たような修正ですね。
if($user{"${num}_item"} ne '' && rand(1)<0.4){
local(@myitem);
@myitem = split(/\+\+/,$user{"${num}_item"});
$cut = $myitem[int(rand(@myitem))];
$cut =~ s/\+//g;
$cut = "+" . $cut . "+";
$user{"${num}_item"}=~s/\Q$cut\E//;
($itemname)=&lib'getprice($cut);
$user{"${num}_alert"}.="酔った勢いで".$itemname."を捨てました。<br>";
こうなります。
最後の難関が、main.jsです。ログイン後の画面などを担当しています。
まず、プレイヤー1人1人の車を表示する部分です。
if(user_event[2] == ""){
layer.push("car" + user[i]["car"] + user[i]["color"] + ".gif");
}else{
layer.push("car" + user_event[2] + ".gif");
}
user[i]["car"]にも「+番号+」の書式で入っているので、こう直します。
if(user_event[2] == ""){
var mycar = user[i]["car"].replace(/\+/g,"");
layer.push("car" + mycar + user[i]["color"] + ".gif");
}else{
layer.push("car" + user_event[2] + ".gif");
}
さて、次に、配列itemnumを参照している部分を修正します。今まで車を表す変数には数字が入っていたから、直接その変数を添字にすることができました。しかし、今回その変数に「+番号+」のような書式が入っているので、直接添字にできません。そこで、添字にできるように変換する必要がありますが、あちこちでこれをするとプログラムが見にくくなります。そこで、次のようにします。
itemdata.get = function(str){
var num = str.replace(/\+/g,"");
return this[num];
};
これを、
var subwin=null;
の下あたりに追加しましょう。これで、「+番号+」の形変数から、アイテムデータを「itemdata.get(変数)」のように取得できます。
これを利用して、該当部分を直していきます。
userinfo="\\n車種:" + itemdata[user[i]["car"]][0] + "\\n持ち金:" + user[i]["money"] + "万円\\n状態:";
↓
userinfo="\\n車種:" + itemdata.get(user[i]["car"])[0] + "\\n持ち金:" + user[i]["money"] + "万円\\n状態:";
if(getroute(p) || (user[num]["status"] + itemdata[user[num]["car"]][4]).match(/t/) != null){
↓
if(getroute(p) || (user[num]["status"] + itemdata.get(user[num]["car"])[4]).match(/t/) != null){
output=output + "<tr><td bgcolor=\"#FFCCCC\">名前</td><td bgcolor=\"#FFCCCC\">" + user[num]["name"] + "</td></tr><tr><td bgcolor=\"#CCCCFF\">車種</td><td bgcolor=\"#CCCCFF\">" + itemdata[user[num]["car"]][0] + "</td></tr><tr><td bgcolor=\"#FFCCCC\">持ち金</td><td bgcolor=\"#FFCCCC\">" + user[num]["money"] + "万円</td></tr><tr><td bgcolor=\"#CCCCFF\">状態</td><td bgcolor=\"#CCCCFF\">" + statusimg + "</td></tr><tr><td bgcolor=\"#FFCCCC\">現在地</td><td bgcolor=\"#FFCCCC\">" + prfname[graph[user[num]["position"]][3]] + " " + p + "</td></tr><tr><td bgcolor=\"#CCCCFF\">目的地</td><td bgcolor=\"#CCCCFF\">" + prfname[graph[user_goal][3]] + " " + graph[user_goal][0] + "</td></tr><form name=\"Info\" action=\"item.cgi\" method=\"POST\" target=\"sub\"><tr><td bgcolor=\"#FFCCCC\">領地</td><td bgcolor=\"#FFCCCC\"><select name=\"prf\">"+ own + "</select></td></tr><tr><td bgcolor=\"#CCCCFF\">建物</td><td bgcolor=\"#CCCCFF\"><select>" + building + "</select></td></tr>";
↓
output=output + "<tr><td bgcolor=\"#FFCCCC\">名前</td><td bgcolor=\"#FFCCCC\">" + user[num]["name"] + "</td></tr><tr><td bgcolor=\"#CCCCFF\">車種</td><td bgcolor=\"#CCCCFF\">" + itemdata.get(user[num]["car"])[0] + "</td></tr><tr><td bgcolor=\"#FFCCCC\">持ち金</td><td bgcolor=\"#FFCCCC\">" + user[num]["money"] + "万円</td></tr><tr><td bgcolor=\"#CCCCFF\">状態</td><td bgcolor=\"#CCCCFF\">" + statusimg + "</td></tr><tr><td bgcolor=\"#FFCCCC\">現在地</td><td bgcolor=\"#FFCCCC\">" + prfname[graph[user[num]["position"]][3]] + " " + p + "</td></tr><tr><td bgcolor=\"#CCCCFF\">目的地</td><td bgcolor=\"#CCCCFF\">" + prfname[graph[user_goal][3]] + " " + graph[user_goal][0] + "</td></tr><form name=\"Info\" action=\"item.cgi\" method=\"POST\" target=\"sub\"><tr><td bgcolor=\"#FFCCCC\">領地</td><td bgcolor=\"#FFCCCC\"><select name=\"prf\">"+ own + "</select></td></tr><tr><td bgcolor=\"#CCCCFF\">建物</td><td bgcolor=\"#CCCCFF\"><select>" + building + "</select></td></tr>";
if((user[i]["status"] + itemdata[user[i]["car"]][4]).match(/[gy]/) != null){
return(false);
}
↓
if((user[i]["status"] + itemdata.get(user[i]["car"])[4]).match(/[gy]/) != null){
return(false);
}
また、アイテムを表示する部分にも修正が必要です。
itemlist="";
for(i=0; i<user[num]["item"].length; i++){
itemnum=user[num]["item"].charCodeAt(i);
if(itemnum>=97){
itemnum-=87;
}else if(itemnum>=65){
itemnum-=29;
}else{
itemnum+=29;
}
itemlist=itemlist + "<option value=\"" + user[num]["item"].charAt(i) + "\">" + itemdata[itemnum][0];
}
output=output + "</select></td></tr><tr><td bgcolor=\"#CCCCFF\">アイテム</td><td bgcolor=\"#CCCCFF\"><select name=\"item\">" + itemlist + "</select><input type=\"hidden\" name=\"user\" value=\"" + num + "\"><input type=\"hidden\" name=\"code\" value=\"" + code + "\"><input type=\"hidden\" name=\"target\" value=\"\">";
これも、アイテムが1つ1文字であることを前提にした処理なので、配列に分けて処理します。
itemlist="";
var items = user[num]["item"].split("++");
for(i=0; i<items.length; i++){
itemnum = items[i].replace(/\+/g,"");
if(itemnum=="")continue;
itemlist=itemlist + "<option value=\"+" + itemnum + "+\">" + itemdata[itemnum][0];
}
output=output + "</select></td></tr><tr><td bgcolor=\"#CCCCFF\">アイテム</td><td bgcolor=\"#CCCCFF\"><select name=\"item\">" + itemlist + "</select><input type=\"hidden\" name=\"user\" value=\"" + num + "\"><input type=\"hidden\" name=\"code\" value=\"" + code + "\"><input type=\"hidden\" name=\"target\" value=\"\">";
文字を番号に変換する処理が無くなったので、少し短くなりました。
さて、これでプログラムの修正は終わりましたが、まだ直すところはあります。それは、マップデータの、アイテムショップとカーショップの売り物データの修正です。マップデータの見方は第一回で解説しました。
['',3,171,47,'c','58','',387,47,'']
というマップデータがあったとします。ちなみに、これは沖縄のカーショップです。マスの種類を見分けるには、左から5番目、つまり、これの場合は「'c'」のところを見るのでした。cがカーショップで、アイテムショップはiです。
売り物は、その次のデータで、今までは、1つのアイテムや車が1文字で表わしていたから、これは「5」と「8」の車、つまりトラックと戦車を売っているということです。ここの書式は、同じようにアイテムや車を列挙します。車の場合は簡単で、5の車は5番、8の車は8番だから、「+5+」と「+8+」ということになり、このマスは
['',3,171,47,'c','+5++8+','',387,47,'']
となります。
アイテムショップの場合も同じで、例えば売り物が「ab」であった場合、aは10番目、bは11番目だから、「+10++11+」と書きます。こんな感じで、全国のカーショップとアイテムショップ全てを直さないといけません。頑張って直しましょう。これを直せば、改造は完了です。
この改造を行った利点は、アイテムを何個追加しようが同じように扱うことができる点などです。