箱庭諸島/hakoniwa.cgi

提供: Hakoniwapedia
移動: 案内検索

箱庭諸島 > 箱庭諸島/hakoniwa.cgi

本文


以降の記述にはスクリプト本文があります。 [記述をスキップ]



<nowiki>
#!/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]       = '<FONT STYLE="background-color:blue">海</FONT>';
    $word[$wasteland] = '<FONT STYLE="background-color:darkred">荒</FONT>';
    $word[$plains]    = '<FONT STYLE="background-color:greenyellow">平</FONT>';
    $word[$town1]     = '<FONT STYLE="background-color:yellow">村</FONT>';
    $word[$town2]     = '<FONT STYLE="background-color:orange">町</FONT>';
    $word[$town3]     = '<FONT STYLE="background-color:lightgrey">都</FONT>';
    $word[$forest]    = '<FONT STYLE="background-color:forestgreen">森</FONT>';
    $word[$farm]      = '<FONT STYLE="background-color:palegreen">農</FONT>';
    $word[$factory]   = '<FONT STYLE="background-color:gray">工</FONT>';
    $word[$base]      = '<FONT STYLE="background-color:olive">基</FONT>';
    $word[$dbase]     = '<FONT STYLE="background-color:crimson">防</FONT>';
}

# 陸地である
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 = <IN>);
    chomp($Island::lastUpdateTime = <IN>);
    chomp($Island::totalNumber = <IN>);

    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 = <IN>);     # 名前
    chomp($absent = <IN>);   # 連続資金繰り
    chomp($message = <IN>);  # メッセージ
    chomp($password = <IN>); # password
    chomp($money = <IN>);    # 金
    
    # 土地
    for($y = 0; $y < $Value::islandSize; $y++) {
	$line = <IN>;
	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 = <IN>;
	$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}<B>(機密)</B>$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 = <IN>;
	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(<IN>) {
	$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 . '<BR>');
	    }
        } else {
	    if(($name eq '') || ($line =~ /$name/)) {
		&IO::out($line . '<BR>');
	    }
	}
    }
}

#----------------------------------------------------------------------
#Temp package 出力Template
#----------------------------------------------------------------------
package Temp;
BEGIN {
    my($i, $j, $c, $selected);

    # タイトル
    $tt_ = '<FONT COLOR="#4040a0"><B>';
    $_tt = '</B></FONT>';

    # 大きい文字
    $big_ = '<FONT SIZE=6><B>';
    $_big = '</B></FONT>';

    # ちょっと大きい文字
    $mid_ = '<FONT SIZE=4><B>';
    $_mid = '</B></FONT>';

    # 強調文字、表項目
    $ind_ = '<FONT COLOR="#800000"><B>';
    $_ind = '</B></FONT>';

    # 位置、島の名前
    $pt_ = '<FONT COLOR="#a06040"><B>';
    $_pt = '</B></FONT>';

    # 島の名前、薄め
    $pt2_ = '<FONT COLOR="#808080"><B>';
    $_pt2 = '</B></FONT>';

    # コマンド
    $com_ = '<FONT COLOR="#202060"><B>';
    $_com = '</B></FONT>';

    # 災害
    $red_ = '<FONT COLOR="#e00000"><B>';
    $_red = '</B></FONT>';

    # 島のSELECTの中身
    $islandList = '';
    $targetList = '';

    # 「戻る」リンク
    $back = "<A HREF=\"$Value::thisFile\">${big_}戻る${_big}</A>";

    # 計画番号用のリストボックス
    $numberList = '';
    for($i = 0; $i < $Value::commandMax; $i++) {
	$j = $i + 1;
	$numberList .=
	    "<OPTION VALUE=$i>$j\n";
    }
    
    # 座標用のリストボックス
    $pointList = '';
    for($i = 0; $i < $Value::islandSize; $i++) {
	$pointList .=
	    "<OPTION VALUE=$i>$i\n";
    }
    
    # 計画用のリストボックス
    $commandList = '';
    for($i = 0; $i < $Command::total; $i++) {
	$c = $Command::list[$i];
	if($c == $Command::prepare) {
	    $selected = 'SELECTED'; # 整地をデフォルトに
	} else {
	    $selected = '';
	}
	$commandList .= "<OPTION VALUE=$c $selected>$Command::name[$c]($Command::cost[$c]$Value::moneyUnit)";
    }
}


# 島データのプルダウンメニュー用
sub getIslandList($) {
    my($select) = @_;
    my($list, $name);

    #島リストのメニュー
    $list = '';
    for($i = 0; $i < $Island::totalNumber; $i++) {
	$name = $Island::island[$i]->{'name'};
	if($name eq $select) {
	    $s = 'SELECTED';
	} else {
	    $s = '';
	}
	$list .=
	    "<OPTION VALUE=\"$name\" $s>$name\n";
    }
    return $list;
}


#プルダウンメニューの内容等を更新する
#(島データが更新された後に呼ばれる)
sub initialize() {
    my($i, $j, $s, $name, $pop, $money, $farm, $factory, $message, $absent,
       $pm);

    # 簡略表示チェックボックス
    if($Island::printMode eq 'simple') {
	$pm = 'CHECKED';
    } else {
	$pm = '';
    }
    $simpleBox = "<INPUT TYPE=checkbox NAME=SIMPLEMODE VALUE=\"simple\" $pm>簡略表示\n";

    # 島リストのメニュー
    $islandList = &getIslandList($Island::defaultName);
    $targetList = &getIslandList($Island::defaultTarget);

    # ランキングの中身
    $islandRanking = '';
    for($i = 0; $i < $Island::totalNumber; $i++) {
	$j = $i + 1;
	$name = $Island::island[$i]->{'name'};
	$pop = $Island::island[$i]->{'pop'};
	$money = $Island::island[$i]->{'money'};
	$farm = $Island::island[$i]->{'farm'};
	$factory = $Island::island[$i]->{'factory'};
	$message = $Island::island[$i]->{'message'};
	$message = &escape($message);
	$absent = $Island::island[$i]->{'absent'};
	if($absent > 0) {
	    $name = "<TD><NOBR>${pt2_}$name${_pt2}</NOBR></TD>";
	} else {
	    $name = "<TD><NOBR>${pt_}$name${_pt}</NOBR></TD>";
	}
	$islandRanking .= <<END;
<TR>
<TD align=center><NOBR>${mid_}$j${_mid}</NOBR></TD>
$name
<TD><NOBR>$pop$Value::popUnit</NOBR></TD>
<TD><NOBR>$money$Value::moneyUnit</NOBR></TD>
<TD align=center><NOBR>$factory</NOBR></TD>
<TD align=center><NOBR>$farm</NOBR></TD>
<TD><NOBR>$message</NOBR></TD>
</TR>
END
    }
}

# HTMLの文字をエスケープ
sub escape($) {
    my($s) = @_;
    $s =~ s/&/&/g;
    $s =~ s/</</g;
    $s =~ s/>/>/g;
    $s =~ s/\"/"/g; #"
    return $s;
}

# HTMLのアタマ
sub header($) {
    my($body) = @_;
return <<END;
Content-type: text/html

<HTML>
<HEAD>
<TITLE>
箱庭諸島
</TITLE>
</STYLE>
</HEAD>
<BODY $body>
END
}

# HTMLのケツ
sub footer() {
return <<END;
<HR>
<P align=center>
管理者:$Value::admin(<A HREF="mailto:$Value::email">$Value::email</A>)<BR>
掲示板(<A HREF="$Value::bbs">$Value::bbs</A>)<BR>
トップページ(<A HREF="$Value::toppage">$Value::toppage</A>)<BR>
箱庭諸島のページ(<A HREF="http://www.bekkoame.ne.jp/~tokuoka/hakoniwa.html">http://www.bekkoame.ne.jp/~tokuoka/hakoniwa.html</A>)<BR>
</P>
</BODY>
</HTML>
END
}

#トップページ
sub topPage() {
    my($debugStr, $newStr);
    $debugStr = '';
    if($Value::debug == 1) {
	$debugStr = <<END;
<FORM action="$Value::thisFile" method=POST>
<INPUT TYPE=submit VALUE="ターンを進める" NAME=TurnButton>
</FORM>
END
    }

    if($Island::totalNumber >= $Value::maxIsland) {
	$newStr = <<END;
<H1>${tt_}新しい島を探す${_tt}</H1>
島の数が最大数です・・・現在登録できません。
END
    } else {
        $newStr = <<END;
<H1>${tt_}新しい島を探す${_tt}</H1>
<FORM action="$Value::thisFile" method=POST>
どんな名前をつける予定?<BR>
<INPUT TYPE=text NAME=ISLANDNAME SIZE=32 MAXLENGTH=32>島<BR>
パスワードは?<BR>
<INPUT TYPE=password NAME=PASSWORD SIZE=32 MAXLENGTH=32><BR>
念のためパスワードをもう一回<BR>
<INPUT TYPE=password NAME=PASSWORD2><BR>

<INPUT TYPE=submit VALUE="探しに行く" NAME=NewIslandButton>
</FORM>
END
    }

return <<END;
$debugStr

<H1>${tt_}自分の島へ${_tt}</H1>
<FORM action="$Value::thisFile" method=POST>
あなたの島の名前は?<BR>
<SELECT NAME=ISLANDNAME>
$islandList
</SELECT><BR>

パスワードをどうぞ!!<BR>
<INPUT TYPE=password NAME=PASSWORD VALUE="$Island::defaultPassword"><BR>
$simpleBox<BR>
<INPUT TYPE=submit VALUE="開発しに行く" NAME=OwnerButton><BR>
</FORM>

<HR>
<H1>${tt_}その他の島へ${_tt}</H1>
<FORM action="$Value::thisFile" method=POST>
どの島を見に行く?<BR>
<SELECT NAME=ISLANDNAME>
$islandList
</SELECT>
<BR>
$simpleBox<BR>
<INPUT TYPE=submit VALUE="観光しに行く" NAME=SightButton>
</FORM>

<HR>
$newStr
<HR>

<H1>${tt_}諸島の状況${_tt}</H1>
<TABLE BORDER>
<TR><TD COLSPAN=7>
${big_}ターン${Island::turn}:${_big}
</TD></TR>
<TR>
<TH><NOBR>${ind_}順位${_ind}</NOBR></TH>
<TH><NOBR>${ind_}島${_ind}</NOBR></TH>
<TH><NOBR>${ind_}人口${_ind}</NOBR></TH>
<TH><NOBR>${ind_}資金${_ind}</NOBR></TH>
<TH><NOBR>${ind_}工場${_ind}</NOBR></TH>
<TH><NOBR>${ind_}農場${_ind}</NOBR></TH>
<TH><NOBR>${ind_}コメント${_ind}</NOBR></TH>
$islandRanking
</TR>
</TABLE>

<HR>
<H1>${tt_}最近の出来事${_tt}</H1>

END
}

# 島の表示
sub islandMap($$) {
    my($mode, $island) = @_;
    my($str, $x, $y, $kind, $caption, $land, $sm, $tmp);
    $land = $island->{'land'};

    if($Island::printMode eq 'simple') {
	$sm = 1;
    } else {
	$sm = 0;
    }

    # 本体
    $str = '';
    $str .= <<END;
<CENTER>
<TABLE BORDER>
<TR>
<TH>${ind_}人口${_ind}</TH>
<TD>$island->{'pop'}$Value::popUnit</TD>
<TH>${ind_}資金${_ind}</B></TH>
<TD>$island->{'money'}$Value::moneyUnit</TD>
</TR>
<TR>
<TH>${ind_}工場${_ind}</TH>
<TD align=center>$island->{'factory'}</TD>
<TH>${ind_}農場${_ind}</B></TH>
<TD align=center>$island->{'farm'}</TD>
</TR>
</TABLE>
<TABLE BORDER WIDTH=0 HEIGHT=0 CELLSPACING=0 CELLPADDING=0>
<TR><TD>
END
    if($sm == 0) {
	$str .= "<IMG SRC=\"$Value::imageDir/xbar.gif\" width=400 height=16><BR>";
    } else {
	$str .= "<PRE><FONT SIZE=5>  0 1 2 3 4 5 6 7 8 9 0 1\n";
    }
    for($y = 0; $y < $Value::islandSize; $y++) {
	if($sm == 1) {
	    if($y < 10) {
		$str .= "$y";
	    } else {
		$tmp = $y - 10;
		$str .= "$tmp";
	    }
	}
        if(($y % 2) == 0) {
	    if($sm == 0) {
		$str .= "<IMG SRC=\"$Value::imageDir/space${y}.gif\" width=16 height=32>";
	    } else {
		$str .= " ";
	    }
	}
	for($x = 0; $x < $Value::islandSize; $x++) {
	    $kind = $land->[$x][$y];
	    if(($kind == $Land::base) && ($mode == 0)) {
		$kind = $Land::forest;
	    }
	    $caption= "($x, $y)$Land::name[$kind]";
	    if($sm == 0) {
		$str .= "<IMG SRC=\"$Value::imageDir/land$kind.gif\" ALT=\"$caption\" width=32 height=32>";
	    } else {
		$str .= $Land::word[$kind];
	    }
	}
        if(($y % 2) == 1) {
	    if($sm == 0) {
		$str .= "<IMG SRC=\"$Value::imageDir/space${y}.gif\" width=16 height=32>";
	    } else {
		$str .= " ";
	    }
	}
	if($sm == 0) {
	    $str .= "<BR>";
	} else {
	    $str .= "\n";
	}
    }
    if($sm == 1) {
	$str .= "</FONT>
";
   }
   $str .= "</TD></TR></TABLE></CENTER>";
   return $str;

}

  1. 新規で名前が無い場合

sub newIslandNoName() { return <<END; ${big_}島につける名前が必要です。${_big}$back END }

  1. 新規で名前がすでに使用されている場合

sub newIslandAlready() { return <<END; ${big_}その島ならすでに発見されています。${_big}$back END }

  1. 新規で名前が反則な場合

sub newIslandBadName() { return <<END; ${big_}',?()<>'とか入った変な文字入った名前はやめましょうよ~。${_big}$back END }

  1. 新規で島が作成された場合

sub newIslandSuccess($) {

   my($island) = @_;
   $map = &Temp::islandMap(1,$island);

return <<END;

${big_}島を発見しました!!${_big}
${big_}${pt_}「$island->{'name'}」${_pt}${_big}
${big_}と名付けます。${_big}
$map
$back

END }

  1. 島の表示モード

sub printIsland($) {

   my($island) = @_;
   $map = &Temp::islandMap(0,$island);

return <<END;

${big_}${pt_}$island->{'name'}${_pt}へようこそ!!${_big}
$back
$map
$back

${big_}${pt_}$island->{'name'}${_pt}の近況${_big}
END }

  1. コマンド変数モード

sub ownerMode($) {

   my($island) = @_;
   my($map, $command1, $command2, $command3, $command4);
   $map = &islandMap(1,$island);
   $command1 = &islandCommand($island->{'command'}, 0,

int($Value::commandMax / 5 * 2));

   $command2 = &islandCommand($island->{'command'},

int($Value::commandMax / 5 * 2), int($Value::commandMax / 5 * 3));

   $command3 = &islandCommand($island->{'command'},

int($Value::commandMax / 5 * 3), int($Value::commandMax / 5 * 4));

   $command4 = &islandCommand($island->{'command'},

int($Value::commandMax / 5 * 4), $Value::commandMax); return <<END;

${big_}${pt_}$island->{'name'}${_pt}開発計画${_big}
$back

<FORM action="$Value::thisFile" method=POST>

計画番号 開発計画 ターゲット 座標

<SELECT NAME=NUMBER> $numberList </SELECT>

<SELECT NAME=COMMAND> $commandList </SELECT>

<SELECT NAME=TARGETNAME> $targetList </SELECT>

( <SELECT NAME=POINTX> $pointList </SELECT> , <SELECT NAME=POINTY> $pointList </SELECT> )

<INPUT TYPE=radio NAME=COMMANDKIND VALUE=insert CHECKED>挿入 <INPUT TYPE=radio NAME=COMMANDKIND VALUE=write>上書き <INPUT TYPE=radio NAME=COMMANDKIND VALUE=delete>削除 $simpleBox

コメント<INPUT TYPE=text NAME=MESSAGE SIZE=80 MAXLENGTH=80>

パスワード <INPUT TYPE=password NAME=PASSWORD VALUE="$Island::defaultPassword">

<INPUT TYPE=submit VALUE="$island->{'name'}へ送信" NAME=CommandButton>

</FORM>

$command1

$map

$command2
$command3
$command4

$back

${big_}${pt_}$island->{'name'}${_pt}の近況${_big}
END }

sub islandCommand($$$) {

   my($command, $start, $end) = @_;
   my($i, $j, $kind, $target, $x, $y, $str, $pt);
   $str = ;
   for($i = $start; $i < $end; $i++) {

$j = $i + 1; $str .= "<TR><TD>$ind_$j$_ind</TD><TD>";

# 各値の取り出し $kind = $command->[$i]->{'kind'}; $target = $command->[$i]->{'target'}; $x = $command->[$i]->{'x'}; $y = $command->[$i]->{'y'};

# 基本部品 $pt = &point($x, $y); # 座標 $tg = &targetName($target); # 発射目標

# 分岐 if(($kind == $Command::doNothing) ||($kind == $Command::giveup)) { # 資金繰り、島の放棄 $str .= "${com_}$Command::name[$kind]${_com}"; } elsif(($kind == $Command::prepare) ||($kind == $Command::prepare2) ||($kind == $Command::plant) ||($kind == $Command::farm) ||($kind == $Command::factory) ||($kind == $Command::base) ||($kind == $Command::dbase) ||($kind == $Command::reclaim)) { $str .= "$ptで${com_}$Command::name[$kind]${_com}"; } elsif(($kind == $Command::missileNM) ||($kind == $Command::missilePP) ||($kind == $Command::missileST) ||($kind == $Command::missileLD)) { $str .= "$tgの$ptへ${com_}$Command::name[$kind]${_com}"; } elsif(($kind == $Command::donate) || ($kind == $Command::aid)) { $str .= "$tgへ${com_}$Command::name[$kind]${_com}"; }

$str .= "</TD></TR>";

   }
   return $str;

}

  1. 座標

sub point($$) {

   my($x, $y) = @_;
   return "$pt_($x,$y)$_pt";

}

  1. 座標

sub targetName($) {

   return "$pt_$_[0]$_pt";

}

  1. password無し

sub noPassword() { return <<END; ${big_}パスワードがありません。${_big}$back END }

  1. password間違い

sub wrongPassword() { return <<END; ${big_}パスワードが違います。${_big}$back END }

  1. lock失敗

sub lockFail() { return <<END; ${big_}同時アクセスエラーです。${_big}$back END }

  1. ターン

sub logTurn() {

   return "${ind_}ターン${Island::turn}:${_ind}";

}

  1. 島発見の log記述

sub logNewIsland($) {

   return "新しく${pt_}$_[0]${_pt}が発見されました。";

}

  1. コマンド削除

sub comDelete() {

return "${big_}コマンドを削除しました${_big}
";

}

  1. コマンド登録

sub comAdd() {

return "${big_}コマンドを登録しました${_big}
";

}

  1. 資金不足

sub procNoMoney($$) {

   my($name, $com) = @_;
   return "${pt_}$name${_pt}で予定されていた${com_}$com${_com}は、資金不足のため実行できませんでした。";

}

  1. 整地等の失敗

sub procNotAdeqLand($$$$) {

   my($name, $pt, $com, $land) = @_;
   return "${pt_}$name${_pt}で予定されていた${com_}$com${_com}は、予定地の${pt_}$pt${_pt}地点が${big_}$land${_big}であったため実施できませんでした。";

}

  1. 整地等の成功

sub procSuccess($$$) {

   my($name, $pt, $com) = @_;
   return "${pt_}$name$pt${_pt}で${com_}$com${_com}が行われました。";

}

  1. 森か基地の建設

sub procPBSuccess($) {

   my($name) = @_;
   return "こころなしか、${pt_}$name${_pt}の${big_}森${_big}が増えたようです。";

}

  1. 島の放棄

sub procGiveup($) {

   my($name) = @_;
   return "${pt_}$name${_pt}は放棄され、${big_}無人島${_big}になりました。";

}

  1. 資金援助

sub procAid($$$) {

   my($name, $com, $target) = @_;
   return "${pt_}$name${_pt}が${pt_}$target${_pt}へ${com_}$com${_com}を行いました。";

}

sub procAid2($$$) {

   my($name, $com, $target) = @_;
   return "${pt_}$name${_pt}で予定されていた${com_}$com${_com}は、${pt_}$target${_pt}がすでに${big_}無人島${_big}になっているため手遅れでした。";

}

  1. 基地が無くてミサイルが打てない

sub procNoBase($$) {

   my($name, $com) = @_;
   return "${pt_}$name${_pt}で予定されていた${com_}$com${_com}は、ミサイル基地を保有していないため実施できませんでした。";

}

  1. 目標が無くてミサイルが打てない

sub procNoTarget($$$) {

   my($name, $com, $target) = @_;
   return "${pt_}$name${_pt}で予定されていた${com_}$com${_com}は、目標の${pt_}$target${_pt}がすでに放棄されているため、中止されました。";

}

  1. 画面外に落ちる

sub missileOutArea($$$$) {

   my($name, $com, $target, $pt) = @_;
   return "${pt_}$name${_pt}が${pt_}$target${_pt}の${pt_}$pt${_pt}地点に向けて${com_}$com${_com}を行いましたが、領域外の海に落ちた模様です。";

}

  1. 海ポチャ

sub missileSea($$$$$) {

   my($name, $com, $target, $pt, $tPt) = @_;
   return "${pt_}$name${_pt}が${pt_}$target${_pt}の${pt_}$pt${_pt}地点に向けて${com_}$com${_com}を行いましたが、${pt_}$tPt${_pt}の海に落ちた模様です。";

}

  1. 防衛施設でキャッチ

sub missileDef($$$$$) {

   my($name, $com, $target, $pt, $tPt) = @_;
   return "${pt_}$name${_pt}が${pt_}$target${_pt}の${pt_}$pt${_pt}地点に向けて${com_}$com${_com}を行いましたが、${pt_}$tPt${_pt}地点上空で力場に捕らえられ、${big_}空中爆破${_big}しました。";

}

  1. 通常弾

sub missileNormal($$$$$$) {

   my($name, $com, $target, $pt, $tPt, $tName) = @_;
   return "${pt_}$name${_pt}が${pt_}$target${_pt}の${pt_}$pt${_pt}地点に向けて${com_}$com${_com}を行い、${pt_}$tPt${_pt}の${big_}$tName${_big}に着弾。一帯が荒地と化しました。";

}

  1. 陸地破壊

sub missileLD($$$$$$) {

   my($name, $com, $target, $pt, $tPt, $tName) = @_;
   return "${pt_}$name${_pt}が${pt_}$target${_pt}の${pt_}$pt${_pt}地点に向けて${com_}$com${_com}を行い、${pt_}$tPt${_pt}の${big_}$tName${_big}に着弾。一帯が水没しました。";

}

  1. 死滅

sub procDead($) {

   my($name) = @_;
   return "${pt_}$name${_pt}から人がいなくなり、${big_}無人島${_big}になりました。";

}

  1. 火災発生

sub disFire($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}で${red_}火災発生${_red}、${lName}は壊滅しました。";

}

  1. 台風発生

sub disTyphoon1($) {

   my($name) = @_;
   return "${pt_}$name${_pt}を${red_}台風${_red}が襲いました。";

}

  1. 台風被害

sub disTyphoon2($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}は${red_}台風${_red}によりドームごと飛ばされました。";

}

  1. 地震発生

sub disEarthquake1($) {

   my($name) = @_;
   return "${pt_}$name${_pt}で大規模な${red_}地震${_red}が発生しました。";

}

  1. 地震被害

sub disEarthquake2($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}は${red_}地震${_red}により壊滅しました。";

}

  1. 津波発生

sub disTsunami1($) {

   my($name) = @_;
   return "${pt_}$name${_pt}付近で巨大な${red_}津波${_red}が発生しました。";

}

  1. 津波被害

sub disTsunami2($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}は${red_}津波${_red}により壊滅しました。";

}

  1. 火山噴火発生

sub disEruption0($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}で突然${red_}火山が噴火${_red}!!";

}

  1. 噴火の影響、海

sub disEruption1($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}に陸地ができました。";

}

  1. 噴火の影響、陸

sub disEruption2($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}だった所は、${red_}噴火${_red}により荒地になりました。";

}

  1. 海に隕石落下

sub disMeteo1($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点に${red_}隕石${_red}が落ちましたが、${big_}$lName${_big}であったため無事でした。";

}

  1. 陸に隕石落下

sub disMeteo2($$$$) {

   my($name, $lName, $x, $y) = @_;
   return "${pt_}$name($x,$y)${_pt}地点の${big_}$lName${_big}に${red_}隕石${_red}が落ち、一帯の陸地が水没しました。";

}

  1. 埋蔵金

sub disMaizo($$) {

   my($name, $price) = @_;
   return "${pt_}$name${_pt}で行われた整地中に、${big_}$price$Value::moneyUnit${_big}もの埋蔵金が発見されました。";

}


</nowiki> </pre>


以上でスクリプト本文の記述は終わりです。


解説

箱庭諸島ver1のスクリプト

[1]より