#!/usr/local/bin/perl # ↑はサーバーに合わせて変更して下さい。 # なお、perl5.002以降用です。 #---------------------------------------------------------------------- # 箱庭諸島 ver1.1 # # 字: 徳岡宏樹(tokuoka@taurus.bekkoame.ne.jp) # 絵: 小川克人 # テストプレイ他協力: 稲葉修吾、井上友博、小澤武史 # 箱庭諸島のページ: http://www.bekkoame.ne.jp/~tokuoka/hakoniwa.html #---------------------------------------------------------------------- #---------------------------------------------------------------------- # 使用条件 #---------------------------------------------------------------------- # このスクリプトについては、自己責任で使用する限り、基本的には自由に # 利用してもらってかまいません。ただし、変更を加えた場合は、変更した # ものを勝手に配るのはやめて下さい。 # # また、付属しているgifファイルは、小川克人氏が著作権をもっています。 # このゲーム用以外の用途に許可なく使用するのは禁止します。 # # バグを発見した場合は上記のページまでお知らせ下さい。 #---------------------------------------------------------------------- # 設置方法の説明 #---------------------------------------------------------------------- # # ----設置方法---- #・下のValue packageのところにある設定値を、適切な値に設定 # #・CGIが実行されるディレクトリを作り、パーミッションを777に設定します。 # #・そのディレクトリに、このファイル(hakoniwa.cgi)を置き、 # パーミッションを755に設定します。 # #・key-free というファイル名の、大きさが0のファイルを作成し、 # 同じディレクトリに起きます。パーミッションは644に設定します。 # #・サーバーにjcode.plがない場合は、同じディレクトリに置きます。 # #・CGIで実行されるわけではない、通常にアクセス出来る場所に、 # 付属するgifファイル(land*.gif、space*.gif)をすべて置きます。 # # 以上です。なお、一回目の実行において、hakoniwa.dat、hakoniwa.log # の2つのファイルが生成されます。 # # 構成 ()内の数字にパーミッションを設定 # # cgi実行可能なディレクトリ(755)/ # | # |-- hakoniwa.cgi (755) # |-- key-free (644) # |-- jcode.pl ※必要な場合のみ # |-- hankoniwa.dat (644) ※初回に生成される # |-- hakoniwa.log (644) ※初回に生成される # # 通常のウェブのディレクトリ/ # | # |-- land0.gif # |-- ... # |-- land9.gif # |-- space.gif #---------------------------------------------------------------------- # 注意 #---------------------------------------------------------------------- # key-freeファイルは、スクリプト実行中はkey-lockedという名前に # なっています。スクリプトが正常に終了しなかった場合、key-locked # になったままになってしまう事があり、その場合は何度アクセスしても # 同時アクセスエラーになってしまいます。 # # そういった場合は、key-locked を強制的に key-free にrenameして下さい。 # ftpのrenameコマンドで出来るはずです。 #---------------------------------------------------------------------- #Value package 各種設定値 #---------------------------------------------------------------------- package Value; BEGIN { #------------------------------------------------------------# # 必ず設定する部分 #------------------------------------------------------------# # jcode.plの位置 # $jcode = '/usr/libperl/jcode.pl'; # ベッコアメの場合 # $jcode = './jcode.pl'; # 同じディレクトリに置く場合 $jcode = '/usr/libperl/jcode.pl'; # このファイルを置くディレクトリ # $baseDir = 'http://サーバー/ディレクトリ'; # # 例) # http://cgi2.bekkoame.ne.jp/cgi-bin/user/u5534/hakoniwa/hakoniwa.cgi # として置く場合、 # $baseDir = 'http://cgi2.bekkoame.ne.jp/cgi-bin/user/u5534/hakoniwa'; # とする。最後にスラッシュ(/)は付けない。 $baseDir = 'http://cgi2.bekkoame.ne.jp/cgi-bin/user/u5534/hakoniwa'; # 画像ファイルを置くディレクトリ # $imageDir = 'http://サーバー/ディレクトリ'; $imageDir = 'http://www.bekkoame.ne.jp/~tokuoka/island'; # 管理者の名前 $admin = '徳岡宏樹'; # 管理者のメールアドレス $email = 'tokuoka@taurus.bekkoame.ne.jp'; # トップページ $toppage = 'http://www.bekkoame.ne.jp/~tokuoka/hakoniwa.html'; # 掲示板 $bbs = 'http://cgi2.bekkoame.ne.jp/cgi-bin/user/u5534/hakobbs/minibbs.cgi'; #------------------------------------------------------------# # 以降は好みによって変更 #------------------------------------------------------------# # BODYタグのoption $body = 'BGCOLOR="#90b090"'; # コマンド先行入力限界数 $commandMax = 40; # 「最近の出来事」保持ターン数 $logMax = 5; # 「最近の出来事」表示ターン数 $logPrint = 1; # 1ターンが何秒か $unitTime = 21600; # 6時間 # 初期資金 $startMoney = 50; # 島の最大数 $maxIsland = 150; # 期限切れ(資金繰りがこのターン数連続すると、島の放棄) $expire = 28; # お金の単位 $moneyUnit = '億円'; # 人口の単位 $popUnit = '000人'; # 災害発生率(1d1000で下の数字以下) $fire = 10; # 火災 $typhoon = 10; # 台風 $tsunami = 20; # 津波 $eruption = 10; # 噴火 $meteo = 10; # 隕石 $earthquake = 5; # 地震 $maizo = 10; # 埋蔵金 # 島の大きさ(変えない方がいいかも) $islandSize = 12; # デバッグ(1にすると、「ターンを進める」ボタンが出る) # $debug = 1; $debug = 0; # このファイル $thisFile = "$baseDir/hakoniwa.cgi"; } #---------------------------------------------------------------------- # main package メインルーチン #---------------------------------------------------------------------- package main; # jcode.plのよみこみ require "$Value::jcode"; # ロックをかける if(!&Lock::lock()) { # ロック失敗 # ヘッダ出力 &IO::out(&Temp::header($Value::body)); # ロック失敗メッセージ &IO::out(&Temp::lockFail()); # フッタ出力 &IO::out(&Temp::footer()); # 終了 exit(0); } # 乱数初期化 srand; # cookie入力 &Cookie::input(); # CGIコマンド入力 &IO::cgiInput(); # 島データ読み込み &IO::parseAll(); # ターン処理 # 何ターン過ぎているか計算 $now = time; $passTurn = int(($now - $Island::lastUpdateTime) / $Value::unitTime); # デバッグ用ターン処理 if(($Value::debug == 1) && ($Island::mainMode eq 'turn')) { $passTurn = 1; # top modeにもどす $Island::mainMode = 'top'; } # ターン処理(1ターンのみに改定) if($passTurn > 0) { # 最終更新時間を更新 $Island::lastUpdateTime += $Value::unitTime; # ログファイル名変更 my($i, $j); for($i = $Value::logMax - 2; $i >= 0; $i--) { $j = $i + 1; rename("hakoniwa.log$i", "hakoniwa.log$j"); } # ファイルバックアップ rename('hakoniwa.bak7','hakoniwa.bak8'); rename('hakoniwa.bak6','hakoniwa.bak7'); rename('hakoniwa.bak5','hakoniwa.bak6'); rename('hakoniwa.bak4','hakoniwa.bak5'); rename('hakoniwa.bak3','hakoniwa.bak4'); rename('hakoniwa.bak2','hakoniwa.bak3'); rename('hakoniwa.bak1','hakoniwa.bak2'); rename('hakoniwa.dat','hakoniwa.bak1'); # 1ターン進める &Process::turn(); # ファイルに書き出す &IO::writeIslands(); } # 人口順にソート &Util::sort(); # テンプレート初期化 &Temp::initialize(); # cookie出力 &Cookie::output(); # ヘッダ出力 &IO::out(&Temp::header($Value::body)); # モードにより分岐 if($Island::mainMode eq 'top') { # ロック解除 &Lock::unlock(); # トップページ &TopPage::main(); } elsif($Island::mainMode eq 'new') { # 島の新規作成 &NewIsland::main(); # ロック解除 &Lock::unlock(); } elsif($Island::mainMode eq 'print') { # ロック解除 &Lock::unlock(); # 島の表示 &PrintIsland::main(); } elsif($Island::mainMode eq 'owner') { # ロック解除 &Lock::unlock(); # 開発計画 &Owner::main(); } elsif($Island::mainMode eq 'command') { # 開発計画 &ComSend::main(); } else { # ロック解除 &Lock::unlock(); } # フッタ出力 &IO::out(&Temp::footer()); exit(0); #---------------------------------------------------------------------- # Land package 地形データ #---------------------------------------------------------------------- package Land; BEGIN { # 地形番号の設定 $sea = 0; # 海 $wasteland = 1; # 荒地 $plains = 2; # 平地 $town1 = 3; # 村 $town2 = 4; # 町 $town3 = 5; # 都市 $forest = 6; # 森 $farm = 7; # 農場 $factory = 8; # 工場 $base = 9; # ミサイル基地 $dbase = 10; # 防衛施設 # 地形の名前 $name[$sea] = '海'; $name[$wasteland] = '荒地'; $name[$plains] = '平地'; $name[$town1] = '村'; $name[$town2] = '町'; $name[$town3] = '都市'; $name[$forest] = '森'; $name[$farm] = '農場'; $name[$factory] = '工場'; $name[$base] = 'ミサイル基地'; $name[$dbase] = '防衛施設'; # 人口 $pop[$town1] = 1; $pop[$town2] = 3; $pop[$town3] = 5; # 職場 $work[$farm] = 10; $work[$factory] = 30; # 地形の文字(簡略モード用) $word[$sea] = ''; $word[$wasteland] = ''; $word[$plains] = ''; $word[$town1] = ''; $word[$town2] = ''; $word[$town3] = ''; $word[$forest] = ''; $word[$farm] = ''; $word[$factory] = ''; $word[$base] = ''; $word[$dbase] = ''; } # 陸地である sub isLand($) { my($land) = @_; if(($land != $sea) && ($land != -1)) { return 1; } else { return 0; } } # 成長候補である sub growLand($) { my($land) = @_; if(($land == $plains) || ($land == $town1) || ($land == $town2)) { return 1; } else { return 0; } } # 成長要素である sub growFactor($) { my($land) = @_; if(($land == $town1) || ($land == $town2) || ($land == $town3) || ($land == $farm)) { return 1; } else { return 0; } } # 平地系である sub isPlain($) { my($land) = @_; if(($land == $plains) || ($land == $town1) || ($land == $town2) || ($land == $town3)) { return 1; } else { return 0; } } # 大きな建物 sub isBuilding($) { my($land) = @_; if(($land == $factory) || ($land == $town3)) { return 1; } else { return 0; } } # 森 sub isForest($) { my($land) = @_; if($land == $forest) { return 1; } else { return 0; } } # 津波にやられるやつ sub isTsunami($) { my($land) = @_; if(($land == $factory) || ($land == $town1) || ($land == $town2) || ($land == $town3) || ($land == $farm) || ($land == $base) || ($land == $dbase)) { return 1; } else { return 0; } } #---------------------------------------------------------------------- # Command package 計画データ #---------------------------------------------------------------------- package Command; BEGIN{ # 計画の総数 $total = 16; # 計画番号の設定 $doNothing = 0; # 資金繰り $prepare = 1; # 整地 $prepare2 = 11; # 地ならし $plant = 2; # 植林 $farm = 3; # 農地整備 $factory = 4; # 工場建設 $base = 5; # ミサイル基地建設 $dbase = 15; # 防衛施設建設 $reclaim = 6; # 埋め立て $donate = 14; # 寄付 $aid = 13; # 資金援助 $missileNM = 7; # ミサイル発射 $missilePP = 8; # PPミサイル発射 $missileST = 12; # STミサイル発射 $missileLD = 9; # 陸地破壊弾発射 $giveup = 10; # 島の放棄 # 順番 @list = ($doNothing, $prepare, $prepare2, $plant, $farm, $factory, $base, $dbase, $reclaim, $donate, $aid, $missileNM, $missilePP, $missileST, $missileLD, $giveup); # 計画の名前 $name[$doNothing] = '資金繰り'; $name[$prepare] = '整地'; $name[$prepare2] = '地ならし'; $name[$plant] = '植林'; $name[$farm] = '農地整備'; $name[$factory] = '工場建設'; $name[$base] = 'ミサイル基地建設'; $name[$dbase] = '防衛施設建設'; $name[$reclaim] = '埋め立て'; $name[$donate] = '寄付'; $name[$aid] = '資金援助'; $name[$missileNM] = 'ミサイル発射'; $name[$missilePP] = 'PPミサイル発射'; $name[$missileST] = 'STミサイル発射'; $name[$missileLD] = '陸地破壊弾発射'; $name[$giveup] = '島の放棄'; # 必要な資金 $cost[$doNothing] = 0; $cost[$prepare] = 5; $cost[$prepare2] = 100; $cost[$plant] = 5; $cost[$farm] = 10; $cost[$factory] = 100; $cost[$base] = 300; $cost[$dbase] = 1000; $cost[$reclaim] = 100; $cost[$donate] = 100; $cost[$aid] = 500; $cost[$missileNM] = 20; $cost[$missilePP] = 50; $cost[$missileST] = 50; $cost[$missileLD] = 150; $cost[$giveup] = 0; # 現在受け取ったコマンド $planNumber = 0; # 計画番号 $kind = 0; # コマンドの種類 $target = ''; # 標的 $x = 0; $y = 0; # 座標 $mode = 0; # モード(挿入、上書き、削除) } #---------------------------------------------------------------------- # Island package グローバル変数 #---------------------------------------------------------------------- package Island; BEGIN { # ターン数 $turn = 0; # 島の数 $totalNumber = 0; # 最終更新時間 $lastUpdateTime = 0; # CGI入力関係 $name = ''; $password = ''; $password2 = ''; $mainMode = ''; $message = ''; $printMode = ''; # クッキー $defaultName = ''; $defaultPassword = ''; $defaultTarget = ''; # 島配列(島型の配列) @island = (); # 島型 # 以下のメンバを持つハッシュ # name 名前 :文字列 # money 資金 :整数値 # land 地形 :整数の2次元配列 # command 計画 :計画型の配列 # (以降はlandより算出) # pop 人口 :整数 # work 職場 :整数 # arm 基地の数 :整数 # prod 生産力 :整数 # farm 農場の数 :整数 # factory 工場の数 :整数 # prepare 整地実行数 :整数 # prepare2 地ならし実行数 :整数 # launch ミサイル発射数 :整数 # dead 死滅 :0 or 1 # 計画型 # 以下のメンバを持つハッシュ # kind コマンド:整数値 # target 標的の島:文字列 # x,y 座標:整数 } #---------------------------------------------------------------------- #以降、各要求における動作 #---------------------------------------------------------------------- #---------------------------------------------------------------------- #TopPage package ゲームのトップページ #---------------------------------------------------------------------- package TopPage; sub main() { # トップページの表示 &IO::out(&Temp::topPage()); # ログの表示 &Log::printAll(); } #---------------------------------------------------------------------- # NewIsland package 島の新規作成 #---------------------------------------------------------------------- package NewIsland; sub main() { my($number, $land, @command, $i, $land); # 名前があるかチェック if($Island::name eq '') { &IO::out(&Temp::newIslandNoName()); return; } # 島名の設定 $Island::name .= '島'; # 名前の重複チェック if(&Util::nameToNumber($Island::name) != -1) { # すでに発見ずみ &IO::out(&Temp::newIslandAlready()); return; } # 名前の中に,がないかチェック if($Island::name =~ /[,\?\(\)\<\>]/) { # 使えない名前 &IO::out(&Temp::newIslandBadName()); return; } # passwordの存在判定 if($Island::password eq '') { # password無し &IO::out(&Temp::noPassword()); return; } # 確認用パスワード if($Island::password ne $Island::password2) { # password間違い &IO::out(&Temp::wrongPassword()); return; } # 新しい島の番号を決める $number = $Island::totalNumber; # 島の番号を一つ増やす $Island::totalNumber++; # 初期コマンドを生成 for($i = 0; $i < $Value::commandMax; $i++) { $command[$i] = { 'kind' => 0, 'target' => '', 'x' => 0, 'y' => 0 }; } # 島型を生成 $land = &createLand(); $Island::island[$number] = { 'name' => $Island::name, 'password' => &Util::encode($Island::password), 'money' => $Value::startMoney, 'land' => $land, 'command' => \@command, 'message' => "(未登録)" }; # 人口その他の計算 &Calc::estimate($Island::island[$number]); # データの書き出し &IO::writeIslands(); # logの書き出し &IO::outLog(&Temp::logNewIsland($Island::name)); #「発見した」メッセージ &IO::out(&Temp::newIslandSuccess($Island::island[$number])); } # 新規作成 sub createLand(){ my(@land, $i, $count); # 島の基礎を作る @land = &createLandBase(); # 平地を増殖 for($i = 0; $i < 50; $i++) { &Hex::randomVisit(\&makePlains, @land); } # 森を増殖 for($i = 0; $i < 20; $i++) { &Hex::randomVisit(\&makeForest, @land); } # 村を作る $count = 0; while($count < 2) { $count += &Hex::randomVisit(\&makeTown, @land); } # 基地を作る $count = 0; while($count < 1) { $count += &Hex::randomVisit(\&makeBase, @land); } return \@land; } #初期の陸地を決定 sub createLandBase() { my(@land, $x, $y, $sx, $sy, $ex, $ey, $v); #陸地を作る座標の範囲を設定 $sx = $Value::islandSize / 4; $sy = $Value::islandSize / 4; $ex = $Value::islandSize - $sx; $ey = $Value::islandSize - $sy; for($x = 0; $x < $Value::islandSize; $x++) { for($y = 0; $y < $Value::islandSize; $y++) { if(($x >= $sx) && ($x < $ex) && ($y >= $sy) && ($y < $ey)) { #範囲内の場合、陸地(荒地)に設定 $land[$x][$y] = $Land::wasteland; } else { #範囲外の場合、海に設定 $land[$x][$y] = $Land::sea; } } } return @land; } #平地を増やす sub makePlains($$$$@) { my($land, $x, $y, $unit, @land) = @_; #周囲すべて海なら増やさない if(&Hex::countLand(\&Land::isLand, $x, $y, @land) != 0) { return $Land::plains; } else { return $land; } } #森を増やす sub makeForest($$$$@) { my($land, $x, $y, $unit, @land) = @_; #陸地だった場合に森にする if(&Land::isLand($land)) { return $Land::forest; } else { return $land; } } #村を増やす sub makeTown($$$$@) { my($land, $x, $y, $unit, @land) = @_; #周囲すべて陸地で、まだ村でない場合に村にする if((&Hex::countLand(\&Land::isLand, $x, $y, @land) == 7) && ($land != $Land::town1)) { $$unit = 1; #村にした場合はカウント return $Land::town1; } else { return $land; } } #基地を増やす sub makeBase($$$$@) { my($land, $x, $y, $unit, @land) = @_; #周囲すべて陸地で、村でない場合に村にする if((&Hex::countLand(\&Land::isLand, $x, $y, @land) == 7) && ($land != $Land::town1)) { $$unit = 1; #基地にした場合はカウント return $Land::base; } else { return $land; } } #---------------------------------------------------------------------- # PrintIsland package 島の表示 #---------------------------------------------------------------------- package PrintIsland; sub main() { my($number); # 島番号の取得 $number = &Util::nameToNumber($Island::name); if($number == -1) { # 何かの間違い &IO::out($Temp::back); return; } # 「ようこそ」メッセージ &IO::out(&Temp::printIsland($Island::island[$number])); # 最近の出来事表示 &Log::printOther($Island::name); } #---------------------------------------------------------------------- # Owner package 開発計画編集画面 #---------------------------------------------------------------------- package Owner; sub main() { my($number, $island); # 島番号の取得 $number = &Util::nameToNumber($Island::name); if($number == -1) { # 何かの間違い &IO::out($Temp::back); return; } # 島の取得 $island = $Island::island[$number]; # password if(&Util::encode($Island::password) ne $island->{'password'}) { &IO::out(&Temp::wrongPassword()); return; } #コマンド編集画面の表示 &IO::out(&Temp::ownerMode($island)); # 最近の出来事表示 &Log::printOwner($Island::name); } #---------------------------------------------------------------------- # ComSend package 開発計画送信 #---------------------------------------------------------------------- package ComSend; sub main() { my($number, $island); # 島番号の取得 $number = &Util::nameToNumber($Island::name); if($number == -1) { # 何かの間違い &IO::out($Temp::back); return; } # 島の取得 $island = $Island::island[$number]; # password if(&Util::encode($Island::password) ne $island->{'password'}) { &IO::out(&Temp::wrongPassword()); return; } # modeで分岐 if($Command::mode eq 'delete') { &Util::slideFront($island->{'command'},$Command::planNumber); &IO::out(&Temp::comDelete()); } else { if($Command::mode eq 'insert') { &Util::slideBack($island->{'command'},$Command::planNumber); } # コマンドをさしかえ $island->{'command'}->[$Command::planNumber] = { 'kind' => $Command::kind, 'target' => $Command::target, 'x' => $Command::x, 'y' => $Command::y }; &IO::out(&Temp::comAdd()); } # データの書き出し &IO::writeIslands(); # ロック解除 &Lock::unlock(); # 開発計画画面へ &Owner::main(); } #---------------------------------------------------------------------- # Process package ターン進行処理 #---------------------------------------------------------------------- package Process; # 1ターン進める sub turn() { my($i, $r, $total, $island, @order); $total = $Island::totalNumber; # turnの数をふやす $Island::turn++; # 収入フェイズ for($i = 0; $i < $total; $i++) { $island = $Island::island[$i]; $island->{'money'} += $island->{'prod'}; } # コマンドフェイズ # コマンド処理順番を決める for($i = 0; $i < $total; $i++ ){ $order[$i] = -1; } for($i = 0; $i < $total; $i++ ){ $r = int(rand(1) * $total); if($order[$r] == -1) { $order[$r] = $i; } else { $i--; } } # orderに従ってコマンド処理 for($i = 0; $i < $total; $i++ ){ $island = $Island::island[$order[$i]]; if($island->{'dead'} != 1){ # コマンド1つ実行出来るまで回す while(&doCommand($island) == 0){} } } # 災害フェイズ for($i = 0; $i < $total; $i++ ){ $island = $Island::island[$order[$i]]; if($island->{'dead'} != 1){ $currentName = $island->{'name'}; &doDisaster($island); } } # 町の成長フェイズ for($i = 0; $i < $total; $i++ ){ $island = $Island::island[$order[$i]]; if($island->{'dead'} != 1){ $currentName = $island->{'name'}; &doGrow($island); } } # 死滅判定 for($i = 0; $i < $total; $i++ ){ $island = $Island::island[$i]; if($island->{'dead'} != 1){ # 人口計算 &Calc::estimate($island); if($island->{'pop'} == 0) { # ぜんめつ $island->{'dead'} = 1; &IO::outLog(&Temp::procDead($island->{'name'})); } } } # 遅延ログを書き出し &IO::lateLogWrite(); } # コマンド一つ実行 sub doCommand($) { my($island) = @_; my($command, $kind, $target, $x, $y, $cost, $comName, $land, $pt, $landKind, $landName, $tn); # コマンド取り出し $command = $island->{'command'}; $kind = $command->[0]->{'kind'}; $target = $command->[0]->{'target'}; $x = $command->[0]->{'x'}; $y = $command->[0]->{'y'}; # 導出値 $name = $island->{'name'}; $land = $island->{'land'}; $landKind = $land->[$x][$y]; $landName = $Land::name[$landKind]; $cost = $Command::cost[$kind]; $comName = $Command::name[$kind]; $pt = &Temp::point($x, $y); # 1つ詰めておく &Util::slideFront($command, 0); # 資金チェック if($island->{'money'} < $cost) { # 足りない場合 &IO::outLog(&Temp::procNoMoney($name, $comName)); return 0; } # コマンドで分岐 if($kind == $Command::doNothing) { # 資金繰り $island->{'money'} += 10; $island->{'absent'} += 1; if($island->{'absent'} >= $Value::expire) { # 期限切れ # 次のコマンドを放棄に $command->[0]->{'kind'} = $Command::giveup; } return 1; } else { $island->{'absent'} = 0; if(($kind == $Command::prepare) || ($kind == $Command::prepare2)){ # 整地 if($landKind == $Land::sea) { # 海だと失敗 &IO::outLog(&Temp::procNotAdeqLand($name, $pt, $comName, $landName)); return 0; } # 成功 # コマンド名を'整地'に統一 $comName = $Command::name[$Command::prepare]; $land->[$x][$y] = $Land::plains; $island->{'money'} -= $cost; &IO::outLog(&Temp::procSuccess($name, $pt, $comName)); if($kind == $Command::prepare2) { $island->{'prepare2'}++; return 0; } $island->{'prepare'}++; return 1; } elsif($kind == $Command::reclaim) { # 埋め立て if($landKind != $Land::sea) { # 海じゃないと失敗 &IO::outLog(&Temp::procNotAdeqLand($name, $pt, $comName, $landName)); return 0; } # 成功 $land->[$x][$y] = $Land::wasteland; $island->{'money'} -= $cost; &IO::outLog(&Temp::procSuccess($name, $pt, $comName)); return 1; } elsif(($kind == $Command::plant) || ($kind == $Command::farm) || ($kind == $Command::factory) || ($kind == $Command::base) || ($kind == $Command::dbase)) { # 建設系 if(!&Land::isPlain($land->[$x][$y])) { # 平地系じゃないと失敗 &IO::outLog(&Temp::procNotAdeqLand($name, $pt, $comName, $landName)); return 0; } # 成功 if($kind == $Command::farm) { # 農地 $land->[$x][$y] = $Land::farm; &IO::outLog(&Temp::procSuccess($name, $pt, $comName)); } elsif($kind == $Command::factory) { # 工場 $land->[$x][$y] = $Land::factory; &IO::outLog(&Temp::procSuccess($name, $pt, $comName)); } elsif($kind == $Command::dbase) { # 防衛施設 $land->[$x][$y] = $Land::dbase; &IO::outLog(&Temp::procSuccess($name, $pt, $comName)); } elsif($kind == $Command::plant) { # 森 $land->[$x][$y] = $Land::forest; &IO::outLog(&Temp::procPBSuccess($name)); &IO::outLogSecret($name, &Temp::procSuccess($name, $pt, $comName)); } elsif($kind == $Command::base) { # 基地 $land->[$x][$y] = $Land::base; &IO::outLog(&Temp::procPBSuccess($name)); &IO::outLogSecret($name,&Temp::procSuccess($name, $pt, $comName)); } $island->{'money'} -= $cost; return 1; } elsif($kind == $Command::giveup) { # 島の放棄 &IO::outLog(&Temp::procGiveup($name)); $island->{'dead'} = 1; return 1; } elsif(($kind == $Command::donate) || ($kind == $Command::aid)) { #資金援助、寄付 # targetを取得 $tn = &Util::nameToNumber($target); if($tn == -1) { # その島がすでに無かったら失敗 &IO::outLog(&Temp::procAid2($name, $comName, $target)); } else { $island->{'money'} -= $cost; $Island::island[$tn]->{'money'} += $cost; &IO::outLog(&Temp::procAid($name, $comName, $target)); } return 0; # どちらにしてもターンは進まない } elsif($kind == $Command::missileNM) { return &launchMissile(19, 0, $island, $comName, $target, $pt, $cost, $x, $y, $pt); } elsif($kind == $Command::missilePP) { return &launchMissile(7, 0, $island, $comName, $target, $pt, $cost, $x, $y, $pt); } elsif($kind == $Command::missileST) { return &launchMissile(19, 2, $island, $comName, $target, $pt, $cost, $x, $y, $pt); } elsif($kind == $Command::missileLD) { return &launchMissile(19, 1, $island, $comName, $target, $pt, $cost, $x, $y, $pt); } } return 0; } # ミサイル発射 sub launchMissile($$$$$$$$$$) { my($err, $power, $island, $comName, $target, $pt, $cost, $x, $y, $pt) = @_; my($name, $arm, $attack, $tn, $i, $tIsland, $tLand, $tx, $ty, $tPt, $en, $tKind, $tName, $sName, $defence); $name = $island->{'name'}; $arm = $island->{'arm'}; # 基地があるか判定 if($arm == 0) { # 無かったら失敗 &IO::outLog(&Temp::procNoBase($name, $comName)); return 0; } # targetを取得 $tn = &Util::nameToNumber($target); if($tn == -1) { # その島がすでに無かったら失敗 &IO::outLog(&Temp::procNoTarget($name, $comName, $target)); return 0; } $tIsland = $Island::island[$tn]; $tLand = $tIsland->{'land'}; # 何発撃つか計算 $attack = &Util::min($arm, int(($island->{'money'} / $cost))); $island->{'launch'} += $attack; # ステルス if($power == 2) { $sName = $name; $name = '???島'; } # 発射 for($i = 0; $i < $attack; $i++) { # 誤差値を計算 $en = int(rand(1) * $err); # 着弾地点を算出 ($tx, $ty) = &Hex::around($x, $y, $en); $tPt = &Temp::point($tx, $ty); # 領域外かどうか判定 if($tx == -1) { # 領域外 if($power == 2) { # ステルス &IO::outLogLate(&Temp::missileOutArea($name, $comName, $target, $pt)); &IO::outLogSecret($sName, &Temp::missileOutArea($sName, $comName, $target, $pt)); } else { # 通常 &IO::outLog(&Temp::missileOutArea($name, $comName, $target, $pt)); } } else { # 領域内 $tKind = $tLand->[$tx][$ty]; if($tKind == $Land::sea) { # 海ポチャの場合 if($power == 2) { # ステルス &IO::outLogLate(&Temp::missileSea($name, $comName, $target, $pt, $tPt)); &IO::outLogSecret($sName, &Temp::missileSea($sName, $comName, $target, $pt, $tPt)); } else { &IO::outLog(&Temp::missileSea($name, $comName, $target, $pt, $tPt)); } } else { # 防衛施設判定 if($tKind == $Land::dbase) { $defence = 0; } else { $defence = &Hex::judgeDBase($tx, $ty, $tLand); } if($defence != 0) { # キャッチされた場合 if($power == 2) { # ステルス &IO::outLogLate(&Temp::missileDef($name, $comName, $target, $pt, $tPt)); &IO::outLogSecret($sName, &Temp::missileDef($sName, $comName, $target, $pt, $tPt)); } else { &IO::outLog(&Temp::missileDef($name, $comName, $target, $pt, $tPt)); } } else { # 陸地に落ちた場合 $tName = $Land::name[$tKind]; if(($power == 0) || ($power == 2)){ if($power == 2) { # ステルス &IO::outLogLate(&Temp::missileNormal($name, $comName, $target, $pt, $tPt, $tName)); &IO::outLogSecret($sName, &Temp::missileNormal($sName, $comName, $target, $pt, $tPt, $tName)); } else { # 通常 &IO::outLog(&Temp::missileNormal($name, $comName, $target, $pt, $tPt, $tName)); } $tLand->[$tx][$ty] = $Land::wasteland; } elsif($power == 1) { # 陸地破壊 &IO::outLog(&Temp::missileLD($name, $comName, $target, $pt, $tPt, $tName)); $tLand->[$tx][$ty] = $Land::sea; } } } } $island->{'money'} -= $cost; } return 1; } # 町の成長判定 sub doGrow($) { my($island) = @_; my($count, $x, $y, $l, $d, $tx, $ty); $count = &Hex::visit(\&grow, @{$island->{'land'}}); # $countに増えた人口が入ってるはずだが、 # 現時点では使用していない。 } # 成長 sub grow($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random); # 平地系じゃなければ何もしない if(!&Land::growLand($land)) { return $land; } # 周囲の町、畑を数える $count = &Hex::countLand(\&Land::growFactor, $x, $y, @land); # サイコロ(1-10) $random = &Util::dice(10); # 乱数に従って成長判定 if($count >= $random) { if($land == $Land::plains) { $$unit += 1; return $Land::town1; } elsif($land == $Land::town1) { $$unit += 2; return $Land::town2; } elsif($land == $Land::town2) { $$unit += 2; return $Land::town3; } } return $land; } # 災害判定 sub doDisaster($) { my($island) = @_; my($random, $price, $p, $i); # 埋蔵金 $random = &Util::dice(1000); if(($island->{'prepare'} > 0) && ($random <= $Value::maizo)) { $price = 99 + &Util::dice(401); $island->{'money'} += $price; &IO::outLog(&Temp::disMaizo($currentName, $price)); } # 火災 &Hex::visit(\&fire, @{$island->{'land'}}); # 台風 $random = &Util::dice(1000); $p = $Value::typhoon * ($island->{'factory'} + 1); if($random <= $p) { &IO::outLog(&Temp::disTyphoon1($currentName)); &Hex::visit(\&typhoon, @{$island->{'land'}}); } # 地震 $random = &Util::dice(1000); $p = $Value::earthquake * ($island->{'prepare2'} + 1); if($random <= $p) { &IO::outLog(&Temp::disEarthquake1($currentName)); &Hex::visit(\&earthquake, @{$island->{'land'}}); } # 津波 $random = &Util::dice(1000); if($random <= $Value::tsunami) { &IO::outLog(&Temp::disTsunami1($currentName)); &Hex::visit(\&tsunami, @{$island->{'land'}}); } # 火山噴火 $random = &Util::dice(1000); if($random <= $Value::eruption) { &Hex::randomVisit(\&eruption, @{$island->{'land'}}); } # 隕石 $random = &Util::dice(1000); $p = $Value::meteo * ($island->{'launch'} + 1); if($random <= $p) { do { &Hex::randomVisit(\&meteo, @{$island->{'land'}}); } while(&Util::dice(2) == 1); } } # 火災(工場、都市が荒地になる) sub fire($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random, $lName); # 工場、都市じゃなければ何もしない if(!&Land::isBuilding($land)) { return $land; } # サイコロ(1-1000) $random = &Util::dice(1000); # 乱数に従って判定 if($random > $Value::fire) { return $land; } # 周囲の森の数を数える(1-7) $count = &Hex::countLand(\&Land::isForest, $x, $y, @land); if($count > 0) { # 森に隣接してれば何もしない return $land; } # 乱数に従って火災判定 $lName = $Land::name[$land]; &IO::outLog(&Temp::disFire($currentName, $lName, $x, $y)); return $Land::wasteland; # 荒地になる } # 台風(農場が荒地になる) sub typhoon($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random, $lName); # 農場じゃなければ何もしない if($Land::farm != $land) { return $land; } # サイコロ(1-2) $random = &Util::dice(2); # 乱数に従って被害判定 if($random <= 1) { $lName = $Land::name[$land]; &IO::outLog(&Temp::disTyphoon2($currentName, $lName, $x, $y)); return $Land::plains; # 平地になる } return $land; } # 地震(建物が荒地になる) sub earthquake($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random, $lName); # 工場、都市じゃなければ何もしない if(!&Land::isBuilding($land)) { return $land; } # サイコロ(1-3) $random = &Util::dice(3); # 乱数に従って被害判定 if($random <= 1) { $lName = $Land::name[$land]; &IO::outLog(&Temp::disEarthquake2($currentName, $lName, $x, $y)); return $Land::wasteland; # 荒地になる } return $land; } # 津波(沿岸の建造物が荒地になる) sub tsunami($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random, $lName); # 津波対象地形かどうか調べる if(!&Land::isTsunami($land)) { return $land; } # 周囲の陸の数を数える(1-7) $count = &Hex::countLand(\&Land::isLand, $x, $y, @land); # 率を決定 $count = 6 - $count; # サイコロ(1-10) $random = &Util::dice(10); # 乱数に従って被害判定 if($random <= $count) { $lName = $Land::name[$land]; &IO::outLog(&Temp::disTsunami2($currentName, $lName, $x, $y)); return $Land::wasteland; # 荒地になる } return $land; } # 火山噴火(陸、海を問わず荒地になる) sub eruption($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random, $l, $lName, $i, $tx, $ty); # 発生 &IO::outLog(&Temp::disEruption0($currentName, $lName, $x, $y)); for($i = 0; $i < 7; $i++) { ($tx, $ty) = &Hex::around($x, $y, $i); if($tx != -1) { $l = $land[$tx][$ty]; $lName = $Land::name[$l]; # 海かどうかでメッセージを分ける if($l == $Land::sea) { # 海の場合 &IO::outLog(&Temp::disEruption1($currentName, $lName, $tx, $ty)); } else { # 海じゃない場合 &IO::outLog(&Temp::disEruption2($currentName, $lName, $tx, $ty)); } $land[$tx][$ty] = $Land::wasteland; } } return $Land::wasteland; # 荒地へ。 } # 隕石 落ちた所が海になる sub meteo($$$$@) { my($land, $x, $y, $unit, @land) = @_; my($count, $random, $lName); # 海かどうかでメッセージを分ける $lName = $Land::name[$land]; if($land == $Land::sea) { # 海の場合 &IO::outLog(&Temp::disMeteo1($currentName, $lName, $x, $y)); } else { # 海じゃない場合 &IO::outLog(&Temp::disMeteo2($currentName, $lName, $x, $y)); } return $Land::sea; # 海になる } #---------------------------------------------------------------------- #Hex package 座標関係 #---------------------------------------------------------------------- package Hex; BEGIN { #周囲2ヘックスの座標 #周囲2ヘックスの座標 @dx = (0,1,1,1,0,-1,0,1,2,2,2,1,0,-1,-1,-2,-1,-1,0); @dy = (0,-1,0,1,1,0,-1,-2,-1,0,1,2,2,2,1,0,-1,-2,-2); } #周囲のヘックスを求める sub around() { my($sx, $sy, $number, $x, $y); ($sx, $sy, $number) = @_; $x = $sx + $dx[$number]; $y = $sy + $dy[$number]; if((($sy % 2) == 1) && (($y % 2) == 0)) { $x -= 1; } #範囲外の場合は(-1,-1)で統一 if(($x < 0) || ($x >= $Value::islandSize) || ($y < 0) || ($y >= $Value::islandSize)) { $x = -1; $y = -1; } return ($x, $y); } #ランダムにヘックスを選ぶ(一番外側以外) sub random() { my($x, $y); $x = int(rand(1) * ($Value::islandSize - 2)) + 1; $y = int(rand(1) * ($Value::islandSize - 2)) + 1; return ($x, $y); } #全部のヘックスをなめる #引数は、適用関数、地形型(整数の2次元配列) sub visit(&@) { my($visitor,@land) = @_; my($x, $y, $count, $unit); #ループ $count = 0; for($y = 0; $y < $Value::islandSize; $y++) { for($x = 0; $x < $Value::islandSize; $x++) { $unit = 0; #カウント要素用 $land[$x][$y] = &$visitor($land[$x][$y], $x, $y, \$unit, @land); $count += $unit; #カウント要素を加算 } } return $count; } #ランダムなヘックスに適用 #(一番外は除く) sub randomVisit(&@) { my($visitor,@land) = @_; my($x, $y, $count); #座標決定 ($x, $y) = random(); $count = 0; $land[$x][$y] = &$visitor($land[$x][$y], $x, $y, \$count, @land); return $count; } #周囲のヘックス(+自分のヘックス)のうち、引数の数字のやつの探す sub countLand(&$$@) { my($cond, $sx, $sy, @land) = @_; my($count, $i, $x, $y); $count = 0; for($i = 0; $i < 7; $i++) { ($x, $y) = &around($sx, $sy, $i); if($x != -1) { if(&$cond($land[$x][$y])) { $count++; } } } return $count; } # 周囲2ヘックス(自分除く)に防衛施設があるかどうか sub judgeDBase($$$) { my($sx, $sy, $land) = @_; my($i, $x, $y); for($i = 1; $i < 19; $i++) { ($x, $y) = &around($sx, $sy, $i); if($x != -1) { if($land->[$x][$y] == $Land::dbase) { return 1; } } } return 0; } #---------------------------------------------------------------------- #Calc package 人口や生産力等の計算 #---------------------------------------------------------------------- package Calc; sub estimate($) { my($island) = @_; my($x, $y); # 初期化 $island->{'pop'} = 0; $island->{'farm'} = 0; $island->{'factory'} = 0; $island->{'work'} = 0; $island->{'arm'} = 0; # ループ for($y = 0; $y < $Value::islandSize; $y++) { for($x = 0; $x < $Value::islandSize; $x++) { $l = $island->{'land'}->[$x][$y]; if($l == $Land::town1) { # 村 $island->{'pop'} ++; } elsif($l == $Land::town2) { # 町 $island->{'pop'} += 3; } elsif($l == $Land::town3) { # 都市 $island->{'pop'} += 5; } elsif($l == $Land::farm) { # 農場 $island->{'farm'} ++; $island->{'work'} +=10; } elsif($l == $Land::factory) { # 工場 $island->{'factory'} ++; $island->{'work'} +=30; } elsif($l == $Land::base) { # 基地 $island->{'arm'} ++; } } } #生産力 $island->{'prod'} = &Util::min($island->{'pop'}, $island->{'work'}); } #---------------------------------------------------------------------- # IO package 入出力 #---------------------------------------------------------------------- package IO; # cgiデータの読み込み sub cgiInput() { my($line); # 入力を受け取って日本語変換 $line = <>; $line =~ tr/+/ /; $line =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $line = &jcode::euc($line); $line =~ s/[\x00-\x1f\,]//g; # 対象の島の名前 if($line =~ /CommandButton=(.*)へ送信/) { # コマンド送信ボタンの場合 $Island::name = $1; $Island::defaultName = $1; } elsif($line =~ /ISLANDNAME=([^\&]*)\&/){ # その他の場合 $Island::name = $1; $Island::defaultName = $1; } else { $Island::name = $line; } # パスワード if($line =~ /PASSWORD=([^\&]*)\&/) { $Island::password = $1; $Island::defaultPassword = $1; } if($line =~ /PASSWORD2=([^\&]*)\&/) { $Island::password2 = $1; } # メッセージ if($line =~ /MESSAGE=([^\&]*)\&/) { $Island::message = $1; } # 簡略表示モード if($line =~ /SIMPLEMODE=simple\&/) { $Island::printMode = 'simple'; } else { $Island::printMode = ''; } # main modeの取得 if($line =~ /TurnButton/) { if($Value::debug == 1) { $Island::mainMode = 'turn'; } } elsif($line =~ /OwnerButton/) { $Island::mainMode = 'owner'; } elsif($line =~ /SightButton/) { $Island::mainMode = 'print'; } elsif($line =~ /NewIslandButton/) { $Island::mainMode = 'new'; } elsif($line =~ /CommandButton/) { $Island::mainMode = 'command'; # コマンドモードの場合、コマンドの取得 $line =~ /NUMBER=([^\&]*)\&/; $Command::planNumber = $1; $line =~ /COMMAND=([^\&]*)\&/; $Command::kind = $1; $line =~ /TARGETNAME=([^\&]*)\&/; $Command::target = $1; $Island::defaultTarget = $1; $line =~ /POINTX=([^\&]*)\&/; $Command::x = $1; $line =~ /POINTY=([^\&]*)\&/; $Command::y = $1; $line =~ /COMMANDKIND=([^\&]*)\&/; $Command::mode = $1; } else { $Island::mainMode = 'top'; } } # 島データの読み込み sub parseAll() { # ファイルを開く if(open(IN, "hakoniwa.dat") == 0) { close(IN); my($now); # データファイルが無かった場合、作る open(OUT, ">hakoniwa.dat"); print OUT "1\n"; #ターン数 $now = time; $now = $now - ($now % ($Value::unitTime)); print OUT "$now\n"; # 開始時間 print OUT "0\n"; # 島の数 close(OUT); chmod(0666, 'hakoniwa.dat'); return &parseAll(); } # 現在のターン数を読み込む chomp($Island::turn = ); chomp($Island::lastUpdateTime = ); chomp($Island::totalNumber = ); my($i); for($i = 0; $i < $Island::totalNumber; $i++) { # 各島を読み込む $Island::island[$i] = &parseIsland(); #人口その他の計算 &Calc::estimate($Island::island[$i]); } close(IN); } # 島一つをよみこみ sub parseIsland() { my($name, $password, $money, $y, $x, $i, $line, @land, @command); chomp($name = ); # 名前 chomp($absent = ); # 連続資金繰り chomp($message = ); # メッセージ chomp($password = ); # password chomp($money = ); # 金 # 土地 for($y = 0; $y < $Value::islandSize; $y++) { $line = ; for($x = 0; $x < $Value::islandSize; $x++) { $line =~ s/.//; if($& eq 'a') { $land[$x][$y] = 10; } else { $land[$x][$y] = $&; } } } #コマンド for($i = 0; $i < $Value::commandMax; $i++) { $line = ; $line =~ /^(.*),(.*),(.*),(.*)$/; $command[$i] = { 'kind' => $1, 'target' => $2, 'x' => $3, 'y' => $4 }; } #島型にして返す return { 'name' => $name, 'password' => $password, 'money' => $money, 'land' => \@land, 'command' => \@command, 'message' => $message, 'absent' => $absent }; } # 島データの書き出し sub writeIslands() { my($total, $i); # 生きてる島を数える $total = 0; for($i = 0; $i < $Island::totalNumber; $i++) { if($Island::island[$i]->{'dead'} != 1) { $total++; } } # ファイル開く if(open(OUT, '>hakoniwa.dat') == 0) { print "HOGE STOP"; exit(1); } # ターン数、最終更新、島の数 print OUT "$Island::turn\n"; print OUT "$Island::lastUpdateTime\n"; print OUT "$total\n"; # 各島を書き出す for($i = 0; $i < $Island::totalNumber; $i++) { if($Island::island[$i]->{'dead'} != 1) { &writeIsland($Island::island[$i]); } } # ファイル閉じる close(OUT); } # 島一つの書き出し sub writeIsland($) { my($island) = @_; my($land, $command, $x, $y, $i); #名前、message、password、資金 print OUT "$island->{'name'}\n"; print OUT "$island->{'absent'}\n"; if($island->{'name'} eq $Island::defaultName) { if($Island::message ne "") { print OUT "${Island::message}\n"; } else { print OUT "$island->{'message'}\n"; } } else { print OUT "$island->{'message'}\n"; } print OUT "$island->{'password'}\n"; print OUT "$island->{'money'}\n"; # 要素取り出し $land = $island->{'land'}; $command = $island->{'command'}; # 陸地の書き出し for($y = 0; $y < $Value::islandSize; $y++) { for($x = 0; $x < $Value::islandSize; $x++) { printf OUT "%x",$land->[$x][$y]; } print OUT "\n"; } # 計画の書き出し for($i = 0; $i < $Value::commandMax; $i++) { print OUT "$command->[$i]->{'kind'},"; print OUT "$command->[$i]->{'target'},"; print OUT "$command->[$i]->{'x'},"; print OUT "$command->[$i]->{'y'}\n"; } } # 標準出力への出力 sub out($) { my($str) = @_; print STDOUT &jcode::sjis($str); } # logfile 1行追記 sub outLog($) { my($str) = @_; my($turn); open(OUT, '>>hakoniwa.log0'); $turn = &Temp::logTurn(); print OUT "$turn$str\n"; close(OUT); } # logfile 遅延追記 sub outLogLate($) { my($str) = @_; my($turn); $turn = &Temp::logTurn(); push(@lateLog, "$turn$str\n"); } sub lateLogWrite() { open(OUT, '>>hakoniwa.log0'); print OUT @lateLog; close(OUT); @lateLog = (); } # logfile 1行追記 sub outLogSecret($$) { my($name, $str) = @_; my($turn); open(OUT, '>>hakoniwa.log0'); $turn = &Temp::logTurn(); print OUT "secretinfo$name${turn}(機密)$str\n"; close(OUT); } #---------------------------------------------------------------------- #Lock package 同時アクセス対策 #---------------------------------------------------------------------- package Lock; sub lock() { my($t); # ロックを試す if(unlink('./key-free')) { # 成功 # ロック時間書き出し open(OUT, '>key-locked'); print OUT time; close(OUT); return 1; } else { # ロック時間チェック if(!open(IN, 'key-locked')) { return 0; } $t = ; close(IN); if(($t != 0) && (($t + 120) < time)) { # 120秒以上経過してたら、強制的にロックを外す unlock(); } return 0; } } sub unlock() { # ロックを外す my($i); $i = rename('./key-locked', './key-free'); } #---------------------------------------------------------------------- #Util package 各種便利ツール #---------------------------------------------------------------------- package Util; #島の名前から番号を取得するやつ sub nameToNumber { my($i, $name); $name = $_[0]; for($i = 0; $i < $Island::totalNumber; $i++){ if($Island::island[$i]->{'name'} eq $name) { return $i; } } return -1; } #pass wordをエンコードするやつ sub encode($) { return crypt($_[0], 'hakoniwa'); # (cryptの使い方の自信無し) } #小さい方を返すやつ sub min($$) { my($x, $y) = @_; if($x > $y) { return $y; } else { return $x } } # コマンドを後ろにずらすやつ sub slideBack($$) { my($command,$number,$i) = @_; my($i); for($i = $Value::commandMax - 1; $i > $number; $i--) { $command->[$i] = $command->[$i - 1]; } } # コマンドを前につめるやつ sub slideFront($$) { my($command,$number) = @_; my($i); for($i = $number; $i < ($Value::commandMax - 1); $i++) { $command->[$i] = $command->[$i + 1]; } $command->[$Value::commandMax - 1] = { 'kind' => 0, 'target' => '', 'x' => 0, 'y' => 0 }; } # 1d10 sub dice($) { return int(rand(1) * $_[0]) + 1; } # 人口順にソート sub sort() { my($flag, $size, $i, $tmp); # ばぶるそおと $flag = 1; $size = $Island::totalNumber; while($flag == 1) { $flag = 0; for($i = 0; $i < ($size - 1); $i++) { if($Island::island[$i]->{'pop'} < $Island::island[$i + 1]->{'pop'}) { $flag = 1; # 島の入れ換え $tmp = $Island::island[$i]; $Island::island[$i] = $Island::island[$i + 1]; $Island::island[$i + 1] = $tmp; } } } } #---------------------------------------------------------------------- #Cookie package cookie入出力 #---------------------------------------------------------------------- package Cookie; #cookie入力 sub input() { my($cookie); $cookie = &jcode::euc($ENV{'HTTP_COOKIE'}); if($cookie =~ /${Value::baseDir}OWNISLANDNAME=\(([^\)]*)\)/) { $Island::defaultName = $1; } if($cookie =~ /${Value::baseDir}OWNISLANDPASSWORD=\(([^\)]*)\)/) { $Island::defaultPassword = $1; } if($cookie =~ /${Value::baseDir}TARGETISLANDNAME=\(([^\)]*)\)/) { $Island::defaultTarget = $1; } } #cookie出力 sub output() { my($cookie, $info); # 消える期限の設定 my($sec, $min, $hour, $date, $mon, $year, $day, $yday, $dummy) = gmtime(time + 30 * 86400); # 現在 + 30日 # 2ケタ化 if ($year < 10) { $year = "0$year"; } if ($date < 10) { $date = "0$date"; } if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } # 曜日を文字に $day = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")[$day]; # 月を文字に $mon = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[$mon]; # パスと期限のセット $info = "; expires=$day, $date\-$mon\-$year $hour:$min:$sec GMT\n"; # $info = "path=$Value::baseDir/\n"; $cookie = ''; if(($Island::name) && ($Island::mainMode eq 'owner')){ # if($Island::name) { $cookie .= "Set-Cookie: ${Value::baseDir}OWNISLANDNAME=($Island::name) $info"; } if($Island::password) { $cookie .= "Set-Cookie: ${Value::baseDir}OWNISLANDPASSWORD=($Island::password) $info"; } if($Command::target) { $cookie .= "Set-Cookie: ${Value::baseDir}TARGETISLANDNAME=($Command::target) $info"; } &IO::out($cookie); } #---------------------------------------------------------------------- #Log package Log表示関係 #---------------------------------------------------------------------- package Log; sub printAll() { my($i); for($i = 0; $i < $Value::logPrint; $i++) { &print('', 0, "hakoniwa.log$i"); } } sub printOther($) { my($i); for($i = 0; $i < $Value::logMax; $i++) { &print($_[0], 0, "hakoniwa.log$i"); } } sub printOwner($) { my($i); for($i = 0; $i < $Value::logMax; $i++) { &print($_[0], 1, "hakoniwa.log$i"); } } sub print($$$) { my($name, $secret, $fileName) = @_; my($count, @line, $i, $line, $turn); $turn = &Temp::logTurn(); # ログファイルを読み込む open(IN, $fileName); $count = 0; while() { $line[$count] = $_; $count++; } close(IN); # 表示 for($i = $count - 1; $i >= 0; $i--) { $line = $line[$i]; if($line =~ /^secretinfo/) { # 機密情報チェック if(($secret == 1) && ($line =~ s/^secretinfo$name//)) { &IO::out($line . '
'); } } else { if(($name eq '') || ($line =~ /$name/)) { &IO::out($line . '
'); } } } } #---------------------------------------------------------------------- #Temp package 出力Template #---------------------------------------------------------------------- package Temp; BEGIN { my($i, $j, $c, $selected); # タイトル $tt_ = ''; $_tt = ''; # 大きい文字 $big_ = ''; $_big = ''; # ちょっと大きい文字 $mid_ = ''; $_mid = ''; # 強調文字、表項目 $ind_ = ''; $_ind = ''; # 位置、島の名前 $pt_ = ''; $_pt = ''; # 島の名前、薄め $pt2_ = ''; $_pt2 = ''; # コマンド $com_ = ''; $_com = ''; # 災害 $red_ = ''; $_red = ''; # 島のSELECTの中身 $islandList = ''; $targetList = ''; # 「戻る」リンク $back = "${big_}戻る${_big}"; # 計画番号用のリストボックス $numberList = ''; for($i = 0; $i < $Value::commandMax; $i++) { $j = $i + 1; $numberList .= "