特殊処理を行うサイコロを振る関数

### 前提知識：nDm
TRPGでは頻繁にサイコロを使う。nがサイコロを振る個数、mが使用するサイコロの最大出目である。
例として、チンチロリンでは６面体サイコロ３つを用いる。よって、`3D6`と略称する。
サイコロだけでなく、固定数値を足し引きしたい時もある。
そのような場合、例として６面体サイコロ１つと固定数値３を足し合わせるのであれば`1D6+3`と表記する。
Dはdiceを意味する。変数n,mとの区別の為にこの項では大文字のDとしたが、ゲーム上では小文字でも構わない。当記事でも以後小文字で表記する。

#### 前提知識：クリティカルとファンブル
> https://www16.atwiki.jp/takugedic/pages/37.html#mugenjouhou
> ▼クリティカルとファンブル
> ダイスロールの結果によって、クリティカルとファンブルという処理が存在します。
> 
> 基本的にダイス目で６が出た時がクリティカル。つまりより良い結果が期待される処理です。
> ダイス目で１が出た時がファンブル。判定結果が悪い結果に転がってしまう処理となります。
>> ▼クリティカル　【　無限ロール方式　】
>> ダイス目６が出続ける限り、ダイス追加して数値を加算する。
>> ※クリティカル後のダイス目１はファンブル扱いにはせずにそのまま数値を加算する。
>> ▼ファンブル　【　マイナス方式　】
>> ダイス目１が出た場合、ダイスをもう一度振って合計値からマイナスする。
>> はじめに出たダイス目１はそのまま加算して良い。 
>> 例）　ファンブルロールでダイス目４を出した場合は－３。
>> ※ファンブルロールでは追加のファンブルやクリティカルは発生しない

## 土台関数
「クリティカル・ファンブル処理を行うnd6」のことを"C"ritical　& "F"umble nd6　から略し、`cfnd6`と呼称する事にする。
まずは基本となる「Rでcf1d6」。
単独でも使えるが、出力結果に解説を入れていない。
実行例に出力結果のベクトルの各値の表す意味を記す。

```r:cf1d6
cf1d6 <- function(x) {    # x = Upper limit of critical chain
    ans <- 1:x            # Total value
    dice <- 1:x           # Dice value
    cr <- 0               # Critical count
    fa <- 0               # Fumble count
    for(i in 1:x) {
        ans[i] <-  sample(c(1:6), 1, replace=TRUE)    # sample(~) is Dice roll
        dice[i] <- ans[i]
    }
    ans0 <- ans[1]
    dice0 <- dice[1]
    if(ans[1] == 1) {     # Fumble calculation
        ans0 <- ans0 - ans[2]
        dice0 <- paste(dice0, "-", dice[2],sep="")
        fa <- fa + 1 　   # Fumble count +1
    } else {
        for(j in 1:(x-1)){        # Critical calculation
            if(ans[j] == 6) {
                ans0 <- ans0 + ans[j+1]
                dice0 <- paste(dice0, "+", dice[j+1],sep="")
                cr <- cr + 1        # Critical count +1
            } else break
        }
    }
    cat(dice0, "\n", sep = "")
    return(c(ans0,cr,fa))
}
```

実行例１　１、ファンブル→２。
達成値+1-2=-1、クリティカル0回、ファンブル1回

    > cf1d6(10)
    1-2
    [1] -1  0  1

実行例２　６、クリティカル→クリティカル→クリティカル→連鎖終了。
達成値+6+6+6+1=19、クリティカル3回、ファンブル0回

    > cf1d6(10)
    6+6+6+1
    [1] 19  3  0
---
次に別関数用に内蔵する用のもの。単独での使用は非推奨。

```r:cf1d6_connect
cf1d6_connect <- function(x) {
    ans <- 1:x
    dice <- 1:x
    cr <- 0
    fa <- 0
    for(i in 1:x) {
        ans[i] <-  sample(c(1:6), 1, replace=TRUE)
        dice[i] <- ans[i]
    }
    ans0 <- ans[1]
    dice0 <- dice[1]
    if(ans[1] == 1) {
        ans0 <- ans0 - ans[2]
        dice0 <- paste(dice0, "-", dice[2],sep="")
        fa <- fa + 1
    } else {
        for(j in 1:(x-1)){
            if(ans[j] == 6) {
                ans0 <- ans0 + ans[j+1]
                dice0 <- paste(dice0, "+", dice[j+1],sep="")
                cr <- cr + 1
            } else break
        }
    }
    cat(dice0, ", ", sep = "")
    return(c(ans0,cr,fa))
}
```
# 本題
そして、本命の「Rでcfnd6」。
例として`cfnd6(5) + 10`と記述する事で、cf5d6+10が可能。
5つの6面体のサイコロを振り、サイコロ一つずつにクリティカル・ファンブル処理を適応。そして出した合計値に固定数値10を加える、というものになる。

```r:cfnd6
cfnd6 <- function(n) {
    dice0 <- 0
    dice <- matrix(NA, n, 3)
    for(i in 1:(n-1)) {
        dice[i,] <- cf1d6_connect(10)
    }
    dice[n,] <- cf1d6(10)
    for(j in 1:n){
        dice0 <- dice0 + dice[j,]
    }
    cat("cr:", dice0[2], ", ", sep = "") # Critical count
    cat("fa:", dice0[3], "\n", sep = "") # Fumble count
    return(dice0[1])
}
```
実行例１　ダイスのみの値は出ず、固定数値を計算した達成値のみが`return`される事に注意。

    > cfnd6(5)+10
    3, 6+3, 2, 5, 2
    cr:1, fa:0
    [1] 31

実行例２　Rでの処理ならば、このようなやや複雑な計算式も一回の実行で処理可能。

    > (cfnd6(3)+15) / 2
    5, 4, 4
    cr:0, fa:0
    [1] 14

次は複数ダイスを連ねる
＝関数を連ね`cfnd6(3) + cfnd6(2) + 10`のようにしても表示が壊れない関数を作成したい。

##### おまけ：assign関数を利用したバージョン
試行錯誤中にできたモノ。クリティカル・ファンブル処理こそ行っているが、それぞれ発生した回数を記録していない段階。
これをそのまま「Rでcfnd6」関数内部の「Rでcf1d6」の代用とはできないので注意。

```r:cf1d6_old
function(x){        # x = Upper limit of critical chain
    for(i in 1:x) {
        assign(paste("ans", i, sep = ""), sample(c(1:6), 1, replace = TRUE))
    }
    ans0 <- ans1
    if(ans1 == 1)
        ans0 <- ans0 - ans2
    for(j in 1:(x-1)) {
        if(eval(parse(text = paste("ans", j, sep = ""))) == 6) {
            ans0 <- ans0 + eval(parse(text = paste("ans", j+1, sep = "")))
        } else
            break
    }
    return(ans0)
}
```

##### おまけ：ギャンブル対応版の関数内部
こちらも「Rでcf1d6」同様、固定数値を予め足したり一度の入力で計算が可能。

```r:cfg1d6
function(x) {      # x = Upper limit of critical chain
    ans <- 1:x     # Total value
    dice <- 1:x    # Dice value
    cr <- 0        # Critical count
    fa <- 0        # Fumble count
    for(i in 1:x) {
        ans[i] <-  sample(c(1:6), 1, replace=TRUE)
        dice[i] <- ans[i]
    }
    ans0 <- ans[1]
    dice0 <- dice[1]
    if(ans[1] <= 3) {    # Fumble calculation
        ans0 <- ans0 - ans[2]
        dice0 <- paste(dice0, "-", dice[2], sep="")
        fa <- fa + 1     # Fumble count +1
    } else {
        if(ans[1] >= 4){    # Critical calculation(first time)
            ans0 <- ans0 + ans[2]
            dice0 <- paste(dice0, "+", dice[2], sep="")
            cr <- cr + 1 #Critical count +1
            for(j in 2:(x-1)){    # Critical calculation (second and subsequent)
                if(ans[j] == 6) {
                    ans0 <- ans0 + ans[j+1]
                    dice0 <- paste(dice0,"+",dice[j+1],sep="")
                    cr <- cr + 1 #Critical count +1
                } else break
            }
        }
    }
    cat(dice0, "\n", sep = "")
    return(c(ans0,cr,fa))
}
```