#!/usr/local/bin/perl
# ↑はサーバーに合わせて変更して下さい。
# perl5用です。
#----------------------------------------------------------------------
# 箱庭諸島 ver2.20
# メインスクリプト
# 使用条件、使用方法等は、hako-readme.txtファイルを参照
#
# 箱庭諸島のページ:
http://www.bekkoame.ne.jp/~tokuoka/hakoniwa.html
#----------------------------------------------------------------------
#$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%
# 重複登録追跡機能改造版
# 1999.11.27
# 改造者:T.Sakamoto
# http://village.infoweb.ne.jp/~sakatuba/
# ※ この「改造版」を使うことによるいかなる不利益に関して一切責任は持ちません。
# 使用者の責任において使用してください。
#
#%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$
package H2;
#----------------------------------------------------------------------
# 各種設定値
# (これ以降の部分の各設定値を、適切な値に変更してください)
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# 以下、必ず設定する部分
#----------------------------------------------------------------------
# このファイルを置くディレクトリ
# my($baseDir) = 'http://サーバー/ディレクトリ';
#
# 例)
# http://cgi2.bekkoame.ne.jp/cgi-bin/user/u5534/hakoniwa/hakojima.cgi
# として置く場合、
# my($baseDir) = 'http://cgi2.bekkoame.ne.jp/cgi-bin/user/u5534/hakoniwa';
# とする。最後にスラッシュ(/)は付けない。
my($baseDir) = 'http://XXXXXXXXX.XX.jp/~xxxxx/xxxxxx';
# 画像ファイルを置くディレクトリ
# my($imageDir) = 'http://サーバー/ディレクトリ';
my($imageDir) = 'http://www37.tok2.com/home/naotyhakoniwa/hako-image/';
# jcode.plの位置
# my($jcode) = '/usr/libperl/jcode.pl'; # ベッコアメの場合
# my($jcode) = './jcode.pl'; # 同じディレクトリに置く場合
my($jcode) = 'jcode.pl';
# マスターパスワード
# このパスワードは、すべての島のパスワードを代用できます。
# 例えば、「他の島のパスワード変更」等もできます。
my($masterPassword) = 'yourpassword';
# 特殊パスワード
# このパスワードで「名前変更」を行うと、その島の資金、食料が最大値になります。
# (実際に名前を変える必要はありません。)
$H2::specialPassword = 'specialpassword';
# 管理者名
my($adminName) = '名無しのゴンベイ';
# 管理者のメールアドレス
my($email) = 'XXXXXX@XXXXX.XX.jp';
# 掲示板アドレス
my($bbs) = 'http://WWWWWWW.WW.jp/~WWWWWWW/WWWWW/WWWWWW.cgi';
# ホームページのアドレス
my($toppage) = 'http://WWWWWWWWWW.WW.jp/~WWWWWWWW/index.html';
# ディレクトリのパーミッション
# 通常は0755でよいが、0777、0705、0704等でないとできないサーバーもあるらしい
$H2::dirMode = 0755;
# データディレクトリの名前
# ここで設定した名前のディレクトリ以下にデータが格納されます。
# デフォルトでは'data'となっていますが、セキュリティのため
# なるべく違う名前に変更してください。
$H2::dirName = 'data';
# ロックの方式
# 1 ディレクトリ
# 2 システムコール(可能ならば最も望ましい)
# 3 シンボリックリンク
# 4 通常ファイル(あまりお勧めでない)
my($lockMode) = 2;
# (注)
# 4を選択する場合には、'key-free'という、パーミション666の空のファイルを、
# このファイルと同位置に置いて下さい。
#----------------------------------------------------------------------
# 必ず設定する部分は以上
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# 以下、好みによって設定する部分
#----------------------------------------------------------------------
#----------------------------------------
# ゲームの進行やファイルなど
#----------------------------------------
# 1ターンが何秒か
$H2::unitTime = 21600; # 6時間
# 異常終了基準時間
# (ロック後何秒で、強制解除するか)
my($unlockTime) = 120;
# 島の最大数
$H2::maxIsland = 50;
# トップページに表示するログのターン数
$H2::topLogTurn = 2;
# ログファイル保持ターン数
$H2::logMax = 8;
# バックアップを何ターンおきに取るか
$H2::backupTurn = 12;
# バックアップを何回分残すか
$H2::backupTimes = 4;
# 発見ログ保持行数
$H2::historyMax = 10;
# 放棄コマンド自動入力ターン数
$H2::giveupTurn = 120;
# コマンド入力限界数
# (ゲームが始まってから変更すると、データファイルの互換性が無くなります。)
$H2::commandMax = 20;
# ローカル掲示板行数
# (ゲームが始まってから変更すると、データファイルの互換性が無くなります。)
$H2::lbbsMax = 10;
# 島の大きさ
# (変更できないかも)
$H2::islandSize = 12;
# 他人から資金を見えなくするか
# 0 見えない
# 1 見える
# 2 100の位で四捨五入
$H2::hideMoneyMode = 2;
# パスワードの暗号化(0だと暗号化しない、1だと暗号化する)
my($cryptOn) = 1;
# デバッグモード(1だと、「ターンを進める」ボタンが使用できる)
$H2::debug = 0;
#$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%$%%$
#重複登録者発見用パラメータ
#
# 重複登録の発見は「開発者訪問ログ」を見ることによって行ってください
# 「開発者訪問ログ」は島の開発計画入力画面に入る、もしくは
# 開発計画を送信したときに書き加えられます。
# 同じIPアドレスのユーザーが、続けてほかの島の開発を行っている場合、
# 重複登録した島に対して計画を送信している疑いがあります。
# ただし、この改造版は自動で重複を削除したり、警告を発したりする
# ような機能は**一切ありません**!!
# その辺はそれぞれの箱庭諸島の管理人の皆様にお任せします^^;
#
# 開発者訪問ログファイル名(ファイル名のみ)
# パスはスクリプトのあるディレクトリになります
# ここを空欄('')にすると、ログファイルを作成しません。
$H2::ownerLogFile = 'ownerLog.log';
# ログファイルの最大記録レコード数(島の最大数、ターン進行速度によって決めてください)
$H2::ownerLogMAX = 600;
#----------------------------------------
# 資金、食料などの設定値と単位
#----------------------------------------
# 初期資金
$H2::initialMoney = 1000;
# 初期食料
$H2::initialFood = 1000;
# お金の単位
$H2::unitMoney = '円';
# 食料の単位
$H2::unitFood = 'トン';
# 人口の単位
$H2::unitPop = '人';
# 広さの単位
$H2::unitArea = '坪';
# 木の数の単位
$H2::unitTree = '本';
# 木の単位当たりの売値
$H2::treeValue = 5;
# 名前変更のコスト
$H2::costChangeName = 500;
# 人口1単位あたりの食料消費料
$H2::eatenFood = 0.2;
#----------------------------------------
# 基地の経験値
#----------------------------------------
# 経験値の最大値
$H2::maxExpPoint = 200; # ただし、最大でも255まで
# レベルの最大値
my($maxBaseLevel) = 5; # ミサイル基地
my($maxSBaseLevel) = 3; # 海底基地
# 経験値がいくつでレベルアップか
my(@baseLevelUp, @sBaseLevelUp);
@baseLevelUp = (20, 60, 120, 200); # ミサイル基地
@sBaseLevelUp = (50, 200); # 海底基地
#----------------------------------------
# 防衛施設の自爆
#----------------------------------------
# 怪獣に踏まれた時自爆するなら1、しないなら0
$H2::dBaseAuto = 1;
#----------------------------------------
# 災害
#----------------------------------------
# 通常災害発生率(確率は0.1%単位)
$H2::disEarthquake = 5; # 地震
$H2::disTsunami = 15; # 津波
$H2::disTyphoon = 20; # 台風
$H2::disMeteo = 15; # 隕石
$H2::disHugeMeteo = 5; # 巨大隕石
$H2::disEruption = 10; # 噴火
$H2::disFire = 10; # 火災
$H2::disMaizo = 10; # 埋蔵金
# 地盤沈下
$H2::disFallBorder = 90; # 安全限界の広さ(Hex数)
$H2::disFalldown = 30; # その広さを超えた場合の確率
# 怪獣
$H2::disMonsBorder1 = 1000; # 人口基準1(怪獣レベル1)
$H2::disMonsBorder2 = 2500; # 人口基準2(怪獣レベル2)
$H2::disMonsBorder3 = 4000; # 人口基準3(怪獣レベル3)
$H2::disMonster = 3; # 単位面積あたりの出現率(0.01%単位)
# 種類
$H2::monsterNumber = 8;
# 各基準において出てくる怪獣の番号の最大値
$H2::monsterLevel1 = 2; # サンジラまで
$H2::monsterLevel2 = 5; # いのらゴーストまで
$H2::monsterLevel3 = 7; # キングいのらまで(全部)
# 名前
@H2::monsterName =
(
'メカいのら', # 0(人造)
'いのら', # 1
'サンジラ', # 2
'レッドいのら', # 3
'ダークいのら', # 4
'いのらゴースト', # 5
'クジラ', # 6
'キングいのら' # 7
);
# 最低体力、体力の幅、特殊能力、経験値、死体の値段
@H2::monsterBHP = ( 2, 1, 1, 3, 2, 1, 4, 5);
@H2::monsterDHP = ( 0, 2, 2, 2, 2, 0, 2, 2);
@H2::monsterSpecial = ( 0, 0, 3, 0, 1, 2, 4, 0);
@H2::monsterExp = ( 5, 5, 7,12,15,10,20,30);
@H2::monsterValue = ( 0, 400, 500, 1000, 800, 300, 1500, 2000);
# 特殊能力の内容は、
# 0 特になし
# 1 足が速い(最大2歩あるく)
# 2 足がとても速い(最大何歩あるくか不明)
# 3 奇数ターンは硬化
# 4 偶数ターンは硬化
# 画像ファイル
@H2::monsterImage =
(
'monster7.gif',
'monster0.gif',
'monster5.gif',
'monster1.gif',
'monster2.gif',
'monster8.gif',
'monster6.gif',
'monster3.gif'
);
# 画像ファイルその2(硬化中)
@H2::monsterImage2 =
('', '', 'monster4.gif', '', '', '', 'monster4.gif', '');
#----------------------------------------
# 油田
#----------------------------------------
# 油田の収入
$H2::oilMoney = 1000;
# 油田の枯渇確率
$H2::oilRatio = 40;
#----------------------------------------
# 記念碑
#----------------------------------------
# 何種類あるか
$H2::monumentNumber = 3;
# 名前
@H2::monumentName =
(
'モノリス',
'平和記念碑',
'戦いの碑'
);
# 画像ファイル
@H2::monumentImage =
(
'monument0.gif',
'monument0.gif',
'monument0.gif'
);
#----------------------------------------
# 賞関係
#----------------------------------------
# ターン杯を何ターン毎に出すか
$H2::turnPrizeUnit = 100;
# 賞の名前
$H2::prize[0] = 'ターン杯';
$H2::prize[1] = '繁栄賞';
$H2::prize[2] = '超繁栄賞';
$H2::prize[3] = '究極繁栄賞';
$H2::prize[4] = '平和賞';
$H2::prize[5] = '超平和賞';
$H2::prize[6] = '究極平和賞';
$H2::prize[7] = '災難賞';
$H2::prize[8] = '超災難賞';
$H2::prize[9] = '究極災難賞';
#----------------------------------------
# 外見関係
#----------------------------------------
# タグのオプション
my($htmlBody) = 'BGCOLOR="#EEFFFF"';
# ゲームのタイトル文字
$H2::title = '箱庭諸島2..';
# タグ
# タイトル文字
$H2::tagTitle_ = '';
$H2::_tagTitle = ' ';
# H1タグ用
$H2::tagHeader_ = '';
$H2::_tagHeader = ' ';
# 大きい文字
$H2::tagBig_ = '';
$H2::_tagBig = ' ';
# 島の名前など
$H2::tagName_ = '';
$H2::_tagName = ' ';
# 薄くなった島の名前
$H2::tagName2_ = '';
$H2::_tagName2 = ' ';
# 順位の番号など
$H2::tagNumber_ = '';
$H2::_tagNumber = ' ';
# 順位表における見だし
$H2::tagTH_ = '';
$H2::_tagTH = ' ';
# 開発計画の名前
$H2::tagComName_ = '';
$H2::_tagComName = ' ';
# 災害
$H2::tagDisaster_ = '';
$H2::_tagDisaster = ' ';
# ローカル掲示板、観光者の書いた文字
$H2::tagLbbsSS_ = '';
$H2::_tagLbbsSS = ' ';
# ローカル掲示板、島主の書いた文字
$H2::tagLbbsOW_ = '';
$H2::_tagLbbsOW = ' ';
# 通常の文字色(これだけでなく、BODYタグのオプションもちゃんと変更すべし
$H2::normalColor = '#000000';
# 順位表、セルの属性
$H2::bgTitleCell = 'BGCOLOR="#ccffcc"'; # 順位表見出し
$H2::bgNumberCell = 'BGCOLOR="#ccffcc"'; # 順位表順位
$H2::bgNameCell = 'BGCOLOR="#ccffff"'; # 順位表島の名前
$H2::bgInfoCell = 'BGCOLOR="#ccffff"'; # 順位表島の情報
$H2::bgCommentCell = 'BGCOLOR="#ccffcc"'; # 順位表コメント欄
$H2::bgInputCell = 'BGCOLOR="#ccffcc"'; # 開発計画フォーム
$H2::bgMapCell = 'BGCOLOR="#ccffcc"'; # 開発計画地図
$H2::bgCommandCell = 'BGCOLOR="#ccffcc"'; # 開発計画入力済み計画
#----------------------------------------------------------------------
# 好みによって設定する部分は以上
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# これ以降のスクリプトは、変更されることを想定していませんが、
# いじってもかまいません。
# コマンドの名前、値段などは解りやすいと思います。
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# 各種定数
#----------------------------------------------------------------------
# このファイル
$H2::thisFile = "$baseDir/hako-main.cgi";
# 地形番号
$H2::landSea = 0; # 海
$H2::landWaste = 1; # 荒地
$H2::landPlains = 2; # 平地
$H2::landTown = 3; # 町系
$H2::landForest = 4; # 森
$H2::landFarm = 5; # 農場
$H2::landFactory = 6; # 工場
$H2::landBase = 7; # ミサイル基地
$H2::landDefence = 8; # 防衛施設
$H2::landMountain = 9; # 山
$H2::landMonster = 10; # 怪獣
$H2::landSbase = 11; # 海底基地
$H2::landOil = 12; # 海底油田
$H2::landMonument = 13; # 記念碑
$H2::landHaribote = 14; # ハリボテ
# コマンド
$H2::commandTotal = 28; # コマンドの種類
# 計画番号の設定
# 整地系
$H2::comPrepare = 01; # 整地
$H2::comPrepare2 = 02; # 地ならし
$H2::comReclaim = 03; # 埋め立て
$H2::comDestroy = 04; # 掘削
$H2::comSellTree = 05; # 伐採
# 作る系
$H2::comPlant = 11; # 植林
$H2::comFarm = 12; # 農場整備
$H2::comFactory = 13; # 工場建設
$H2::comMountain = 14; # 採掘場整備
$H2::comBase = 15; # ミサイル基地建設
$H2::comDbase = 16; # 防衛施設建設
$H2::comSbase = 17; # 海底基地建設
$H2::comMonument = 18; # 記念碑建造
$H2::comHaribote = 19; # ハリボテ設置
# 発射系
$H2::comMissileNM = 31; # ミサイル発射
$H2::comMissilePP = 32; # PPミサイル発射
$H2::comMissileST = 33; # STミサイル発射
$H2::comMissileLD = 34; # 陸地破壊弾発射
$H2::comSendMonster = 35; # 怪獣派遣
# 運営系
$H2::comDoNothing = 41; # 資金繰り
$H2::comSell = 42; # 食料輸出
$H2::comMoney = 43; # 資金援助
$H2::comFood = 44; # 食料援助
$H2::comPropaganda = 45; # 誘致活動
$H2::comGiveup = 46; # 島の放棄
# 自動入力系
$H2::comAutoPrepare = 61; # フル整地
$H2::comAutoPrepare2 = 62; # フル地ならし
$H2::comAutoDelete = 63; # 全コマンド消去
# 順番
@H2::comList =
($H2::comPrepare, $H2::comSell, $H2::comPrepare2, $H2::comReclaim, $H2::comDestroy,
$H2::comSellTree, $H2::comPlant, $H2::comFarm, $H2::comFactory, $H2::comMountain,
$H2::comBase, $H2::comDbase, $H2::comSbase, $H2::comMonument, $H2::comHaribote,
$H2::comMissileNM, $H2::comMissilePP,
$H2::comMissileST, $H2::comMissileLD, $H2::comSendMonster, $H2::comDoNothing,
$H2::comMoney, $H2::comFood, $H2::comPropaganda, $H2::comGiveup,
$H2::comAutoPrepare, $H2::comAutoPrepare2, $H2::comAutoDelete);
# 計画の名前と値段
$H2::comName[$H2::comPrepare] = '整地';
$H2::comCost[$H2::comPrepare] = 5;
$H2::comName[$H2::comPrepare2] = '地ならし';
$H2::comCost[$H2::comPrepare2] = 100;
$H2::comName[$H2::comReclaim] = '埋め立て';
$H2::comCost[$H2::comReclaim] = 150;
$H2::comName[$H2::comDestroy] = '掘削';
$H2::comCost[$H2::comDestroy] = 200;
$H2::comName[$H2::comSellTree] = '伐採';
$H2::comCost[$H2::comSellTree] = 0;
$H2::comName[$H2::comPlant] = '植林';
$H2::comCost[$H2::comPlant] = 50;
$H2::comName[$H2::comFarm] = '農場整備';
$H2::comCost[$H2::comFarm] = 20;
$H2::comName[$H2::comFactory] = '工場建設';
$H2::comCost[$H2::comFactory] = 100;
$H2::comName[$H2::comMountain] = '採掘場整備';
$H2::comCost[$H2::comMountain] = 300;
$H2::comName[$H2::comBase] = 'ミサイル基地建設';
$H2::comCost[$H2::comBase] = 300;
$H2::comName[$H2::comDbase] = '防衛施設建設';
$H2::comCost[$H2::comDbase] = 800;
$H2::comName[$H2::comSbase] = '海底基地建設';
$H2::comCost[$H2::comSbase] = 8000;
$H2::comName[$H2::comMonument] = '記念碑建造';
$H2::comCost[$H2::comMonument] = 9999;
$H2::comName[$H2::comHaribote] = 'ハリボテ設置';
$H2::comCost[$H2::comHaribote] = 1;
$H2::comName[$H2::comMissileNM] = 'ミサイル発射';
$H2::comCost[$H2::comMissileNM] = 20;
$H2::comName[$H2::comMissilePP] = 'PPミサイル発射';
$H2::comCost[$H2::comMissilePP] = 50;
$H2::comName[$H2::comMissileST] = 'STミサイル発射';
$H2::comCost[$H2::comMissileST] = 50;
$H2::comName[$H2::comMissileLD] = '陸地破壊弾発射';
$H2::comCost[$H2::comMissileLD] = 100;
$H2::comName[$H2::comSendMonster] = '怪獣派遣';
$H2::comCost[$H2::comSendMonster] = 3000;
$H2::comName[$H2::comDoNothing] = '資金繰り';
$H2::comCost[$H2::comDoNothing] = 0;
$H2::comName[$H2::comSell] = '食料輸出';
$H2::comCost[$H2::comSell] = -100;
$H2::comName[$H2::comMoney] = '資金援助';
$H2::comCost[$H2::comMoney] = 100;
$H2::comName[$H2::comFood] = '食料援助';
$H2::comCost[$H2::comFood] = -100;
$H2::comName[$H2::comPropaganda] = '誘致活動';
$H2::comCost[$H2::comPropaganda] = 1000;
$H2::comName[$H2::comGiveup] = '島の放棄';
$H2::comCost[$H2::comGiveup] = 0;
$H2::comName[$H2::comAutoPrepare] = '整地自動入力';
$H2::comCost[$H2::comAutoPrepare] = 0;
$H2::comName[$H2::comAutoPrepare2] = '地ならし自動入力';
$H2::comCost[$H2::comAutoPrepare2] = 0;
$H2::comName[$H2::comAutoDelete] = '全計画を白紙撤回';
$H2::comCost[$H2::comAutoDelete] = 0;
#----------------------------------------------------------------------
# 変数
#----------------------------------------------------------------------
# COOKIE
my($defaultID); # 島の名前
my($defaultTarget); # ターゲットの名前
# 島の座標数
$H2::pointNumber = $H2::islandSize * $H2::islandSize;
#----------------------------------------------------------------------
# メイン
#----------------------------------------------------------------------
# jcode.plをrequire
require($jcode);
# 「戻る」リンク
$H2::tempBack = "${H2::tagBig_}トップへ戻る${H2::_tagBig} ";
# ロックをかける
if(!hakolock()) {
# ロック失敗
# ヘッダ出力
tempHeader();
# ロック失敗メッセージ
tempLockFail();
# フッタ出力
tempFooter();
# 終了
exit(0);
}
# 乱数の初期化
srand;
# COOKIE読みこみ
cookieInput();
# CGI読みこみ
cgiInput();
# 島データの読みこみ
if(readIslandsFile($H2::currentID) == 0) {
unlock();
tempHeader();
tempNoDataFile();
tempFooter();
exit(0);
}
# COOKIE出力
cookieOutput();
# テンプレートを初期化
tempInitialize();
# ヘッダ出力
tempHeader();
if($H2::mainMode eq 'turn') {
# ターン進行
require('hako-turn.cgi');
require('hako-top.cgi');
turnMain();
} elsif($H2::mainMode eq 'new') {
# 島の新規作成
require('hako-turn.cgi');
require('hako-map.cgi');
newIslandMain();
} elsif($H2::mainMode eq 'print') {
# 観光モード
require('hako-map.cgi');
printIslandMain();
} elsif($H2::mainMode eq 'owner') {
# 開発モード
require('hako-map.cgi');
ownerMain();
} elsif($H2::mainMode eq 'command') {
# コマンド入力モード
require('hako-map.cgi');
commandMain();
} elsif($H2::mainMode eq 'comment') {
# コメント入力モード
require('hako-map.cgi');
commentMain();
} elsif($H2::mainMode eq 'lbbs') {
# ローカル掲示板モード
require('hako-map.cgi');
localBbsMain();
} elsif($H2::mainMode eq 'change') {
# 情報変更モード
require('hako-turn.cgi');
require('hako-top.cgi');
changeMain();
} else {
# その他の場合はトップページモード
require('hako-top.cgi');
topPageMain();
}
# フッタ出力
tempFooter();
# 終了
exit(0);
# コマンドを前にずらす
sub slideFront {
my($command, $number) = @_;
my($i);
# それぞれずらす
splice(@$command, $number, 1);
# 最後に資金繰り
$command->[$H2::commandMax - 1] = {
'kind' => $H2::comDoNothing,
'target' => 0,
'x' => 0,
'y' => 0,
'arg' => 0
};
}
# コマンドを後にずらす
sub slideBack {
my($command, $number) = @_;
my($i);
# それぞれずらす
return if $number == $#$command;
pop(@$command);
splice(@$command, $number, 0, $command->[$number]);
}
#----------------------------------------------------------------------
# 島データ入出力
#----------------------------------------------------------------------
# 全島データ読みこみ
sub readIslandsFile {
my($num) = @_; # 0だと地形読みこまず
# -1だと全地形を読む
# 番号だとその島の地形だけは読みこむ
# データファイルを開く
if(!open(IN, "${H2::dirName}/hakojima.dat")) {
return 0;
}
# 各パラメータの読みこみ
$H2::islandTurn = int(); # ターン数
if($H2::islandTurn == 0) {
return 0;
}
$H2::islandLastTime = int(); # 最終更新時間
if($H2::islandLastTime == 0) {
return 0;
}
$H2::islandNumber = int(); # 島の総数
$H2::islandNextID = int(); # 次に割り当てるID
# ターン処理判定
my($now) = time;
if((($H2::debug == 1) &&
($H2::mainMode eq 'H2::debugturn')) ||
(($now - $H2::islandLastTime) >= $H2::unitTime)) {
$H2::mainMode = 'turn';
$num = -1; # 全島読みこむ
}
# 島の読みこみ
my($i);
for($i = 0; $i < $H2::islandNumber; $i++) {
$H2::islands[$i] = readIsland($num);
$H2::idToNumber{$H2::islands[$i]->{'id'}} = $i;
}
# ファイルを閉じる
close(IN);
return 1;
}
# 島ひとつ読みこみ
sub readIsland {
my($num) = @_;
my($name, $id, $prize, $absent, $comment, $password, $money, $food,
$pop, $area, $farm, $factory, $mountain);
$name = ; # 島の名前
chomp($name);
$id = int(); # ID番号
$prize = ; # 受賞
chomp($prize);
$absent = int(); # 連続資金繰り数
$comment = ; # コメント
chomp($comment);
$password = ; # 暗号化パスワード
chomp($password);
$money = int(); # 資金
$food = int(); # 食料
$pop = int(); # 人口
$area = int(); # 広さ
$farm = int(); # 農場
$factory = int(); # 工場
$mountain = int(); # 採掘場
# H2::idToNameテーブルへ保存
$H2::idToName{$id} = $name; #
# 地形
my(@land, @landValue, $line, @command, @lbbs);
if(($num == -1) || ($num == $id)) {
open(IIN, "${H2::dirName}/island.$id");
my($x, $y);
for($y = 0; $y < $H2::islandSize; $y++) {
$line = ;
for($x = 0; $x < $H2::islandSize; $x++) {
$line =~ s/^(.)(..)//;
$land[$x][$y] = hex($1);
$landValue[$x][$y] = hex($2);
}
}
# コマンド
my($i);
for($i = 0; $i < $H2::commandMax; $i++) {
$line = ;
$line =~ /^([0-9]*),([0-9]*),([0-9]*),([0-9]*),([0-9]*)$/;
$command[$i] = {
'kind' => int($1),
'target' => int($2),
'x' => int($3),
'y' => int($4),
'arg' => int($5)
}
}
# ローカル掲示板
for($i = 0; $i < $H2::lbbsMax; $i++) {
$line = ;
chomp($line);
$lbbs[$i] = $line;
}
close(IIN);
}
# 島型にして返す
return {
'name' => $name,
'id' => $id,
'prize' => $prize,
'absent' => $absent,
'comment' => $comment,
'password' => $password,
'money' => $money,
'food' => $food,
'pop' => $pop,
'area' => $area,
'farm' => $farm,
'factory' => $factory,
'mountain' => $mountain,
'land' => \@land,
'landValue' => \@landValue,
'command' => \@command,
'lbbs' => \@lbbs,
};
}
# 全島データ書き込み
sub writeIslandsFile {
my($num) = @_;
# ファイルを開く
open(OUT, ">${H2::dirName}/hakojima.dat");
# 各パラメータ書き込み
print OUT "$H2::islandTurn\n";
print OUT "$H2::islandLastTime\n";
print OUT "$H2::islandNumber\n";
print OUT "$H2::islandNextID\n";
# 島の書きこみ
my($i);
for($i = 0; $i < $H2::islandNumber; $i++) {
writeIsland($H2::islands[$i], $num);
}
# ファイルを閉じる
close(OUT)
}
# 島ひとつ書き込み
sub writeIsland {
my($island, $num) = @_;
print OUT $island->{'name'} . "\n";
print OUT $island->{'id'} . "\n";
print OUT $island->{'prize'} . "\n";
print OUT $island->{'absent'} . "\n";
print OUT $island->{'comment'} . "\n";
print OUT $island->{'password'} . "\n";
print OUT $island->{'money'} . "\n";
print OUT $island->{'food'} . "\n";
print OUT $island->{'pop'} . "\n";
print OUT $island->{'area'} . "\n";
print OUT $island->{'farm'} . "\n";
print OUT $island->{'factory'} . "\n";
print OUT $island->{'mountain'} . "\n";
# 地形
if(($num <= -1) || ($num == $island->{'id'})) {
open(IOUT, ">${H2::dirName}/island.$island->{'id'}");
my($land, $landValue);
$land = $island->{'land'};
$landValue = $island->{'landValue'};
my($x, $y);
for($y = 0; $y < $H2::islandSize; $y++) {
for($x = 0; $x < $H2::islandSize; $x++) {
printf IOUT ("%x%02x", $land->[$x][$y], $landValue->[$x][$y]);
}
print IOUT "\n";
}
# コマンド
my($command, $cur, $i);
$command = $island->{'command'};
for($i = 0; $i < $H2::commandMax; $i++) {
printf IOUT ("%d,%d,%d,%d,%d\n",
$command->[$i]->{'kind'},
$command->[$i]->{'target'},
$command->[$i]->{'x'},
$command->[$i]->{'y'},
$command->[$i]->{'arg'}
);
}
# ローカル掲示板
my($lbbs);
$lbbs = $island->{'lbbs'};
for($i = 0; $i < $H2::lbbsMax; $i++) {
print IOUT $lbbs->[$i] . "\n";
}
close(IOUT);
}
}
#----------------------------------------------------------------------
# 入出力
#----------------------------------------------------------------------
# 標準出力への出力
sub out {
print STDOUT jcode::sjis($_[0]);
}
# デバッグログ
sub H2::debugOut {
open(DOUT, ">>debug.log");
print DOUT ($_[0]);
close(DOUT);
}
# CGIの読みこみ
sub cgiInput {
my($line, $getLine);
# 入力を受け取って日本語コードをEUCに
$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;
# GETのやつも受け取る
$getLine = $ENV{'QUERY_STRING'};
# 対象の島
if($line =~ /CommandButton([0-9]+)=/) {
# コマンド送信ボタンの場合
$H2::currentID = $1;
$defaultID = $1;
}
if($line =~ /ISLANDNAME=([^\&]*)\&/){
# 名前指定の場合
$H2::currentName = cutColumn($1, 32);
}
if($line =~ /ISLANDID=([0-9]+)\&/){
# その他の場合
$H2::currentID = $1;
$defaultID = $1;
}
# パスワード
if($line =~ /OLDPASS=([^\&]*)\&/) {
$H2::oldPassword = $1;
$H2::defaultPassword = $1;
}
if($line =~ /PASSWORD=([^\&]*)\&/) {
$H2::inputPassword = $1;
$H2::defaultPassword = $1;
}
if($line =~ /PASSWORD2=([^\&]*)\&/) {
$H2::inputPassword2 = $1;
}
# メッセージ
if($line =~ /MESSAGE=([^\&]*)\&/) {
$H2::message = cutColumn($1, 80);
}
# ローカル掲示板
if($line =~ /LBBSNAME=([^\&]*)\&/) {
$H2::lbbsName = $1;
$H2::defaultName = $1;
}
if($line =~ /LBBSMESSAGE=([^\&]*)\&/) {
$H2::lbbsMessage = cutColumn($1, 80);
}
# main modeの取得
if($line =~ /TurnButton/) {
if($H2::debug == 1) {
$H2::mainMode = 'H2::debugturn';
}
} elsif($line =~ /OwnerButton/) {
$H2::mainMode = 'owner';
} elsif($getLine =~ /Sight=([0-9]*)/) {
$H2::mainMode = 'print';
$H2::currentID = $1;
} elsif($line =~ /NewIslandButton/) {
$H2::mainMode = 'new';
} elsif($line =~ /LbbsButton(..)([0-9]*)/) {
$H2::mainMode = 'lbbs';
if($1 eq 'SS') {
# 観光者
$H2::lbbsMode = 0;
} elsif($1 eq 'OW') {
# 島主
$H2::lbbsMode = 1;
} else {
# 削除
$H2::lbbsMode = 2;
}
$H2::currentID = $2;
# 削除かもしれないので、番号を取得
$line =~ /NUMBER=([^\&]*)\&/;
$H2::commandPlanNumber = $1;
} elsif($line =~ /ChangeInfoButton/) {
$H2::mainMode = 'change';
} elsif($line =~ /MessageButton([0-9]*)/) {
$H2::mainMode = 'comment';
$H2::currentID = $1;
} elsif($line =~ /CommandButton/) {
$H2::mainMode = 'command';
# コマンドモードの場合、コマンドの取得
$line =~ /NUMBER=([^\&]*)\&/;
$H2::commandPlanNumber = $1;
$line =~ /COMMAND=([^\&]*)\&/;
$H2::commandKind = $1;
$H2::defaultKind = $1;
$line =~ /AMOUNT=([^\&]*)\&/;
$H2::commandArg = $1;
$line =~ /TARGETID=([^\&]*)\&/;
$H2::commandTarget = $1;
$defaultTarget = $1;
$line =~ /POINTX=([^\&]*)\&/;
$H2::commandX = $1;
$H2::defaultX = $1;
$line =~ /POINTY=([^\&]*)\&/;
$H2::commandY = $1;
$H2::defaultY = $1;
$line =~ /COMMANDMODE=(write|insert|delete)/;
$H2::commandMode = $1;
} else {
$H2::mainMode = 'top';
}
}
#cookie入力
sub cookieInput {
my($cookie);
$cookie = jcode::euc($ENV{'HTTP_COOKIE'});
if($cookie =~ /${H2::thisFile}OWNISLANDID=\(([^\)]*)\)/) {
$defaultID = $1;
}
if($cookie =~ /${H2::thisFile}OWNISLANDPASSWORD=\(([^\)]*)\)/) {
$H2::defaultPassword = $1;
}
if($cookie =~ /${H2::thisFile}TARGETISLANDID=\(([^\)]*)\)/) {
$defaultTarget = $1;
}
if($cookie =~ /${H2::thisFile}LBBSNAME=\(([^\)]*)\)/) {
$H2::defaultName = $1;
}
if($cookie =~ /${H2::thisFile}POINTX=\(([^\)]*)\)/) {
$H2::defaultX = $1;
}
if($cookie =~ /${H2::thisFile}POINTY=\(([^\)]*)\)/) {
$H2::defaultY = $1;
}
if($cookie =~ /${H2::thisFile}KIND=\(([^\)]*)\)/) {
$H2::defaultKind = $1;
}
}
#cookie出力
sub cookieOutput {
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";
$cookie = '';
if(($H2::currentID) && ($H2::mainMode eq 'owner')){
$cookie .= "Set-Cookie: ${H2::thisFile}OWNISLANDID=($H2::currentID) $info";
}
if($H2::inputPassword) {
$cookie .= "Set-Cookie: ${H2::thisFile}OWNISLANDPASSWORD=($H2::inputPassword) $info";
}
if($H2::commandTarget) {
$cookie .= "Set-Cookie: ${H2::thisFile}TARGETISLANDID=($H2::commandTarget) $info";
}
if($H2::lbbsName) {
$cookie .= "Set-Cookie: ${H2::thisFile}LBBSNAME=($H2::lbbsName) $info";
}
if($H2::commandX) {
$cookie .= "Set-Cookie: ${H2::thisFile}POINTX=($H2::commandX) $info";
}
if($H2::commandY) {
$cookie .= "Set-Cookie: ${H2::thisFile}POINTY=($H2::commandY) $info";
}
if($H2::commandKind) {
# 自動系以外
$cookie .= "Set-Cookie: ${H2::thisFile}KIND=($H2::commandKind) $info";
}
out($cookie);
}
#----------------------------------------------------------------------
# ユーティリティ
#----------------------------------------------------------------------
sub hakolock {
if($lockMode == 1) {
# directory式ロック
return hakolock1();
} elsif($lockMode == 2) {
# flock式ロック
return hakolock2();
} elsif($lockMode == 3) {
# symlink式ロック
return hakolock3();
} else {
# 通常ファイル式ロック
return hakolock4();
}
}
sub hakolock1 {
# ロックを試す
if(mkdir('hakojimalock', $H2::dirMode)) {
# 成功
return 1;
} else {
# 失敗
my($b) = (stat('hakojimalock'))[9];
if(($b > 0) && ((time() - $b)> $unlockTime)) {
# 強制解除
unlock();
# ヘッダ出力
tempHeader();
# 強制解除メッセージ
tempUnlock();
# フッタ出力
tempFooter();
# 終了
exit(0);
}
return 0;
}
}
sub hakolock2 {
open(LOCKID, '>hakojimalockflock');
if(flock(LOCKID, 2)) {
# 成功
return 1;
} else {
# 失敗
return 0;
}
}
sub hakolock3 {
# ロックを試す
if(symlink('hakojimalockdummy', 'hakojimalock')) {
# 成功
return 1;
} else {
# 失敗
my($b) = (stat('hakojimalock'))[9];
if(($b > 0) && ((time() - $b)> $unlockTime)) {
# 強制解除
unlock();
# ヘッダ出力
tempHeader();
# 強制解除メッセージ
tempUnlock();
# フッタ出力
tempFooter();
# 終了
exit(0);
}
return 0;
}
}
sub hakolock4 {
# ロックを試す
if(unlink('key-free')) {
# 成功
open(OUT, '>key-locked');
print OUT time;
close(OUT);
return 1;
} else {
# ロック時間チェック
if(!open(IN, 'key-locked')) {
return 0;
}
my($t);
$t = ;
close(IN);
if(($t != 0) && (($t + 120) < time)) {
# 120秒以上経過してたら、強制的にロックを外す
unlock();
# ヘッダ出力
tempHeader();
# 強制解除メッセージ
tempUnlock();
# フッタ出力
tempFooter();
# 終了
exit(0);
}
return 0;
}
}
# ロックを外す
sub unlock {
if($lockMode == 1) {
# directory式ロック
rmdir('hakojimalock');
} elsif($lockMode == 2) {
# flock式ロック
unlink('hakojimalockflock');
close(LOCKID);
} elsif($lockMode == 3) {
# symlink式ロック
unlink('hakojimalock');
} else {
# 通常ファイル式ロック
my($i);
$i = rename('key-locked', 'key-free');
}
}
# 小さい方を返す
sub min {
return ($_[0] < $_[1]) ? $_[0] : $_[1];
}
# パスワードエンコード
sub encode {
if($cryptOn == 1) {
return crypt($_[0], 'h2');
} else {
return $_[0];
}
}
# パスワードチェック
sub checkPassword {
my($p1, $p2) = @_;
# nullチェック
if($p2 eq '') {
return 0;
}
# マスターパスワードチェック
if($masterPassword eq $p2) {
return 1;
}
# 本来のチェック
if($p1 eq encode($p2)) {
return 1;
}
return 0;
}
# 1000億単位丸めルーチン
sub aboutMoney {
my($m) = @_;
if($m < 500) {
return "推定500${H2::unitMoney}未満";
} else {
$m = int(($m + 500) / 1000);
return "推定${m}000${H2::unitMoney}";
}
}
# エスケープ文字の処理
sub htmlEscape {
my($s) = @_;
$s =~ s/&/&/g;
$s =~ s/
$s =~ s/>/>/g;
$s =~ s/\"/"/g; #"
return $s;
}
# 80ケタに切り揃え
sub cutColumn {
my($s, $c) = @_;
if(length($s) <= $c) {
return $s;
} else {
# 合計80ケタになるまで切り取り
my($ss) = '';
my($count) = 0;
while($count < $c) {
$s =~ s/(^[\x80-\xFF][\x80-\xFF])|(^[\x00-\x7F])//;
if($1) {
$ss .= $1;
$count ++;
} else {
$ss .= $2;
}
$count ++;
}
return $ss;
}
}
# 島の名前から番号を得る(IDじゃなくて番号)
sub nameToNumber {
my($name) = @_;
# 全島から探す
my($i);
for($i = 0; $i < $H2::islandNumber; $i++) {
if($H2::islands[$i]->{'name'} eq $name) {
return $i;
}
}
# 見つからなかった場合
return -1;
}
# 怪獣の情報
sub monsterSpec {
my($lv) = @_;
# 種類
my($kind) = int($lv / 10);
# 名前
my($name);
$name = $H2::monsterName[$kind];
# 体力
my($hp) = $lv - ($kind * 10);
return ($kind, $name, $hp);
}
# 経験地からレベルを算出
sub expToLevel {
my($kind, $exp) = @_;
my($i);
if($kind == $H2::landBase) {
# ミサイル基地
for($i = $maxBaseLevel; $i > 1; $i--) {
if($exp >= $baseLevelUp[$i - 2]) {
return $i;
}
}
return 1;
} else {
# 海底基地
for($i = $maxSBaseLevel; $i > 1; $i--) {
if($exp >= $sBaseLevelUp[$i - 2]) {
return $i;
}
}
return 1;
}
}
# (0,0)から(size - 1, size - 1)までの数字が一回づつ出てくるように
# (@H2::rpx, @H2::rpy)を設定
sub makeRandomPointArray {
# 初期値
my($y);
@H2::rpx = (0..$H2::islandSize-1) x $H2::islandSize;
for($y = 0; $y < $H2::islandSize; $y++) {
push(@H2::rpy, ($y) x $H2::islandSize);
}
# シャッフル
my ($i);
for ($i = $H2::pointNumber; --$i; ) {
my($j) = int(rand($i+1));
if($i == $j) { next; }
@H2::rpx[$i,$j] = @H2::rpx[$j,$i];
@H2::rpy[$i,$j] = @H2::rpy[$j,$i];
}
}
# 0から(n - 1)の乱数
sub random {
return int(rand(1) * $_[0]);
}
#----------------------------------------------------------------------
# ログ表示
#----------------------------------------------------------------------
# ファイル番号指定でログ表示
sub logFilePrint {
my($fileNumber, $id, $mode) = @_;
open(LIN, "${H2::dirName}/hakojima.log$_[0]");
my($line, $m, $turn, $id1, $id2, $message);
while($line = ) {
$line =~ /^([0-9]*),([0-9]*),([0-9]*),([0-9]*),(.*)$/;
($m, $turn, $id1, $id2, $message) = ($1, $2, $3, $4, $5);
# 機密関係
if($m == 1) {
if(($mode == 0) || ($id1 != $id)) {
# 機密表示権利なし
next;
}
$m = '(機密) ';
} else {
$m = '';
}
# 表示的確か
if($id != 0) {
if(($id != $id1) &&
($id != $id2)) {
next;
}
}
# 表示
out("${H2::tagNumber_}ターン$turn$m${H2::_tagNumber}:$message \n");
}
close(LIN);
}
#----------------------------------------------------------------------
# テンプレート
#----------------------------------------------------------------------
# 初期化
sub tempInitialize {
# 島セレクト(デフォルト自分)
$H2::islandList = getIslandList($defaultID);
$H2::targetList = getIslandList($defaultTarget);
}
# 島データのプルダウンメニュー用
sub getIslandList {
my($select) = @_;
my($list, $name, $id, $s, $i);
#島リストのメニュー
$list = '';
for($i = 0; $i < $H2::islandNumber; $i++) {
$name = $H2::islands[$i]->{'name'};
$id = $H2::islands[$i]->{'id'};
if($id eq $select) {
$s = 'SELECTED';
} else {
$s = '';
}
$list .=
"${name}島\n";
}
return $list;
}
# ヘッダ
sub tempHeader {
out(<
Content-type: text/html
$H2::title
箱庭諸島スクリプト配布元
END
}
# フッタ
sub tempFooter {
out(<
管理者:$adminName($email )
掲示板($bbs )
トップページ($toppage )
箱庭諸島のページ(http://www.bekkoame.ne.jp/~tokuoka/hakoniwa.html )
END
}
# ロック失敗
sub tempLockFail {
# タイトル
out(<
${H2::tagBig_}同時アクセスエラーです。
ブラウザの「戻る」ボタンを押し、
しばらく待ってから再度お試し下さい。${H2::_tagBig}$H2::tempBack
END
}
# 強制解除
sub tempUnlock {
# タイトル
out(<
${H2::tagBig_}前回のアクセスが異常終了だったようです。
ロックを強制解除しました。${H2::_tagBig}$H2::tempBack
END
}
# hakojima.datがない
sub tempNoDataFile {
out(<
${H2::tagBig_}データファイルが開けません。${H2::_tagBig}$H2::tempBack
END
}
# パスワード間違い
sub tempWrongPassword {
out(<
${H2::tagBig_}パスワードが違います。${H2::_tagBig}$H2::tempBack
END
}
# 何か問題発生
sub tempProblem {
out(<
${H2::tagBig_}問題発生、とりあえず戻ってください。${H2::_tagBig}$H2::tempBack
END
}
0