주사위 코드를 처리하는 스크립트를 썼어요.

콩 연선은 무엇입니까?사람이 봤다https://ja.wikipedia.org/wiki/주사위#주사위와 게임
roll('2D6') // 2 ~ 12 の乱数(確率もただしいやつ)
이런 거 하고 싶어요.했어.

무작위 이야기


우선, 우리는 프로그램에서 양을 실현한 후에 좋은 무작위 수를 원한다. (충분한 주기를 가지고 가능한 한 고르게 분포한다.)하지만 레벨 같은 등급의 랜덤수를 암호화하려는 것은 아니기 때문에 여기Math.random()에서도 가능하다.

타산적인 말


TRPG 등에서 차분 코드를 사용할 때는 계산 공식이다.2+2D65+3D6라.이거 처리하고 싶어요.희망roll('2+2D6') 일자리라는 것이다.

첫말


계산 결과뿐만 아니라 결과도 있었으면 좋겠다.결과만 보면, 예를 들어 도검세계 2.0을 사용하는 인류 종족의 특징인'운명변천'을 사용할 때 어떤 시작을 해야 할지 모르겠다.
이 세상 사람들을 이야기할 때 없어서는 안 될 것이 바로 이'검의 보우/운명의 변천'이다.
1일 1회(오전 6시 기준)면 판정에서 던진 주사위의 눈을 뒤집을 수 있고,'인종적 특성 강화'규칙이 적용되면 뒤집어 주사위를 더할 수 있다.
https://dic.nicovideo.jp/a/인간(sw2.0)

이루어지다


반폴란드 기법


오래전 반폴란드 기법으로 공식을 해석하고 D를 독자적인 조작원으로 정의해 실현했다.나는 이번에도 이렇게 할 줄 알았는데, 이 방법은 번거로운 문제가 있다.그래서 반박했다.
https://ja.wikipedia.org/wiki/반폴란드 기법
대체로 다음과 같이 설명하다.
普通の記法: 1 + 2D6
逆ポーランド記法(通常版): 1 2D6 +
逆ポーランド記法(Dオペレーターあり): 1 2 6 D +
D를 조작원으로 정의하여 쌓인 수량에 따라 무작위 수를 대체할 수 있다.귀찮아.언어에 따라 계산식을 반폴란드 기법으로 바꾸는 프로그램 라이브러리도 있지만 프로그램 라이브러리를 넣고 싶지 않다.나는 중치 기법을 반폴란드 기법으로 만들기 위해 많은 수학 함수를 항목에 도입하는 것을 좋아하지 않는다.

new Function


어쨌든 eval이야.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
eval이 안전성에 문제가 있어서 지식이 멈췄군요. 그렇군요.이걸로 하는 게 안전하잖아!할 수 있을 것 같은데 이걸로 하면 되지.이렇게 되면 계산 공식을 어떻게 처리해야 하는가의 과제를 해결할 수 있다.JavaScript는 분명 엔진이 계산 공식을 처리하는 능력을 가지고 있지만 스스로 설치할 수 있다.
그러나 new Function 내부에서 실행되는 스크립트를 보면 글로벌 변수만 참조할 수 있습니다.나중에 귀찮은 일이 생겼어요.당분간 이맘때쯤이면 그 일을 모르니까 실시해.

1.ts


declare var roll: (count: number, face: number, rolled: number[]) => number

const rollSingle = (face: number): number => Math.ceil(Math.random() * face)
const roll = (count: number, face: number): number => {
  return Array(count).fill(1).reduce(r => r + rollSingle(face), 0)
}

globalThis.roll = roll

const dice = (exp: string): number => {
  if (!exp.match(/^[\d\+\-\*\/\(\)D]+$/i)) { return 0 }
  return new Function('"use strict"; return ' + exp
    .replace(/(\d+)?D(\d+)/ig, (code, c, f) => `roll(${c||'1'},${f})`))()
}
무엇을 하고 있는지 말하려면 new Function에서 계산 처리를 한다.그러나 발견nDm이 되면 roll(n, m)로 바뀐다.6 + 2D66 + roll(2, 6)로 교체했다.roll 함수는 첫 번째 파라미터에 주사위의 개수를 주고 두 번째 파라미터에 주사위의 면수를 주면 부상 결과를 되돌려준다.이 일을 잘 처리하면 계산 결과가 나올 것이다.간단하네.

2.ts


이미 말했듯이 눈에 띄고 싶어서 고쳐야 한다.
declare var roll: (count: number, face: number, rolled: number[]) => number

const rollSingle = (face: number, rolled: number[]): number => {
  const r = Math.ceil(Math.random() * face)
  rolled.push(r)
  return r
}

const roll = (count: number, face: number, rolled: number[]): number => [...Array(count)].reduce(r => r + rollSingle(face, rolled), 0)

globalThis.roll = roll

interface IDiceResult {
  rolled: number[]
  sum: number
}

const dice = (exp: string): IDiceResult => {
  if (!exp.match(/^[\d\+\-\*\/\(\)D]+$/i)) { return { sum: 0, rolled: [] } }
  return new Function('"use strict"; const rolled = []; const sum = ' + exp
    .replace(/(\d+)?D(\d+)/ig, (code, c, f) => `roll(${c||'1'},${f}, rolled)`) + '; return { sum, rolled, exp: "' + exp + '" }')()
}
위축.

times loop 수정


Array(n).fill(1)
이걸
수정
[...Array(n)]
.한 마디로 하면 길이 n의 배열을 통해 리듀스를 해서 n회 주사위를 회전시킨다.루비라면 n.times를 쓰면 되는데...
전자 코드는'1로 길이 n을 만족시키는empty로 만족하는 진열'을 만들고 후자는'길이 n의undefined로 만족하는 배열'을 만든다.속도를 몰라요.
https://zenn.dev/uhyo/articles/array-n-keys-yamero

IDiceResult


typescript이기 때문에interface를 정의해야 하기 때문에 번거롭습니다.실제로 이런 느낌의 대상이 돌아온다.
{
	"exp": "14+5*2D6+(3+D6)*2",
	"rolled": [2, 4, 2],
	"sum": 54
}
응, 14 + 5 * (2 + 4) + (3 + 2) * 2 그래서...54 그렇지!

new Function에서 평가된 코드


  return new Function('"use strict"; const rolled = []; const sum = ' + exp
    .replace(/(\d+)?D(\d+)/ig, (code, c, f) => `roll(${c||'1'},${f}, rolled)`) + '; return { sum, rolled, exp: "' + exp + '" }')()
도저히 이해하기 어려우니까 내용을 조금 적으면
"use strict";
const rolled = [];
const sum = /* ここに式が入る */;
return { sum, rolled, exp: "/* ここにも式が入る */" };
그렇습니다.
그리고 조금 앞에 new Function은 전 세계만 참조할 수 있는 것 같아서(로컬 범위를 참조하는 방법도 있습니까? context를 제출할 수 있습니까? 지금은 모르겠습니다) 전역적으로 롤 함수를 정의할 필요가 있습니다.
그거 하는 건...
declare var roll: (count: number, face: number, rolled: number[]) => number
globalThis.roll = roll
이거요.(실제로 이 줄은 index.d.ts에서 설명함)
글로벌 디스를 처음 알았어요.
이런 느낌으로 썸의 합계치, 롤러드가 등장점에 들어왔다.rolled는 함수의 매개 변수로calc->rollSingle 사이에서 전달되며, rollSingle로 결과를 push합니다.함수에 부작용이 있으면 그것도 괜찮아요.꼼꼼히 실행하려면 얼마든지 열심히 할 수 있는데 너무 귀찮아서...

총결산


new Function은 편리합니다.
원래 롤러는 전 세계에서 정의된 것이 아니라 new Function 내부에서 정의해도 되지 않습니까?그러나 new Function 내부에서 TypeScript를 사용할 수 없어 피했다.내부에서도 정의할 수 있을 것 같아서요.

좋은 웹페이지 즐겨찾기