第09話:ほどほどのエージェント化とおじいさんエージェント
前回のプログラムはエージェントっぽくしたとは言え、
・認識
・判断
・行動
をエージェントがしているわけではありませんでした。
そこで、もっとちゃんとエージェント化しようとして奮闘し……力尽きました。
まず、世界として、
・少女が出しているカード
・少年が出しているカード
を用意して、
後はエージェント自身が「自分が先手か後手か」「相手がカードを出しているかいないか」で自分の番かどうか判断して行動する……
なんていうのをきっちりやろうとして、どんどん複雑になっていくことに絶望しました。
その時書いた、プログラムの一部なんですが・・・
#カードを読み込み
@mycard = w.girl_card
@enemycard = w.boy_card
#最後に勝った相手
@winner = w.getLastMessage("*","card","win","*")
#自分がカードをひっくり返せる状態か認識
@card_turnable = false
#先手かつ自分がカードを出していない
if (@sente_flag == true) && (@mycard == -1)
@card_turnable = true
#後手かつ相手がカードを出して自分がカードを出していない
elsif (@sente_flag == false) && (@enemycard != -1) && (@mycard == -1)
@card_turnable = true
end
#勝負中かどうか判定
@ingame=false
if (@mycard != -1) && (@enemycard == -1)
@ingame = true
elsif (@mycard == -1) && (@enemycard != -1)
@ingame = true
end
#アクション設定
@action = ""
#カードを出す
if (@card_turnable == true) && (sente_flag == true)
@action = "run_sente"
elsif (@card_turnable == true) && (sente_flag == false)
@action = "run_gote"
@highlow = judge(@enemycard)
elsif (@mycard != -1) && (@enemycard != -1) && (w.getLastMessage("*","card","*","*").message != "win")
@action = "eval_game"
elsif (@mycard != -1) && (@enemycard != -1) && (w.getLastMessage("*","card","*","*").message == "win")
@action = "say_result"
end
とまぁ、細かいところはわからなくていいのですが、とにかくifの塊になっています。
しかもまだ途中。
あの単純なカードゲームですら、エージェントできっちり処理しようとするとこれ以上の膨大な条件分岐になるようです。
ぬぬぬ……
これでは、此処から先いろいろなストーリーを追加していくことはとてもできそうにありません。
見通しが甘かった……orz
ゲームの敵キャラのように、「マップを巡回してプレイヤーを発見したら攻撃」みたいな行動パターンならいいのでしょうが、ストーリーの処理をエージェント式で綺麗にやろうとすると無理があるようです。
なので、完全なエージェント式は諦めました。
基本的にはメインストーリーをどかどか書いていき、細かいセリフだけをエージェント側に任せるようにしました。
今回、少年は少女の顔色を伺うようにしました。
さらに、エージェント化したおじいさんが追加されました。
さぁ、こんな結果です!
**********************************************
少年と少女は退屈していた。
少女「退屈だわ。カードで遊びましょう。先手と後手がカードを一枚ずつ取るのよ。そして、先手が数字を見せたら、後手は自分が選んだ数字が大きいか小さいか当てるのよ」
少年「うん、いいよ」
少女「私が勝ったら30ギル、あなたが勝ったら20ギルね」
少年「え、お金かけるの!? しかも、なんか不公平……」
少女「うるさいわね。まずは私が選ぶわ」
少年の所持金:100
少女の所持金:100
【1戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[9]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ロー!」
少年がカードを裏返すと、[8]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
少年の所持金:120
少女の所持金:80
【2戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[1]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ハイ!」
少女がカードを裏返すと、[2]だった!
少女「私の勝ちね!」
少女はガッツポーズを決めた。
少年「うわ、負けた……」
おじいさんが部屋に入ってきて二人の隣に座った。
少年の所持金:90
少女の所持金:110
【3戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[1]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ハイ!」
少年がカードを裏返すと、[6]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
少年の所持金:110
少女の所持金:90
【4戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[8]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ハイ!」
少女がカードを裏返すと、[5]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
少女は機嫌が悪そうだ。
少年「お、怒らないでよ……」
おじいさんが部屋に入ってきて二人の隣に座った。
少年の所持金:130
少女の所持金:70
【5戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[5]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ハイ!」
少年がカードを裏返すと、[1]だった!
少女「私の勝ちね!」
少女はガッツポーズを決めた。
少年「うわ、負けた……」
おじいさん「頑張るんじゃ少年!」
おじいさん「頑張るんじゃ少年!」
少年の所持金:100
少女の所持金:100
【6戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[4]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ハイ!」
少女がカードを裏返すと、[5]だった!
少女「私の勝ちね!」
少女はガッツポーズを決めた。
少年「うわ、負けた……」
おじいさん「頑張るんじゃ少年!」
おじいさん「頑張るんじゃ少年!」
少年の所持金:70
少女の所持金:130
【7戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[0]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ハイ!」
少年がカードを裏返すと、[2]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少年の所持金:90
少女の所持金:110
【8戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[3]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ロー!」
少女がカードを裏返すと、[4]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少女は機嫌が悪そうだ。
少年「お、怒らないでよ……」
少年の所持金:110
少女の所持金:90
【9戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[2]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ハイ!」
少年がカードを裏返すと、[7]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少年の所持金:130
少女の所持金:70
【10戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[6]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ハイ!」
少女がカードを裏返すと、[9]だった!
少女「私の勝ちね!」
少女はガッツポーズを決めた。
少年「うわ、負けた……」
おじいさん「頑張るんじゃ少年!」
おじいさん「頑張るんじゃ少年!」
少女は機嫌が悪そうだ。
少年「お、怒らないでよ……」
少年の所持金:100
少女の所持金:100
【11戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[3]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ハイ!」
少年がカードを裏返すと、[4]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少年の所持金:120
少女の所持金:80
【12戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[7]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ハイ!」
少女がカードを裏返すと、[3]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少女は機嫌が悪そうだ。
少年「お、怒らないでよ……」
少年の所持金:140
少女の所持金:60
【13戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[1]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ハイ!」
少年がカードを裏返すと、[2]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少年の所持金:160
少女の所持金:40
【14戦目】
***【先手】少年 【後手】少女***
[先手]少年がカード[9]を選んだ
少年「さぁ、選んで」
[後手]少女がカードを選んだ
少年「さぁ、ハイ or ロー?」
少女「ハイ!」
少女がカードを裏返すと、[5]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少女は機嫌が悪そうだ。
少年「お、怒らないでよ……」
少年の所持金:180
少女の所持金:20
【15戦目】
***【先手】少女 【後手】少年***
[先手]少女がカード[9]を選んだ
少女「さぁ、選びなさい」
[後手]少年がカードを選んだ
少女「さぁ、ハイ or ロー?」
少年「ロー!」
少年がカードを裏返すと、[1]だった!
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
少女「そ、そんな嘘よ……」
おじいさん「ぬおおおおお」
おじいさん「ぬおおおおお」
少女「ま、まさか私が負けるなんて。もうお金が……」
少年「ご、ごめん……」
少女「ゆ、許さないわっ」
**********************************************
なかなか賑やかになりました。
特に、エージェント化したおじいさんが二回も部屋に入ってきたことで、二人でハモっています。
ここにいろんなエージェント化していけばもっと賑やかに!?
いやいや、ハイローゲームに観客がそんないるのでしょうか?
また、次の展開を考えていきたいと思います。
今回のプログラムはこの通りです。
それなりに長いです。
#! ruby -E Windows-31J:utf-8
# coding: utf-8
#第09話:ほどほどエージェント
def init
$world = World::new
$girl = GirlAgent::new
$boy = BoyAgent::new
end
def mainstory
print <<"EOS"
**********************************************
少年と少女は退屈していた。
少女「退屈だわ。カードで遊びましょう。先手と後手がカードを一枚ずつ取るのよ。そして、先手が数字を見せたら、後手は自分が選んだ数字が大きいか小さいか当てるのよ」
少年「うん、いいよ」
少女「私が勝ったら30ギル、あなたが勝ったら20ギルね」
少年「え、お金かけるの!? しかも、なんか不公平……」
少女「うるさいわね。まずは私が選ぶわ」
EOS
count = 1
loop do
print_money
#少女先手、少年後手
puts "【"+count.to_s+"戦目】"
puts "***【先手】少女 【後手】少年***"
card1 = (rand()*10).to_i
puts "[先手]少女がカード["+card1.to_s+"]を選んだ"
puts
puts "少女「さぁ、選びなさい」"
puts
card2 = pick_card(card1)
puts "[後手]少年がカードを選んだ"
puts
puts "少女「さぁ、ハイ or ロー?」"
puts
j = $boy.judge(card1)
puts "少年「"+j+"!」"
puts
puts "少年がカードを裏返すと、["+card2.to_s+"]だった!"
puts
if gote_win?(card1,card2,j) == true
$boy.money += 20
$girl.money -= 20
m = Message::new("boy","card","win","")
$boy.talk_for(m)
$girl.talk_for(m)
$world.talk_for_byAllAgent(m)
$girl.angry += 0.3
else
$boy.money -= 30
$girl.money += 30
m = Message::new("girl","card","win","")
$girl.talk_for(m)
$boy.talk_for(m)
$world.talk_for_byAllAgent(m)
$girl.angry = 0
end
if $boy.money <= 0
puts "少年「もうお金がないよ……」"
puts
puts "少女「ふふふ、また挑戦しなさい」"
puts
puts "少年「絶対に嫌だよ……」"
break
elsif $girl.money <= 0
puts "少女「ま、まさか私が負けるなんて。もうお金が……」"
puts
puts "少年「ご、ごめん……」"
puts
puts "少女「ゆ、許さないわっ」"
break
end
count += 1
print_money
#少年先手、少女後手
puts "【"+count.to_s+"戦目】"
puts "***【先手】少年 【後手】少女***"
card1 = (rand()*10).to_i
puts "[先手]少年がカード["+card1.to_s+"]を選んだ"
puts
puts "少年「さぁ、選んで」"
puts
card2 = pick_card(card1)
puts "[後手]少女がカードを選んだ"
puts
puts "少年「さぁ、ハイ or ロー?」"
puts
j = $girl.judge(card1)
puts "少女「"+j+"!」"
puts
puts "少女がカードを裏返すと、["+card2.to_s+"]だった!"
puts
if gote_win?(card1,card2,j) == true
$boy.money -= 30
$girl.money += 30
m = Message::new("girl","card","win","")
$girl.talk_for(m)
$boy.talk_for(m)
$world.talk_for_byAllAgent(m)
$girl.angry += 0.0
else
$boy.money += 20
$girl.money -= 20
m = Message::new("boy","card","win","")
$boy.talk_for(m)
$girl.talk_for(m)
$world.talk_for_byAllAgent(m)
$girl.angry += 0.3
end
if $girl.angry > 0.5
m = Message::new("girl","emotion","angry","boy")
$girl.talk_for(m)
$boy.talk_for(m)
end
if rand() < 0.3
a = JiisanAgent::new
$world.addAgent(a)
puts "おじいさんが部屋に入ってきて二人の隣に座った。"
puts
end
#elsif rand() < 0.05
# a = Ojisan::new
# $world.addAgent(a)
#end
if $boy.money <= 0
puts "少年「もうお金がないよ……」"
puts
puts "少女「ふふふ、また挑戦しなさい」"
puts
puts "少年「絶対に嫌だよ……」"
break
elsif $girl.money <= 0
puts "少女「ま、まさか私が負けるなんて。もうお金が……」"
puts
puts "少年「ご、ごめん……」"
puts
puts "少女「ゆ、許さないわっ」"
break
end
count += 1
end
puts "**********************************************"
end
def pick_card(exclusion)
loop do
a = (rand()*10).to_i
if a != exclusion
return a
end
end
end
def gote_win?(card1,card2,judge)
if (card1 < card2) && (judge == "ハイ")
return true
elsif (card1 > card2) && (judge == "ロー")
return true
else
return false
end
end
def print_money
puts "少年の所持金:"+$boy.money.to_s
puts "少女の所持金:"+$girl.money.to_s
puts
end
def print(s)
puts s.gsub(/^ +/,"").gsub(/\n +/,"\n")
end
#環境クラス
class World
def initialize
@agent = []
end
def addAgent(a)
@agent.push(a)
end
def getAgents
return @agent
end
#すべてのエージェントが話す
def talk_for_byAllAgent(m)
for a in @agent
a.talk_for(m)
end
end
end
#メッセージ
class Message
attr_accessor :actor, :category, :message, :target
def initialize(a,c,m,t)
@actor = a
@category = c
@message = m
@target =t
end
end
#少女エージェント
class GirlAgent
attr_accessor :money
attr_accessor :angry, :sad
def initialize
@money = 100
@angry = 0.0
@sad = 0.0
end
def print(s)
puts s.gsub(/^ +/,"").gsub(/\n +/,"\n")
end
def talk_for(m)
if m.category == "card"
talk_for_card(m)
elsif m.category == "emotion"
talk_for_emotion(m)
end
end
def talk_for_card(m)
if m.message == "win"
if m.actor == "girl"
print <<"EOS"
少女「私の勝ちね!」
少女はガッツポーズを決めた。
EOS
else
print <<"EOS"
少女「そ、そんな嘘よ……」
EOS
end
end
end
def talk_for_emotion(m)
if m.actor == "girl"
talk_for_myemotion(m)
elsif (m.actor != "girl") && (m.target == "girl")
talk_for_emotion_for_girl(m)
elsif (m.actor != "girl") && (m.target != "girl")
talf_for_emotion_for_other(m)
end
end
#自分の感情
def talk_for_myemotion(m)
if m.message == "angry"
puts "少女は機嫌が悪そうだ。"
puts
end
end
#他者の少女に対する感情
def talk_for_emotion_for_girl(m)
if m.message == "angry"
print <<"EOS"
少女「なに怒ってるのかしら」
EOS
end
end
def judge(a)
if rand() < 0.5
return "ハイ"
else
return "ロー"
end
end
end
#少年エージェント
class BoyAgent
attr_accessor :money
def initialize
@money=100
end
def print(s)
puts s.gsub(/^ +/,"").gsub(/\n +/,"\n")
end
def talk_for(m)
if m.category == "card"
talk_for_card(m)
elsif m.category == "emotion"
talk_for_emotion(m)
end
end
def talk_for_card(m)
if m.message == "win"
if m.actor == "boy"
print <<"EOS"
少年「やったー! 僕の勝ちだ!」
少年は歓声を上げた。
EOS
else
print <<"EOS"
少年「うわ、負けた……」
EOS
end
end
end
def talk_for_emotion(m)
if m.actor == "boy"
talk_for_myemotion(m)
elsif (m.actor != "boy") && (m.target == "boy")
talk_for_emotion_for_boy(m)
elsif (m.actor != "boy") && (m.target != "boy")
talf_for_emotion_for_other(m)
end
end
#他者の少年に対する感情
def talk_for_emotion_for_boy(m)
if m.message == "angry"
print <<"EOS"
少年「お、怒らないでよ……」
EOS
end
end
def judge(a)
if a <= 5
#if rand() < 0.5
return "ハイ"
else
return "ロー"
end
end
end
#じいさnエージェント
class JiisanAgent
def initialize
end
def print(s)
puts s.gsub(/^ +/,"").gsub(/\n +/,"\n")
end
def talk_for(m)
if m.category == "card"
talk_for_card(m)
elsif m.category == "emotion"
talk_for_emotion(m)
end
end
def talk_for_card(m)
if m.message == "win"
if m.actor == "boy"
print <<"EOS"
おじいさん「ぬおおおおお」
EOS
else
print <<"EOS"
おじいさん「頑張るんじゃ少年!」
EOS
end
end
end
def talk_for_emotion(m)
if m.actor == "jiisan"
talk_for_myemotion(m)
elsif (m.actor != "jiisan") && (m.target == "jiisan")
talk_for_emotion_for_jiisan(m)
elsif (m.actor != "jiisan") && (m.target != "jiisan")
talf_for_emotion_for_other(m)
end
end
#他者の他者に対する感情
def talk_for_emotion_for_other(m)
if m.message == "angry"
print <<"EOS"
おじいさん「落ち着くんじゃ! 怒ってはいかん」
EOS
end
end
def judge(a)
if a <= 5
#if rand() < 0.5
return "ハイ"
else
return "ロー"
end
end
end
#メイン処理
init
mainstory