#!/usr/bin/env ruby
require 'cgi'
require 'cgi/session'
require 'zlib'
require "xmlrpc/client"
CHOICE = [ 'アリス', 'ボブ', 'チャーリー', 'ドンキー', '降参', 'パス' ]
HUMAN = [ 'アリス', 'ボブ', 'チャーリー', 'ドンキー' ]
class HeadFoot
def initialize
File.open('hateww.html') do |ifile|
cont = ifile.read
i = cont.index('
')
@head = cont[0...i]
i = cont.index('
', i)
@foot = cont[i+6..-1]
end
end
def print_head
print @head
@head = ''
end
def print_foot
print @foot
@foot = ''
end
end
def random_keyword
File.open('keywords') do |ifile|
ifile.seek(0, IO::SEEK_END)
size = ifile.tell
ifile.seek(rand(size-10), IO::SEEK_SET)
ifile.readline
w = ifile.readline
while false
ifile.seek(rand(size-10), IO::SEEK_SET)
ifile.readline
w = ifile.readline
end
w.chomp
end
end
def relational_keywords(s)
server = XMLRPC::Client.new("d.hatena.ne.jp", "/xmlrpc")
res = server.call("hatena.getSimilarWord", {
"wordlist" => s
})
res['wordlist'].map {|v| v['word']}
end
def init_game
while true
root = random_keyword
@s['root'] = root
rels = relational_keywords(root)
next if rels.size < 4
second = rels.delete_at(rand(rels.size))
# easier
reswords = nil
tmp_rels = relational_keywords(second)
tmp_rels.delete(root)
next if tmp_rels.empty?
while true
third = tmp_rels[rand(tmp_rels.size)]
@s['second'] = third
reswords = [ second, third ]
second = third
break
end
# @s['second'] = second
# reswords = [ second ]
second_rels = relational_keywords(second)
second_rels.delete(second)
next if second_rels.empty?
p2 = 14
p3 = 8
reswords += second_rels
if second_rels.size < 3
p2 -= 1
if second_rels.size == 1
p3 -= 2
else
p3 -= 1
end
second_rels2 = relational_keywords(second_rels)
second_rels2.delete_if {|i| reswords.include?(i) }
next if second_rels.size + second_rels2.size < 4
while second_rels.size < 3
second_rels.push(second_rels2.delete_at(rand(second_rels2.size)))
end
else
while second_rels.size > 3
second_rels.delete_at(rand(second_rels.size))
end
end
# @s['second_rels'] = second_rels.dup
reswords += second_rels
rels.delete_if {|i| reswords.include?(i) }
if rels.size < 9
add = 9 - rels.size
p3 += add
if add > 3
p2 += add - 3
end
rels2 = relational_keywords(rels)
rels2.delete_if {|i| reswords.include?(i) }
next if rels.size + rels2.size < 9
while rels.size < 9
rels.push(rels2.delete_at(rand(rels2.size)))
end
else
while rels.size > 9
rels.delete_at(rand(rels.size))
end
end
# @s['rels'] = rels.dup
wolf = rand(4)
@s['wolf'] = wolf.to_s
words = []
for i in 0...3
for j in 0...4
if j == wolf
words.push(second_rels.shift)
else
words.push(rels.shift)
end
end
end
@s['words'] = words.join('|')
@s['points'] = [ '20', p2.to_s, p3.to_s ].join('|')
break
end
end
def print_truth
human = HUMAN.dup
print %Q(真相は以下の通り。
)
wolf = human.delete_at(@s['wolf'].to_i)
print %Q(ワードウルフ: #{wolf} (#{@s['second']})
)
print %Q(その他: #{human.join(',')} (#{@s['root']})
)
print_saying(2)
end
def print_saying(state)
print %Q()
words = @s['words'].split('|')
for j in 0 ... 4
a = []
for i in 0 .. state
a.push(words[i*4+j])
end
print "- #{HUMAN[j]}: #{a.join(', ')}"
end
print %Q(
)
end
@q = CGI.new
@s = CGI::Session.new(@q)
@nojs = @q['nojs'] == '1' ? HeadFoot.new : nil
print @q.header({ 'type' => 'text/html; charset=UTF-8',
'Cache-Control' => 'no-cache',
'Pragma' => 'no-cache',
})
if @nojs
@nojs.print_head
end
begin
if @q.has_key?('highscore')
hf = HeadFoot.new
hf.print_head
print "ハイスコア
"
require 'pstore'
db = PStore.new('score.db')
db.transaction(true) do
db.roots.sort do |x,y|
db[y] <=> db[x]
end.each do |i|
if i != ''
print "- #{i}: #{db[i]}"
end
end
end
print "
"
print %Q(
トップへ
)
hf.print_foot
exit(0)
elsif @q.has_key?('init')
@s['state'] = ''
elsif @q.has_key?('start')
@s['state'] = '0'
@s['score'] = '0' if @s['score'] == ''
init_game
elsif @q.has_key?('score')
if @q.has_key?('name')
@s['highscore'] = @s['record']
@s['name'] = @q['name'].to_s
require 'pstore'
db = PStore.new('score.db')
db.transaction do
name = @q['name'].to_s
score = @s['record'].to_i
prev = db[name].to_i
if score > prev
db[name] = score
else
print "既に#{prev}点という記録があったので登録されない
"
end
end
end
@s['state'] = ''
elsif @q.has_key?('choice')
if @s['state'] !~ /^\d$/
@s['state'] = ''
elsif @q.has_key?('q')
now = Time.now
prev = Time.at(@s['time'].to_i)
state = @s['state'].to_i
choice = @q['q'].to_i
point = @s['points'].split('|')[state].to_i
if now-prev > 60
@s['state'] = 'timeover'
@s['record'] = @s['score'].to_i - (20 - point)
@s['score'] = '0'
elsif choice == 4
@s['state'] = 'giveup'
@s['record'] = @s['score'].to_i - (20 - point)
@s['score'] = '0'
elsif choice == @s['wolf'].to_i
@s['state'] = 'right'
@s['score'] = @s['score'].to_i + point
@s['curpt'] = point
elsif choice != 5 || state >= 2
@s['state'] = 'wrong'
@s['record'] = @s['score'].to_i - (40 - point)
@s['score'] = '0'
else
@s['state'] = (state+1).to_s
end
else
print 'どれか選んで下さい。
'
end
end
state = @s['state'].to_s
# async = (state == '' || state == 'right').to_s
async = 'true'
print %Q(
'
if @nojs
@nojs.print_foot
end
@s['time'] = Time.now.to_i.to_s
rescue
print "なんかエラー起きた
"
print "#{$!}
"
print %Q(#{$!.backtrace.join("\n")}
)
print "リロードするとか戻るとかして下さい。
"
end