先日、「徳の起源」がらみで繰り返し囚人ゲームをやったような口をたたいてしまった。実際には、ライフゲームの延長で移動しないグリッドで囚人ゲーム的なことをやったにすぎない。それなのに、山口浩さんからお言葉をいただいてしまった。
- 作者: マットリドレー,岸由二,Matt Ridley,古川奈々子
- 出版社/メーカー: 翔泳社
- 発売日: 2000/06
- メディア: 単行本
- クリック: 35回
- この商品を含むブログ (23件) を見る
@hidekih 実際にやってみたのですね。面白いです。あれもいろいろな前提条件によって結果が異なったりしますので、そのまま現実にもってくるのは危険ですが、直感に沿ってますよね。
http://twitter.com/HYamaguchi/status/408784220085956608
で、pythonをほぼ最初から勉強しなおして、なんとか移動する繰り返す囚人ゲームシミュレーションを作った。山口さんのご指摘どうり、「前提条件」をよく整備していないので、断言はできないが、お互いに協力しあった時の報酬の値で大きく結果は違う。お互いに相手を信頼しあっても報酬が少なければ、ごくごく少数しか生き残れず、かつ裏切り者が生き残る。ほんの少し、お互いが協力しあった時の報酬と大きくするだけで、協力する方が有利なようだ。ま、とにかく書いたというレベル。平成26年の正月の記念ということでさらしておく。
""" 「「移動する繰り返し囚人ゲーム・シミュレーション」」 <<世界>> bcolum 横の数 braw 縦の数 世界 bcolum × brawのテーブル。pythonの入れ子リスト構造で表現。 world 今回の世界 table 「世界」を関数に渡す時の内部変数 <<生物>> 生物のリスト構造 0=x 1=y 2=asset 3=life 4=strategy lives = [0,0,100,1,0]*number_life # 生物のリスト、ゲーム内の生物の辞書構造と標準値 x, y は位置。ちなみ、teble[y][x]となる。 assetは、自分の資産。エネルギー残量。 lifeは、0だと死んでる。1以上だと生きてる。1だと負けた(裏切られた)後、2だと勝った後。つーか、途中から勝ち数の記録に変更。 <<囚人ゲーム>> gamet_tabel 二つのセルの間の演算(対戦)の結果それぞれのセルが受け取る値。囚人のジレンマゲームのテーブル。 戦略は同意か、裏切りの二つ。結果は以下の通り。 相手 同意=0 裏切=1 自分 同意 10/10 -60 / 0 裏切 0/ -60 -30/-30 """ import random def init_and_main() : global bcolum, braw, world, lives, move_table, number_lives,game_table bcolum = 10 braw = 10 world=[] # ゲームの番 number_lives=30 # 生物の数 game_table=[[[10,10,1,1],[-60,0,-1,1]],[[0,-60,1,-1],[-30,-30,-1,-1]]] # ゲームの結果表 move_table=[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]] # 8方向への移動 world=table_int(bcolum,braw) #世界の生成 lives=life_int(number_lives) #生物の生成 table_rand(world, lives) #世界と生物の初期化(ランダム) print_table(world) #プリント 世界 print_lives(lives) #プリント 生物 # test_trade(world, lives) move_and_trade(world, lives, 10) print_table(world) print_lives(lives) def table_int(col, raw): # 初期化。新しい世界を作る。出力を代入することで初期化する。 table=[-1]*(col + 1) for i in range(col + 1): table[i] = [-1]*(raw + 1) return table def life_int(num): # 生物のリストの初期化。出力を変数に代入して生物を作る。値は全て標準値のまま。 live=[0]*num for i in range(num): live[i]=[0,0,100,4,0] return live def table_rand (table, local_lives): # "lives"の値を乱数で設定し、世界に配置する for i in range(len(local_lives)): finish_flag=0 while finish_flag==0 : x=random.randint(1,len(table[1])-1) y=random.randint(1,len(table)-1) # print i,finish_flag,x,y if table[y][x]==-1 : table[y][x]=i local_lives[i][0]=x local_lives[i][1]=y local_lives[i][4]=random.randint(0,2) # print local_lives[i][0], local_lives[i][1] finish_flag=1 def table_move(table, local_lives, life_num, direction) : # 方向は0から7で表す、世界の外、重なりのチェック、周りにない時だけ動ける table_border_x=len(table[0]) table_border_y=len(table) x=local_lives[life_num][0] y=local_lives[life_num][1] new_x=x+move_table[direction][0] new_y=y+move_table[direction][1] a_round=table_round(table,x,y) if a_round >= 0 or new_x < 1 or new_y < 1 or new_x > table_border_x-1 or new_y > table_border_y-1 : new_x=x new_y=y table[y][x]=-1 table[new_y][new_x]=life_num local_lives[life_num][0]=new_x local_lives[life_num][1]=new_y def table_round(table,x,y): # 世界の位置をx,yで指定して周囲の存在をたしかめる。 # print "x-upper ",len(table[1])," y-upper",len(table) if (x < 2) or (x > (len(table[1]))- 2) or (y < 2) or (y > (len(table) - 2)) : return -1 else: if count_lives(table,x-1,y-1) >= 0: return count_lives(table,x-1,y-1) elif count_lives(table,x,y-1) >=0 : return count_lives(table,x,y-1) elif count_lives(table,x+1,y-1) >= 0 : return count_lives(table,x+1,y-1) elif count_lives(table,x-1,y) >= 0 : return count_lives(table,x-1,y) elif count_lives(table,x+1,y) >= 0 : return count_lives(table,x+1,y) elif count_lives(table,x-1,y+1) >= 0 : return count_lives(table,x-1,y+1) elif count_lives(table,x,y+1) >= 0 : return count_lives(table,x,y+1) elif count_lives(table,x+1,y+1) >= 0 : return count_lives(table,x+1,y+1) else : return -1 def count_lives(table,x,y): # print x,y a = table[y][x] if a == -1: return -1 else: return a def print_lives(local_lives): #生物の属性の表示 for i in range(len(local_lives)) : print "num: %d x: %d y: %d asset: %d life: %d strategy: %d" % (i, local_lives[i][0], local_lives[i][1], local_lives[i][2], local_lives[i][3], local_lives[i][4]) def print_table (b): # 世界の表示 print "-"*len(b[1])*4 for i in range(len(b)): for j in range(len(b[i])): if b[i][j]==-1 : print "| ", else : print "|%2d" % b[i][j], print "|" print "-"*len(b[1])*4 def table_trade(table, local_lives, num1, num2): # 2つの番号(生物)を指定してゲーム(trade)させる。 assets_num1 = local_lives[num1][2] assets_num2 = local_lives[num2][2] decision_num1 = trade_strategy(local_lives, num1) decision_num2 = trade_strategy(local_lives, num2) trade_num1 = game_table[decision_num1][decision_num2][0] trade_num2 = game_table[decision_num1][decision_num2][1] if assets_num1 + trade_num1 <0 : dead_lives(table, local_lives, num1) else: local_lives[num1][2] = assets_num1 + trade_num1 local_lives[num1][3] = local_lives[num1][3] + game_table[decision_num1][decision_num2][2] if assets_num2 + trade_num2 <0 : dead_lives(table, local_lives, num2) else: local_lives[num2][2] = assets_num2 + trade_num2 local_lives[num2][3] = local_lives[num2][3] + game_table[decision_num1][decision_num2][3] print assets_num1,assets_num2,decision_num1,decision_num2,trade_num1,trade_num2, game_table[decision_num1][decision_num2][2],game_table[decision_num1][decision_num2][3] print "num: %d x: %d y: %d asset: %d life: %d strategy: %d" % (num1, local_lives[num1][0], local_lives[num1][1], local_lives[num1][2], local_lives[num1][3], local_lives[num1][4]) print "num: %d x: %d y: %d asset: %d life: %d strategy: %d" % (num2, local_lives[num2][0], local_lives[num2][1], local_lives[num2][2], local_lives[num2][3], local_lives[num2][4]) print def trade_strategy(local_lives, num): # 思考ルーチン、あとでよく考える strategy_type=local_lives[num][4] life_status=local_lives[num][3] if strategy_type==1 :#裏切り者 return 1 elif strategy_type==2 and life_status <= 3 :#負けた後の「考える人」 return 1 elif strategy_type==2 and life_status >= 4 :#勝った後の「考える人」 return 0 else : return 0 #お人好し def dead_lives(table, local_lives,num): # 死んだときの処理 local_lives[num][3]=0 table[local_lives[num][1]][local_lives[num][0]]=-1 def test_trade(table, local_lives): for i in range(100): not_same=0 while not_same==0: a=random.randint(0,number_lives-1) b=random.randint(0,number_lives-1) if a!=b : not_same = 1 table_trade(table, local_lives,a,b) print_table(table) print_lives(local_lives) def move_and_trade(table, local_lives, count): for i in range(count): for j in range(len(local_lives)): if local_lives[j][3] > 0 : # print "x",local_lives[j][0]," y",local_lives[j][1] a_round = table_round(table, local_lives[j][0],local_lives[j][1]) # print a_round if a_round != j : if a_round >= 0 : table_trade(table, local_lives,j,a_round) else : table_move(table, local_lives, j, random.randint(0,7)) # print j, local_lives[j][0],local_lives[j][1]