Help us understand the problem. What is going on with this article?

# FabfibというボードゲームのシミュレータをPythonで書いているという話

More than 1 year has passed since last update.

## Fabfibシミュレータfor研究

Fabfibというゲームの研究用の(プレイ用でない)シミュレータを2017年くらいから書いています。プレイをしたい場合はFabfibの購入をよろしくお願いします。

## 何を使ったか

```pip3 install numpy
```

なぜnumpyを使ったかと言えば、numpyの行列で戦況を格納すれば、分析するときに便利だと考えたからです。

## Call Strategy

「捨てた札を引き直した結果、より高い数字の札を引いた。」と見せかける戦略を基本的な戦略として採用しています。

```class BasicLogic(CallStrategy):

def call_check(self):
"""Basic call_check method
>>> import numpy as np
>>> RegularCase = BasicLogic(431,1,np.array([6,3,1]))
>>> print(RegularCase.call_check() == 631)
True
>>> IregularCase = BasicLogic(831,1,np.array([6,3,1]))
>>> print(631 < IregularCase.call_check() <= 999)
True
>>> NineCase = BasicLogic(995,1,np.array([9,9,4]))
>>> print(995 < NineCase.call_check() <= 999)
True
>>> AllChange = BasicLogic(654,3,np.array([4,3,1]))
>>> print(654 < AllChange.call_check() <= 999)
True
"""
EvaluatedValue = super().evaluate_hand(self.Hand)

# if real hand's value is weak,
# Calling fake number based on Game's State
if self.Number >= EvaluatedValue:

# Leaves to change is based on NonNines Count of
ToCall = np.array([int(i) for i in str(self.Number)])
ToCall = np.sort(ToCall)  # ascending order
NonNines = len(np.where(ToCall != 9)[0])

for i in range(0, LeavesToChange - 1):
ToCall[i] = np.random.poisson(lam=4)
if ToCall[i] > 9:
ToCall[i] = 9

ToCall[LeavesToChange - 1] += 1
ToCall[LeavesToChange - 1] += np.random.poisson(lam=0.2)
if ToCall[LeavesToChange - 1] > 9:
ToCall[LeavesToChange - 1] = 9

return super().evaluate_hand(np.sort(ToCall)[::-1])

else:
return EvaluatedValue
```

```class BasicLogic(DiscardStrategy):
"""Players on BasicLogic strategy discard ...

less then 6, because a high possibility to draw any of 5-9.
If the difference of Max and Min is less then 4, other then nine.
To raise the posibility of 9.
"""

def __init__(self, Hand):
super().__init__(Hand)
self.Max = np.max(Hand)
self.Min = np.min(Hand)

>>> import numpy as np
>>> CloseCase = BasicLogic(np.array([6,5,4]))
array([5, 4, 6])
"""
self.less_then(6)
if((self.Max - self.Min) < 4):
self.less_then(9)

def less_then(self, Number):
self.Hand = self.Hand[self.Hand >= Number]
```

## Doubt Strategy

つまりダウトを仕掛ける判断には、宣言されている数字が重要になります。以下の式を用いてダウト指数とし、状況を加味してそれを補正する方法を採用しました。

```class BasicLogic(DoubtStrategy):

def doubt_check(self):
"""Basic doubt_check
>>> import numpy as np
<class 'bool'>
<class 'bool'>
"""
DoubtIndex = 0.0
DoubtIndex += (np.random.rand() * 0.2 + 0.8) * \
(((self.Call - 700) / 300) ** 3)

DoubtIndex += 0.1
if self.Call >= 990:
DoubtIndex += 0.6

DoubtIndex += 0.3
if self.Call >= 900:
DoubtIndex += 0.3

if DoubtIndex > 0.85:
self.Doubt = True

return self.Doubt
```

## 動かしかた

numpyがインストールされていることを前提とします。cloneします。

```git clone https://github.com/say-ya-sigma/fabfib.git
cd fabfib
```

`game.py`で動かします。引数はゲーム数です。

```python3 game.py 10
```
Why do not you register as a user and use Qiita more conveniently?
1. We will deliver articles that match you
By following users and tags, you can catch up information on technical fields that you are interested in as a whole
2. you can read useful information later efficiently
By "stocking" the articles you like, you can search right away