人狼四国カスタマイズメモ(ruby)

これをどのカテゴリに入れていいか迷うところだけど、rubyの勉強という意味でIT系に入れておきます。人狼四国(ソース)で1日目の夜(鏡を見た直後の夜)を作るメモ。


■四国スクリプト概要

四国スクリプトの大本のファイルはrootのindex.rb。これが細部の動きを制御しているその他の.rbファイルを参照している。

index.rb 1行目~
#!/usr/bin/env ruby
$KCODE = "EUC"
require 'cgi'
require 'config'
require 'login'
require 'player'
require 'vil'
require 'skill'
require 'util'
require 'catalog'
require 'errormsg'
require 'tsslock'
require 'tss'

村関連の動きはvil.rbで制御しているっぽい。

index.rb 444行目~
def handle_update	# updateをhandleするという分かりやすい定義
move = @vildb.transaction do
vil = get_vil(@vid)
vil.update(@cgi['nocnt'] == '1')	#vil.rbの中のupdateを参照する
(vil.state == 4)	#vil.state == 4 →村終了
end
if (move)
print "Status Code: 302 Moved Temporary\n"
print "Location: log_#{@vid}_#{0}.html\n\n"
exit(0)
end
end

vil.rbの中身も合わせて確認する。

vil.rb 711行目~
# 時間切れ判定定義
def up_uptime(period = @period)
now = Time.now.to_i		# 現在の秒数を数値で取得
if (@update_time && @update_time < now) # 時間切れ判定。
@update_time += period * 60	# @update_time < now == TRUE
else
@update_time = now + period * 60	# @update_time < now == FALSE
end
end
# 昼終了時の更新動作について定義
def day_update
@night = true	# 夜モード == TRUE
up_uptime(@night_period)	# 夜タイマースタート
@date += 1	# 日付カウントアップ
addlog('')
if (@date >= 3)	# 投票動作
up_vote
end
up_resetcnt	# 発言数リセット
up_resetcommit	# コミット解除
up_gameover	# ゲーム終了判定
end
# 夜終了時の更新動作について定義
def night_update
@night = false	# 夜モード == FALSE (昼モード)
up_uptime	# 昼タイマースタート
vanish =
if (@date >= 2)
up_fortune	# 占い
end
if (@date >= 2)
up_attack(vanish)	# 襲撃
end
up_gameover	# ゲーム終了判定
if (@state == 3)
return
end
if (@date == 2)
up_gertdie	# ダミー死亡
end
if (@date != 1)
up_showlives	# 生存者表示
end
up_reset	# 投票解除
up_resetcommit	# コミット解除
end
# 夜なしモードの更新動作について定義
def allday_update
up_uptime	# 昼タイマースタート
@date += 1	# 日付カウントアップ
# opening
if (@date == 1)
up_mirror	# 初日処理
end
if (@date >= 3)
up_vote	# 投票
end
vanish =
if (@date >= 2)
up_fortune	# 占い
end
if (@date >= 2)
up_attack(vanish)	# 襲撃
end
up_resetcnt	# 発言数リセット
up_gameover	# ゲーム終了判定
if (@state == 3)
return
end
if (@date == 2)
up_gertdie	# ダミー死亡
end
if (@date != 1)
up_showlives	# 生存者表示
end
up_reset	# 投票解除
up_resetcommit	# コミット解除
end
# 更新管理大元(index.rbの呼び出し先)
def update(nocnt)
if (@state == 4)	# 村終了の場合(動作無効)
return
end
if (@state == 3)	# エピの場合
do_end(nocnt)
@update_time = Time.now.to_i
@state = 4	# 村終了にする
return
end
if (@night_period)	# 夜ありの場合
if (@date == 0)	# 初日の更新の場合
allday_update
@night = false
elsif (@night)	# 夜モードONの場合
night_update
else		# 夜モードOFFの場合
day_update
end
else
allday_update
end
end

■まとめると

index.rb
└vil.update(nocnt)
 ├[夜なし]allday_update→allday_1日目昼update→allday_2日目昼update…
 └[夜あり]allday_update→→day_1日目昼update→night_2日目夜update→

となっている。

初日のallday_updateは

  def allday_update
up_uptime	# 昼タイマースタート
@date += 1	# 日付カウントアップ
# opening
if (@date == 1)
up_mirror	# 初日処理
end

より、date == 1にしてup_mirrorを実行するだけ。up_mirrorは配役の割り振りなどを決定している(動作が複雑なため割愛)。よって新たにfirst_nigth_inを定義して、初回夜の動作を確立してやればよい。

# 初日の夜
def first_night_in
@night = true	# 夜モード == TRUE
up_uptime(@night_period)	# 夜タイマースタート
@date += 1	# 日付カウントアップ
up_resetcnt	# 発言数リセット
up_mirror	# 初日処理
end
if (@night_period)	# 夜ありの場合
if (@date == 0)	# 初日の更新の場合
first_night_in	# 初日の夜
elsif (@night)	# 夜モードONの場合
night_update
else		# 夜モードOFFの場合
day_update
end
else
allday_update
end

いろいろ書いてみたがぶっちゃけよく分かってません(だからメモだって)。ソースにコメントも書いたけど理解が間違っていると思われるところも多々あり…。

■up_uptimeの動作範囲

ぶっちゃけこれのロジックは良く分かってません。が、検証の過程でvil.rbの1回の処理の間だと分かった。というのは

    if (@night_period)	# 夜ありの場合
if (@date == 0)	# 初日の更新の場合
first_night_in	# 初日の夜
first_night_update # 初回の昼
elsif (@night)	# 夜モードONの場合
night_update

と指定したとき、first_night_inをすっ飛ばしてfirst_night_updateの処理をはじめた(つまり夜が飛ばされた)。def単位でup_updateが効いていると思いこのようなロジックを組んだのだが、そうではなかった。

■参考メモ

Time.now.to_i:現在の秒を整数で返す

  • @state == 1 # =>プロローグ
  • @state == 2 # =>進行中
  • @state == 3 # =>エピローグ
  • @state == 4 # =>終了