#!/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://XXXXXXXXX.XX.jp/~xxxxx/xxxxxx'; # 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//>/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 .= "