Edited at

Ruby + Sinatra + Line Messaging api + Herokuで人狼GMbot

More than 1 year has passed since last update.


はじめに

プログラミング四ヶ月記念に何か作りたかったので作ってみた


注意点

動かすことだけを考えたコードなので本当に汚いです.

そこはご了承ください


利用したサービス

・Line Messaging API

・Ruby

・Heroku

・PostgreSQL


概要

アカウントを登録してメッセージのやりとりだけで人狼ができるbot


DataBase設定

Herokuではsqliteは使えないのでPostgreSQL


20161122080417_orta.rb

class Orta < ActiveRecord::Migration[5.0]

def change
create_table :wolf_rooms do |t|
t.integer :room_id
t.integer :status

end
create_table :room_users do |s|
s.integer :room_id
s.text :user_id
s.text :name
s.boolean :orner
s.boolean :life_status
s.integer :role
s.integer :talk_status
s.boolean :vote_state
s.boolean :ablity_state
s.text :gard_id
s.integer :get_vote
s.boolean :get_hount
s.boolean :gard_status
end
end
end



名前登録,村を作成,村に参加

処理を切り取り.

アカウントに最初に送ったメッセージがユーザー名として登録.

人数確認と送ると今村に参加しているユーザーの確認

スクリーンショット 2016-11-30 14.20.46.png


main.rb

elsif event.message['text'] == "村を作成"

room_id = rand(1..9999)
user_id = event['source']['userId']

wolf_rooms = Wolf_room.new(:room_id =>room_id,:status => 1)
wolf_rooms.save
room_users = Room_user.where(:user_id => user_id)
room_users[0].room_id = room_id
room_users[0].orner = true
room_users[0].talk_status = 2
room_users[0].save
message =text_sender("村を作成したよ\n参加させたい人に,このコードを教えてね\n[コード:#{room_id}]\n")
client.reply_message(event['replyToken'], message)
elsif event.message['text'] == "人数確認"
menber_check = Room_user.where(:user_id => event['source']['userId'])
check_count = Room_user.where(:room_id =>menber_check[0].room_id)
i = 0
checkout = Array.new
check_count.each { |x|
checkout[i] = x.name
i = i+1
}
message = text_sender("#{checkout.join("\n")}#{i}人だよ")
client.reply_message(event['replyToken'], message)
elsif event.message['text'] == "村を開始"
room_start = Room_user.where(:user_id => event['source']['userId'])
rst = Wolf_room.where(:room_id =>room_start[0].room_id)
rst[0].status = 2
rst[0].save
check_count = Room_user.where(:room_id =>room_start[0].room_id)
i = 0
checkout = Array.new
role = [0,1,2,3,4]
role.shuffle!
#役分担
check_count.each { |x|
checkout[i] = x.name
x.role = role[i]
x.save
i = i+1
}
check_anounce = Room_user.where(:room_id =>room_start[0].room_id)
j = 0

check_anounce.each { |n|
if n.role == 0
text = "この村には\n村人2人\n狩人\n占い師\n人狼\nがいます\nあなたは村人です\n投票をする時は「○○を投票する」と入力してください"
n.ablity_state = true
n.save
elsif n.role == 1
text = "この村には\n村人2人\n狩人\n占い師\n人狼\nがいます\nあなたは村人です\n投票をする時は「○○を投票する」と入力してください"
n.ablity_state = true
n.save
elsif n.role == 2
text = "この村には\n村人2人\n狩人\n占い師\n人狼\nがいます\nあなたは占い師です.夜の時間に「○○を占う」と入力してください\n投票をする時は「○○を投票する」と入力してください"
elsif n.role == 3
text = "この村には\n村人2人\n狩人\n占い師\n人狼\nがいます\nあなたは騎士です.夜の時間に「○○を守る」と入力してください\n投票をする時は「○○を投票する」と入力してください"
elsif n.role == 4
text = "この村には\n村人2人\n狩人\n占い師\n人狼\nがいます\nあなたは人狼です.夜の時間に「○○を襲う」と入力してください\n投票をする時は「○○を投票する」と入力してください"
end
message = text_sender("村が開始されました\n村人一覧\n#{checkout.join("\n")}\n\n#{text}")
client.push_message(n.user_id,message)
}



会話フェーズ開始

村を開始とおくることで自分の役割が決定し,村が開始される

スクリーンショット 2016-11-30 14.58.27.png


会話フェーズの処理について

会話フェーズはWolf_roomsのstatusとRoom_usersのtalk_statusによって判別させる.


会話フェーズ(昼)

Botにメッセージを送ると下記のような形状で送られる

○○○(名前)を投票で投票する人を確定させる.

時間を進めると発言した際に全員が投票してなければ下記の図のようになる

スクリーンショット 2016-11-30 15.11.33.png


main.rb

 if  room_status[0].status == 2

if event.message['text'] == "時間を進める"
room_hoge = Room_user.where(:user_id => event['source']['userId'] )
room_hofe = Room_user.where(:room_id =>room_hoge[0].room_id)
room_sch = Wolf_room.where(:room_id =>room_hoge[0].room_id)

vote = Array.new
co = 0
chch = 0
room_hofe.each { |x|
if x.vote_state != true
vote[co] = x.name
else
chch = chch +1
end
co = co + 1
}
if chch == 5
maxvo =Room_user.where(:room_id =>room_hoge[0].room_id).order("get_vote desc")
maxvo[0].get_vote = 0
maxvo[0].life_status = false

if maxvo[0].role == 4
message = text_sender("#{maxvo[0].name}\nが投票の結果なくなりました\n人狼が全滅しました.村人の勝利です\nもう一度名前を入力することでゲームをプレイできます")
client.reply_message(event['replyToken'], message)
Wolf_room.destroy_all(:room_id => room_hoge[0].room_id)
Room_user.destroy_all(:room_id => room_hoge[0].room_id)
else
maxvo.each { |aaa|
# aaa.talk_status = 3
# aaa.save

}
maxvo[0].talk_status = 4
maxvo[0].save
message = text_sender("#{maxvo[0].name}\nが投票の結果なくなりました\n夜の時間がやってきます")
client.reply_message(event['replyToken'], message)
room_sch[0].status = 3
room_sch[0].save

end
maxvo[0].save
else
message = text_sender("#{vote.join("\n")}\nがまだ投票してないよ")
client.reply_message(event['replyToken'], message)
end
elsif event.message['text'] =~ /を投票/
vote_check = Room_user.where(:user_id =>event['source']['userId'])
if vote_check[0].vote_state != true
event.message['text'].slice!("を投票")
puts cutname
vote_check[0].vote_state = true
vote_check[0].save
vote_one = Room_user.where(:name => event.message['text'])
vote_one[0].get_vote = vote_one[0].get_vote + 1
vote_one[0].save

elsif vote_check[0].vote_state == true
message = text_sender("#{vote_check[0].name}はすでに誰かに投票しているよ")
client.reply_message(event['replyToken'], message)
else
end
else
all_room = Room_user.where(:room_id =>room_check[0].room_id)
all_room.each {|p|
message = text_sender("#{room_check[0].name}さん\n#{event.message['text']}")
client.push_message(p.user_id,message)
}
end



会話フェーズ(夜)

時間を進めるといった際に全員が投票していた場合下記の図のように

フェーズが変わり決められた役の能力を使うことができる

スクリーンショット 2016-11-30 15.19.36.png


main.rb

elsif room_status[0].status == 3

puts "state 3"
abroom = Room_user.where(:user_id => event['source']['userId'] )
if event.message['text'] == "時間を進める"
puts "success"
froom = Room_user.where(:user_id =>event['source']['userId'])
deadroom = Room_user.where(:room_id => froom[0].room_id)
room_search = Wolf_room.where(:room_id =>froom[0].room_id)
# room_search[0].status = 4
# room_search[0].save
ablity = Array.new
cnt = 0
abch = 0
deadroom.each { |x|
if x.ablity_state != true
# ablity[co] = x.name
else
abch = abch +1
end
cnt = cnt + 1
}
if abch == 5
geth = Room_user.where(:room_id => froom[0].room_id)
geth.each { |c|
if c.get_hount == true
if c.gard_status == true
gard = Room_user.where(:user_id => c.gard_id)

gard[0].life_status = false
gard[0].life_status = false
gard[0].talk_status = 4
gard[0].save
nico = Room_user.where(:room_id => froom[0].room_id)
nico.each { |ccc|
message = text_sender("#{gard[0].name}さんが無残な姿で発見されました\n昼の話し合いを開始して,誰に投票するか決めたら「○○に投票する」と発言してください")
client.push_message(ccc.user_id,message)
if ccc.life_status == true
if ccc.role == 0
ccc.ablity_state = true
ccc.vote_state = false
elsif ccc.role == 1
ccc.ablity_state = true
ccc.vote_state = false
elsif ccc.role == 2
ccc.ablity_state = false
ccc.vote_state = false
elsif ccc.role == 3
ccc.ablity_state = false
ccc.vote_state = false
elsif ccc.role == 4
ccc.ablity_state = false
ccc.vote_state = false
else
end
else
if ccc.role == 0
ccc.ablity_state = true
ccc.vote_state = true
elsif ccc.role == 1
ccc.ablity_state = true
ccc.vote_state = true
elsif ccc.role == 2
ccc.ablity_state = true
ccc.vote_state = true
elsif ccc.role == 3
ccc.ablity_state = true
ccc.vote_state = true
elsif ccc.role == 4
ccc.ablity_state = true
ccc.vote_state = true
end

end

ccc.save
}

# gard[0].vote_state = true
# gard[0].ablity_state = true

c.get_hount = false
c.gard_status = false
c.gard_id = ""
c.save
room_search[0].status = 2
room_search[0].save
else
c.life_status =false
c.talk_status = 4
c.get_hount = false
c.save
deadroom.each { |xxx|
message = text_sender("#{c.name}さんが無残な姿で発見されました\n昼の話し合いを開始して,誰に投票するか決めたら「○○に投票する」と発言してください")
client.push_message(xxx.user_id,message)
if xxx.life_status == true
if xxx.role == 0
xxx.ablity_state = true
xxx.vote_state = false
elsif xxx.role == 1
xxx.ablity_state = true
xxx.vote_state = false
elsif xxx.role == 2
xxx.ablity_state = false
xxx.vote_state = false
elsif xxx.role == 3
xxx.ablity_state = false
xxx.vote_state = false
elsif xxx.role == 4
xxx.ablity_state = false
xxx.vote_state = false
else
end
else
if xxx.role == 0
xxx.ablity_state = true
xxx.vote_state = true
elsif xxx.role == 1
xxx.ablity_state = true
xxx.vote_state = true
elsif xxx.role == 2
xxx.ablity_state = true
xxx.vote_state = true
elsif xxx.role == 3
xxx.ablity_state = true
xxx.vote_state = true
elsif xxx.role == 4
xxx.ablity_state = true
xxx.vote_state = true
else
end

end

xxx.save
}
room_search[0].status = 2
room_search[0].save
end
else
end
}
else
#能力の未使用かな
message = text_sender("まだ行動をしていない方がいます")
client.reply_message(event['replyToken'], message)
end
else
if abroom[0].ablity_state == false
if abroom[0].role == 2
if event.message['text'] =~ /を占う/
event.message['text'].slice!("を占う")
dvineroom == Room_user.where(:name => event.message['text'])
if dvineroom[0].role == 0
message = text_sender("#{dvineroom[0].name}さんは村人です")
elsif dvineroom[0].role == 1
message = text_sender("#{dvineroom[0].name}さんは村人です")
elsif dvineroom[0].role == 3
message = text_sender("#{dvineroom[0].name}さんは騎士です")
elsif dvineroom[0].role == 4
message = text_sender("#{dvineroom[0].name}さんは人狼です")
end
astate = Room_user.where(:user_id => event['source']['userId'])
astate[0].ablity_state = true
astate[0].save
client.reply_message(event['replyToken'], message)
else

end
elsif abroom[0].role == 3
if event.message['text'] =~ /を守る/
event.message['text'].slice!("を守る")
gaurd = Room_user.where(:name => event.message['text'])
gaurd[0].gard_id = event['source']['userId']
gaurd[0].gard_status = true
gaurd[0].save
astate = Room_user.where(:user_id => event['source']['userId'])
astate[0].ablity_state = true
astate[0].save
message = text_sender("#{gaurd[0].name}を対象としました")
client.reply_message(event['replyToken'], message)
else
end
elsif abroom[0].role == 4
if event.message['text'] =~ /を襲う/
event.message['text'].slice!("を襲う")
hount = Room_user.where(:name => event.message['text'])
hount[0].get_hount = true
hount[0].save
astate = Room_user.where(:user_id => event['source']['userId'])
astate[0].ablity_state = true
astate[0].save
message = text_sender("#{hount[0].name}を対象としました")
client.reply_message(event['replyToken'], message)
else
end
else

end

#ablity_state == trueの時の処理のelse
else
if abroom[0].role == 0
message = text_sender("村人はすることはないです")
client.reply_message(event['replyToken'], message)
elsif abroom[0].role == 1
message = text_sender("村人はすることはないです")
client.reply_message(event['replyToken'], message)
else
message = text_sender("すでに行動を終えています")
client.reply_message(event['replyToken'], message)
end
end

end



会話フェーズ(二日目昼)

全員が能力をした際に時間を進めることができる.

既になくなったひとは発言することができない.

スクリーンショット 2016-11-30 15.22.04.png


まとめ

実際に動かすことができたのでとりあえずよかった.

五人しか対応してないので,今後対応人数を増やしていきたい.

リア充のみなさんぜひ飲み会の席とかで使ってください.


参考サイト

人狼GM LINE BOT

http://tsuchinoko.dmmlabs.com/?p=3668