From 86e24d9c7092d926f0ee5141dfed87b7640f5fea Mon Sep 17 00:00:00 2001 From: faceless192x Date: Sun, 10 May 2026 17:47:50 +0900 Subject: [PATCH 1/6] Test update --- lib/bcdice/arithmetic/node.rb | 68 ++++++++++++++++++++++++++++++++++ lib/bcdice/arithmetic/parser.y | 10 ++++- lib/bcdice/command/lexer.rb | 3 ++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/lib/bcdice/arithmetic/node.rb b/lib/bcdice/arithmetic/node.rb index 763be5745..7a4838207 100644 --- a/lib/bcdice/arithmetic/node.rb +++ b/lib/bcdice/arithmetic/node.rb @@ -159,6 +159,74 @@ def divide_and_round(dividend, divisor, _round_type) end end + # べき乗(x^n)のノード + class Power + # ノードを初期化する + # @param [Object] base 底のノード + # @param [Object] exp 指数のノード + def initialize(base, exp) + @base = base + @exp = exp + end + + # @param round_type [Symbol] 端数処理方法 + # @return [Integer] 評価結果 + # @raise [ArgumentError] 指数が負の場合 + def eval(round_type) + b = @base.eval(round_type) + e = @exp.eval(round_type) + raise ArgumentError, "べき乗の指数に負の値は使用できません: #{e}" if e.negative? + + b**e + end + + # @return [String] メッセージへの出力 + def output + "#{@base.output}^#{@exp.output}" + end + + # @return [String] ノードのS式 + def s_exp + "(^ #{@base.s_exp} #{@exp.s_exp})" + end + end + + # 常用対数(xLOGn)のノード + # + # x を底、n を真数とした対数 log_x(n) を計算する。 + # 結果は切り捨てにより整数化する。 + class Log + # ノードを初期化する + # @param [Object] base 底のノード + # @param [Object] value 真数のノード + def initialize(base, value) + @base = base + @value = value + end + + # @param round_type [Symbol] 端数処理方法 + # @return [Integer] 評価結果(切り捨て) + # @raise [ArgumentError] 底または真数が対数の定義域外の場合 + def eval(round_type) + b = @base.eval(round_type).to_f + v = @value.eval(round_type).to_f + raise ArgumentError, "対数の底は1より大きい値でなければなりません: #{b}" if b <= 1.0 + raise ArgumentError, "対数の真数は正の値でなければなりません: #{v}" unless v.positive? + + (Math.log(v) / Math.log(b)).floor + end + + # @return [String] メッセージへの出力 + def output + "#{@base.output}LOG#{@value.output}" + end + + # @return [String] ノードのS式 + def s_exp + "(LOG #{@base.s_exp} #{@value.s_exp})" + end + end + class Negative def initialize(body) @body = body diff --git a/lib/bcdice/arithmetic/parser.y b/lib/bcdice/arithmetic/parser.y index 2658c54bb..f541530af 100644 --- a/lib/bcdice/arithmetic/parser.y +++ b/lib/bcdice/arithmetic/parser.y @@ -1,5 +1,5 @@ class BCDice::Arithmetic::Parser - token NUMBER R U C F PLUS MINUS ASTERISK SLASH PARENL PARENR + token NUMBER R U C F PLUS MINUS ASTERISK SLASH PARENL PARENR CARET LOG rule add: add PLUS mul @@ -32,6 +32,14 @@ class BCDice::Arithmetic::Parser { result = val[1] } | MINUS unary { result = Arithmetic::Node::Negative.new(val[1]) } + | log_op + + log_op: log_op LOG power + { result = Arithmetic::Node::Log.new(val[0], val[2]) } + | power + + power: term CARET power + { result = Arithmetic::Node::Power.new(val[0], val[2]) } | term term: PARENL add PARENR diff --git a/lib/bcdice/command/lexer.rb b/lib/bcdice/command/lexer.rb index 52ce17394..efa3bf102 100644 --- a/lib/bcdice/command/lexer.rb +++ b/lib/bcdice/command/lexer.rb @@ -17,6 +17,7 @@ class Lexer "@" => :AT, "#" => :SHARP, "$" => :DOLLAR, + "^" => :CARET, }.freeze def initialize(source, notations) @@ -38,6 +39,8 @@ def next_token if (number = @scanner.scan(/\d+/)) [:NUMBER, number.to_i] + elsif (log_op = @scanner.scan(/LOG(?=[^A-Za-z]|$)/i)) + [:LOG, log_op.upcase] elsif (cmp_op = @scanner.scan(/[<>!=]+/)) cmp_op = Normalize.comparison_operator(cmp_op) type = cmp_op ? :CMP_OP : :ILLEGAL From ed001cb809a7dd85ac132829b6da7e8ac6ada164 Mon Sep 17 00:00:00 2001 From: faceless192x Date: Sun, 10 May 2026 21:18:57 +0900 Subject: [PATCH 2/6] Fix Files --- lib/bcdice/common_command/lexer.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/bcdice/common_command/lexer.rb b/lib/bcdice/common_command/lexer.rb index b0c90185a..806ebcee6 100644 --- a/lib/bcdice/common_command/lexer.rb +++ b/lib/bcdice/common_command/lexer.rb @@ -17,6 +17,7 @@ class Lexer "]" => :BRACKETR, "?" => :QUESTION, "@" => :AT, + "^" => :CARET, }.freeze def initialize(source) @@ -30,6 +31,8 @@ def next_token if (number = @scanner.scan(/\d+/)) [:NUMBER, number.to_i] + elsif (log_op = @scanner.scan(/LOG(?=[^A-Za-z]|$)/i)) + [:LOG, log_op.upcase] elsif (cmp_op = @scanner.scan(/[<>!=]+/)) [:CMP_OP, Normalize.comparison_operator(cmp_op)] else From b04e791452ffeade7a68a870c304dc6b43cab547 Mon Sep 17 00:00:00 2001 From: faceless192x Date: Sun, 10 May 2026 21:44:22 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=E6=AD=A3=E5=B8=B8=E5=8B=95=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/common_command/calc/parser.y | 10 +++++++++- test/data/Cthulhu.toml | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/bcdice/common_command/calc/parser.y b/lib/bcdice/common_command/calc/parser.y index ba5f0c153..4d4c26472 100644 --- a/lib/bcdice/common_command/calc/parser.y +++ b/lib/bcdice/common_command/calc/parser.y @@ -1,5 +1,5 @@ class BCDice::CommonCommand::Calc::Parser - token NUMBER R U C F S PLUS MINUS ASTERISK SLASH PARENL PARENR + token NUMBER R U C F S PLUS MINUS ASTERISK SLASH PARENL PARENR CARET LOG rule expr: secret C add @@ -45,6 +45,14 @@ class BCDice::CommonCommand::Calc::Parser { result = val[1] } | MINUS unary { result = Arithmetic::Node::Negative.new(val[1]) } + | log_op + + log_op: log_op LOG power + { result = Arithmetic::Node::Log.new(val[0], val[2]) } + | power + + power: term CARET power + { result = Arithmetic::Node::Power.new(val[0], val[2]) } | term term: PARENL add PARENR diff --git a/test/data/Cthulhu.toml b/test/data/Cthulhu.toml index 47d0dd762..dfaed9c9f 100644 --- a/test/data/Cthulhu.toml +++ b/test/data/Cthulhu.toml @@ -1,3 +1,23 @@ +[[ test ]] +game_system = "Cthulhu" +input = "c(10^10)" +output = "c(10^10) > 10000000000" +rands = [ +] +[[ test ]] +game_system = "Cthulhu" +input = "c(10log100)" +output = "c(10LOG100) > 2" +rands = [ +] +[[ test ]] +game_system = "Cthulhu" +input = "c(10*5)" +output = "c(10*5) > 50" +rands = [ +] + + [[ test ]] game_system = "Cthulhu" input = "1D100<=70 ファンブルなし" From 5ea10fa667334d963171bbf86873e4d5b62f1040 Mon Sep 17 00:00:00 2001 From: faceless192x Date: Mon, 11 May 2026 08:28:06 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=82=92=E5=89=8A=E9=99=A4=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/command/lexer.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/bcdice/command/lexer.rb b/lib/bcdice/command/lexer.rb index efa3bf102..52ce17394 100644 --- a/lib/bcdice/command/lexer.rb +++ b/lib/bcdice/command/lexer.rb @@ -17,7 +17,6 @@ class Lexer "@" => :AT, "#" => :SHARP, "$" => :DOLLAR, - "^" => :CARET, }.freeze def initialize(source, notations) @@ -39,8 +38,6 @@ def next_token if (number = @scanner.scan(/\d+/)) [:NUMBER, number.to_i] - elsif (log_op = @scanner.scan(/LOG(?=[^A-Za-z]|$)/i)) - [:LOG, log_op.upcase] elsif (cmp_op = @scanner.scan(/[<>!=]+/)) cmp_op = Normalize.comparison_operator(cmp_op) type = cmp_op ? :CMP_OP : :ILLEGAL From 95bf184a322553fa434003eb7a0437faf040899b Mon Sep 17 00:00:00 2001 From: faceless192x Date: Wed, 13 May 2026 08:23:29 +0900 Subject: [PATCH 5/6] =?UTF-8?q?LOG=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=81=AE=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/arithmetic/node.rb | 36 ------------------------------ lib/bcdice/arithmetic/parser.y | 8 ++----- lib/bcdice/common_command/lexer.rb | 2 -- test/data/Cthulhu.toml | 10 +++++++-- 4 files changed, 10 insertions(+), 46 deletions(-) diff --git a/lib/bcdice/arithmetic/node.rb b/lib/bcdice/arithmetic/node.rb index 7a4838207..6a2e95b48 100644 --- a/lib/bcdice/arithmetic/node.rb +++ b/lib/bcdice/arithmetic/node.rb @@ -191,42 +191,6 @@ def s_exp end end - # 常用対数(xLOGn)のノード - # - # x を底、n を真数とした対数 log_x(n) を計算する。 - # 結果は切り捨てにより整数化する。 - class Log - # ノードを初期化する - # @param [Object] base 底のノード - # @param [Object] value 真数のノード - def initialize(base, value) - @base = base - @value = value - end - - # @param round_type [Symbol] 端数処理方法 - # @return [Integer] 評価結果(切り捨て) - # @raise [ArgumentError] 底または真数が対数の定義域外の場合 - def eval(round_type) - b = @base.eval(round_type).to_f - v = @value.eval(round_type).to_f - raise ArgumentError, "対数の底は1より大きい値でなければなりません: #{b}" if b <= 1.0 - raise ArgumentError, "対数の真数は正の値でなければなりません: #{v}" unless v.positive? - - (Math.log(v) / Math.log(b)).floor - end - - # @return [String] メッセージへの出力 - def output - "#{@base.output}LOG#{@value.output}" - end - - # @return [String] ノードのS式 - def s_exp - "(LOG #{@base.s_exp} #{@value.s_exp})" - end - end - class Negative def initialize(body) @body = body diff --git a/lib/bcdice/arithmetic/parser.y b/lib/bcdice/arithmetic/parser.y index f541530af..e77fb4ab9 100644 --- a/lib/bcdice/arithmetic/parser.y +++ b/lib/bcdice/arithmetic/parser.y @@ -1,5 +1,5 @@ class BCDice::Arithmetic::Parser - token NUMBER R U C F PLUS MINUS ASTERISK SLASH PARENL PARENR CARET LOG + token NUMBER R U C F PLUS MINUS ASTERISK SLASH PARENL PARENR CARET rule add: add PLUS mul @@ -32,11 +32,7 @@ class BCDice::Arithmetic::Parser { result = val[1] } | MINUS unary { result = Arithmetic::Node::Negative.new(val[1]) } - | log_op - - log_op: log_op LOG power - { result = Arithmetic::Node::Log.new(val[0], val[2]) } - | power + | power power: term CARET power { result = Arithmetic::Node::Power.new(val[0], val[2]) } diff --git a/lib/bcdice/common_command/lexer.rb b/lib/bcdice/common_command/lexer.rb index 806ebcee6..af5e8a6cd 100644 --- a/lib/bcdice/common_command/lexer.rb +++ b/lib/bcdice/common_command/lexer.rb @@ -31,8 +31,6 @@ def next_token if (number = @scanner.scan(/\d+/)) [:NUMBER, number.to_i] - elsif (log_op = @scanner.scan(/LOG(?=[^A-Za-z]|$)/i)) - [:LOG, log_op.upcase] elsif (cmp_op = @scanner.scan(/[<>!=]+/)) [:CMP_OP, Normalize.comparison_operator(cmp_op)] else diff --git a/test/data/Cthulhu.toml b/test/data/Cthulhu.toml index dfaed9c9f..110eb1f34 100644 --- a/test/data/Cthulhu.toml +++ b/test/data/Cthulhu.toml @@ -6,8 +6,14 @@ rands = [ ] [[ test ]] game_system = "Cthulhu" -input = "c(10log100)" -output = "c(10LOG100) > 2" +input = "c((2^3^4)-2^(3^4))" +output = "c((2^3^4)-2^(3^4)) > 0" +rands = [ +] +[[ test ]] +game_system = "Cthulhu" +input = "c((2^3^4)-(2^3)^4)" +output = "c((2^3^4)-(2^3)^4) > 2417851639229258349408256" rands = [ ] [[ test ]] From 4ae894beedf1cc34f12b8dc56097d29b4e581f03 Mon Sep 17 00:00:00 2001 From: faceless192x Date: Wed, 13 May 2026 08:27:37 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=E5=89=8A=E9=99=A4=E6=BC=8F=E3=82=8C?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/bcdice/common_command/calc/parser.y | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/bcdice/common_command/calc/parser.y b/lib/bcdice/common_command/calc/parser.y index 4d4c26472..7f69a690d 100644 --- a/lib/bcdice/common_command/calc/parser.y +++ b/lib/bcdice/common_command/calc/parser.y @@ -1,5 +1,5 @@ class BCDice::CommonCommand::Calc::Parser - token NUMBER R U C F S PLUS MINUS ASTERISK SLASH PARENL PARENR CARET LOG + token NUMBER R U C F S PLUS MINUS ASTERISK SLASH PARENL PARENR CARET rule expr: secret C add @@ -45,11 +45,7 @@ class BCDice::CommonCommand::Calc::Parser { result = val[1] } | MINUS unary { result = Arithmetic::Node::Negative.new(val[1]) } - | log_op - - log_op: log_op LOG power - { result = Arithmetic::Node::Log.new(val[0], val[2]) } - | power + | power power: term CARET power { result = Arithmetic::Node::Power.new(val[0], val[2]) }