前提知識:nDm
TRPGでは頻繁にサイコロを使う。nがサイコロを振る個数、mが使用するサイコロの最大出目である。
例として、チンチロリンでは6面体サイコロ3つを用いる。よって、3D6
と略称する。
サイコロだけでなく、固定数値を足し引きしたい時もある。
そのような場合、例として6面体サイコロ1つと固定数値3を足し合わせるのであれば1D6+3
と表記する。
Dはdiceを意味する。変数n,mとの区別の為にこの項では大文字のDとしたが、ゲーム上では小文字でも構わない。当記事でも以後小文字で表記する。
前提知識:クリティカルとファンブル
https://www16.atwiki.jp/takugedic/pages/37.html#mugenjouhou
▼クリティカルとファンブル
ダイスロールの結果によって、クリティカルとファンブルという処理が存在します。基本的にダイス目で6が出た時がクリティカル。つまりより良い結果が期待される処理です。
ダイス目で1が出た時がファンブル。判定結果が悪い結果に転がってしまう処理となります。▼クリティカル 【 無限ロール方式 】
ダイス目6が出続ける限り、ダイス追加して数値を加算する。
※クリティカル後のダイス目1はファンブル扱いにはせずにそのまま数値を加算する。
▼ファンブル 【 マイナス方式 】
ダイス目1が出た場合、ダイスをもう一度振って合計値からマイナスする。
はじめに出たダイス目1はそのまま加算して良い。
例) ファンブルロールでダイス目4を出した場合は-3。
※ファンブルロールでは追加のファンブルやクリティカルは発生しない
土台関数
「クリティカル・ファンブル処理を行うnd6」のことを"C"ritical & "F"umble nd6 から略し、cfnd6
と呼称する事にする。
まずは基本となる「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 1、ファンブル→2。
達成値+1-2=-1、クリティカル0回、ファンブル1回
> cf1d6(10)
1-2
[1] -1 0 1
実行例2 6、クリティカル→クリティカル→クリティカル→連鎖終了。
達成値+6+6+6+1=19、クリティカル3回、ファンブル0回
> cf1d6(10)
6+6+6+1
[1] 19 3 0
次に別関数用に内蔵する用のもの。単独での使用は非推奨。
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を加える、というものになる。
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])
}
実行例1 ダイスのみの値は出ず、固定数値を計算した達成値のみがreturn
される事に注意。
> cfnd6(5)+10
3, 6+3, 2, 5, 2
cr:1, fa:0
[1] 31
実行例2 Rでの処理ならば、このようなやや複雑な計算式も一回の実行で処理可能。
> (cfnd6(3)+15) / 2
5, 4, 4
cr:0, fa:0
[1] 14
次は複数ダイスを連ねる
=関数を連ねcfnd6(3) + cfnd6(2) + 10
のようにしても表示が壊れない関数を作成したい。
おまけ:assign関数を利用したバージョン
試行錯誤中にできたモノ。クリティカル・ファンブル処理こそ行っているが、それぞれ発生した回数を記録していない段階。
これをそのまま「Rでcfnd6」関数内部の「Rでcf1d6」の代用とはできないので注意。
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」同様、固定数値を予め足したり一度の入力で計算が可能。
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))
}