RPG 보드 게임 규칙에 대한 일반 규칙 파서-어떻게해야합니까?


19

펜 및 종이 스타일 RPG 시스템을위한 일반 규칙 파서를 만들고 싶습니다. 규칙은 일반적으로 주사위의 1 ~ N 개의 엔티티 1 ~ N 개의 역할과 엔티티의 여러 속성을 기반으로 값을 계산할 수 있습니다.

예를 들면 다음과 같습니다.

플레이어는 STR 18을 가지고 있으며, 현재 장착 된 무기는 +1 STR의 보너스를 주지만 DEX -1의 보너스입니다. 그는 몬스터 엔티티를 공격하고 이제 게임 로직이 일련의 규칙 또는 조치를 실행해야합니다.

플레이어가 주사위를 굴리면 예를 들어 8 이상 (기본 공격 가치는 기본 속성 중 하나입니다!)을 얻습니다. 몬스터는 주사위를 굴려 공격이 갑옷을 통과하는지 계산합니다. 그렇다면 공격이 차단되지 않은 경우 피해를 입습니다.

단순한 수학 규칙 외에도 특정 클래스의 사용자 (예 : 전사 대 마법사) 또는 다른 속성에만 적용하는 것과 같은 제약 조건이있을 수 있습니다. 따라서 이것은 수학 연산에만 국한되지 않습니다.

Dungeon 및 Dragons와 같은 RPG 시스템에 익숙하다면 내가 무엇을하고 있는지 알게 될 것입니다.

내 문제는 이제 이것을 최선의 방법으로 정확하게 구축하는 방법에 대한 단서가 없다는 것입니다. 나는 사람들이 모든 종류의 규칙을 설정하고 나중에 플레이어와 몬스터를 선택하는 것과 같은 행동을하고 행동 (공격과 같은 규칙)을 실행하기를 원합니다.

나는 데이터베이스 측면에 대한 도움을 덜 요청하지만 규칙을 유연하게 유지하기 위해 구조와 파서를 만드는 방법에 대해 더 많이 묻습니다. 이것에 대한 선택 언어는 PHP입니다.

편집 I :

좀 더 복잡한 게임 규칙을 만들기 위해 사용자 친화적 인 인터페이스 (누군가 프로그래밍 언어를 배우지 않아도 됨)를 만들고 싶습니다. 간단한 이유 : 개인적인 사용으로 항상 모든 규칙을 기억할 필요는 없습니다. 우리는 단순히 그 규칙을 자주 사용하지 않으며 매번 규칙을 찾아 보는 것이 스토퍼입니다. 또한 : 뭔가를하고 배우는 재미있는 작업처럼 보입니다. :)

내가 지금까지 시도한 것 : 잘못된 아키텍처를 구축하는 데 시간을 낭비하지 않고 개념을 생각하는 것입니다. 지금까지 사용자가 원하는 수의 속성을 만든 다음 원하는 종류의 속성을 원하는 유형의 개체에 할당 할 수 있다는 아이디어가 있습니다. 실체는 플레이어, 몬스터, 아이템, 무엇이든 될 수 있습니다. 이제 무언가를 계산할 때 규칙 파서가 규칙 파서가 Player.base_attack + dice (1x6)> Monster.armor_check 다음 Monster.health-1; 여기서 질문은 해당 파서를 만드는 방법에 관한 것입니다.

편집 II :

다음은 매우 기본적인 값의 예이지만 올바르게 계산하기 위해 고려해야 할 다양한 요소와 변수가 있습니다.

기본 공격 보너스 (Term) 기본 공격 보너스 (일반적으로 d20 커뮤니티에서 BAB라고 함)는 캐릭터 클래스 및 레벨에서 파생 된 공격 롤 보너스입니다. 기본 공격 보너스는 다양한 캐릭터 클래스에 따라 다른 속도로 증가합니다. 기본 공격 보너스가 +6, 기본 공격 보너스가 +11 이상인 세 번째, 그리고 기본 공격 보너스가 +16 이상인 네 번째 캐릭터는 라운드 당 두 번째 공격을받습니다. 멀티 클래스 캐릭터 스택과 같은 다른 클래스에서 얻은 기본 공격 보너스. 캐릭터의 기본 공격 보너스는 +16에 도달 한 후 더 이상 공격을 부여하지 않으며, +0보다 작을 수 없으며, 캐릭터 레벨이 20 일에 도달 한 후 클래스 레벨로 인해 증가하지 않습니다. 특정 업적에는 최소 기본 공격 보너스가 필요합니다.

http://www.dandwiki.com/wiki/Base_Attack_Bonus_(Term) 에서 기본 공격에 필요한 값을 계산하기 위해 자체 규칙이있는 클래스 및 위업에 대한 링크를 포함하여 여기에서 읽을 수 있습니다 .

나는 그것을 가능한 한 일반적으로 유지하면 좋은 규칙 파서를 얻는 것이 꽤 어려워 질 것이라고 생각하기 시작했습니다.



2
실제로 오늘 아침 정확히 이런 유형의 문제에 대해 생각하고 있었으며 (RPG와 관련이 없지만 규칙 처리 엔진과 관련이 있음) 규칙 처리에 대한 비 상태 머신 접근 방식과 조합 파서가 일반적으로 수행하는 작업을 완료하는 데 얼마나 효과적인지 생각하려고했습니다. 상태 머신. 모나 딕 콤비 네이터가 대부분의 상태 머신 문제에보다 깔끔하게 접근 할 수있는 가능성이 풍부하다고 생각합니다. 그것은 횡설수설처럼 들릴지 모르지만 나는이 아이디어에 뭔가가 있다고 생각합니다. 단지 2 센트입니다. RPG 시스템은 코딩을 좋아하는 고전적인 재미있는 연습 문제입니다. 아마도이 접근법을 시도해 볼 것입니다.
Jimmy Hoffa

1
@jk. 이 기사에서는 명령 행 프로그램 인수 구문 분석에서 선호하는 패턴을 상기시켜줍니다 Func. 놀랍게도 Yegge의 게시물이 매우 시원하다는 것을 알지 못했습니다.
Jimmy Hoffa

4
왜 이것이 "진짜 질문이 아닌"것으로 닫혔는지 잘 모르겠습니다. 특정 요구 사항 세트 (RPG 규칙 시스템)가있는 응용 프로그램을 설계하는 방법에 대한 상위 수준의 "화이트 보드"질문입니다. 다시 열기로 투표했지만 다시 열려면 다시 4 번의 다른 다시 열기 투표가 필요합니다.
Rachel

1
솔직히 나는이 사이트가 이런 종류의 개념적 질문에 대한 것이라고 생각했지만 stackoverflow.com은 코드 / 구현 문제에 대해 생각했습니다.
burzum

답변:


9

당신이 요구하는 것은 본질적으로 도메인 특정 언어-좁은 목적을위한 작은 프로그래밍 언어,이 경우 P & P RPG 규칙을 정의하는 것입니다. 언어를 디자인하는 것은 원칙적으로 어렵지 않지만, 생산성을 높이기 위해서는 반드시 알아야하는 상당한 양의 사전 지식이 있습니다. 안타깝게도,이 내용에 대한 중심 참조는 없습니다. 시행 착오와 많은 연구를 통해 선택해야합니다.

먼저 다른 작업을 구현할 수있는 기본 작업 집합을 찾습니다. 예를 들면 다음과 같습니다.

  • 플레이어, NPC 또는 몬스터의 속성 가져 오기 또는 설정

  • 다이 롤의 결과를 얻으십시오

  • 산술 식 평가

  • 조건식 평가

  • 조건부 분기 수행

기본 요소를 표현하는 구문을 디자인하십시오. 숫자를 어떻게 표현 하시겠습니까? 진술은 어떻게 생겼습니까? 명령문은 세미콜론으로 종료됩니까? 개행 종료? 블록 구조가 있습니까? 기호 또는 들여 쓰기를 통해 어떻게 표시합니까? 변수가 있습니까? 유효한 변수 이름은 무엇입니까? 변수를 변경할 수 있습니까? 객체의 속성에 어떻게 액세스합니까? 객체는 일류입니까? 직접 만들 수 있습니까?

프로그램을 추상 구문 트리 (AST)로 바꾸는 파서를 작성하십시오. 재귀 강하 구문 분석기로 구문 분석에 대해 학습하십시오. 재귀 하강으로 산술 표현식을 구문 분석하는 것이 성가신 방법에 대해 배우고 하향식 연산자 우선 순위 파서 (Pratt parser)는 삶을 더 쉽고 코드를 단축시킬 수 있습니다.

AST를 평가하는 통역사를 작성하십시오. 그것은 단순히 트리의 각 노드를 읽고 무엇을 말하는 수행 할 수 있습니다 a = b하게하면 new Assignment("a", "b")된다 vars["a"] = vars["b"];. 생활이 더 쉬워지면 평가 전에 AST를 더 간단한 형태로 변환하십시오.

작동하고 읽을 수있는 가장 간단한 것을 디자인하는 것이 좋습니다. 다음은 언어가 어떻게 보일지에 대한 예입니다. 디자인은 특정 요구 사항과 환경 설정에 따라 달라집니다.

ATK = D20
if ATK >= player.ATK
    DEF = D20
    if DEF < monster.DEF
        monster.HP -= ATK
        if monster.HP < 0
            monster.ALIVE = 0
        end
    end
end

또는 Python 또는 Lua와 같은 기존 스크립팅 언어를 응용 프로그램에 포함시키는 방법을 배우십시오. 도메인 별 작업에 범용 언어를 사용하는 단점은 추상화가 유출된다는 것입니다. 언어의 모든 기능과 문제점은 여전히 ​​존재합니다. 장점은 직접 구현할 필요가 없다는 점입니다. 이는 중요한 단점입니다. 생각해 봐.


2
나쁜 접근 방식은 아니지만 DSL에 대해 지속적으로 회의적입니다. 특히 사람들이 가지고있는 유창한 API와는 달리 커스텀 구문을 사용하여 진정한 DSL에 대해 이야기하는 경우 특히 그렇습니다. "DSL"을 호출하기 시작했습니다.) 따라서 가치가 있다면 그 중 하나를 사용하는 것이 좋습니다. 종종 사람들은 작은 규칙 엔진에만 DSL을 사용하려는 DSL을 시도하고 싶어한다고 생각합니다. 여기 내 규칙이있다 : DSL 구현 + 사용법이 DSL이없는 것보다 적은 코드라면, 그렇게한다고 생각하지 않는다.
Jimmy Hoffa

1
@JimmyHoffa : 충분합니다. 언어 기반 솔루션, 특히 게임에 도달하는 것은 저의 본성입니다. 나는 여러 번 해왔 기 때문에 작고 기능적인 것을 만드는 어려움을 과소 평가했을 것입니다. 그러나이 경우 적절한 권장 사항처럼 보입니다.
Jon Purdy

나는 이것이 이런 종류의 문제에 대한 올바른 접근법이라고 말해야한다고 생각하지만, 그것은 구현을 수행하는 사람이 충분한 기술을 가진 사람이라는 것을 전제로합니다. 학습을 위해 DSL은 주니어에게는 훌륭하지만 실제 출시 가능한 제품의 경우 DSL을 작성하는 시니어 레벨 이하의 사람은 결코보고 싶지 않으며 주니어에게는 DSL 해결 가능한 문제가 다른 방식으로 해결되어야합니다.
Jimmy Hoffa

이것을 읽은 후에는 단순히 루아 스크립트를 평가할 수 있다고 생각합니다. 여기서 단점은 사용자가 루아 스크립트를 작성할 수 있어야한다는 것입니다. 내 개인적인 목표는 magento의 규칙 작성기 (전자 상거래 앱)와 같이 프로그래밍 지식없이 사용할 수있는 인터페이스를 작성하는 것입니다. 사람들이 자신의 규칙을 추가 할 수 있기를 원하기 때문입니다. 나는 상업적인 것을 구현하고 있지 않습니다. 저와 제 친구들이 우리가 불규칙한 기반에서 플레이하는 RPG 시스템의 규칙에 들어가서 규칙을 다시 적용하고 적용하는 것은 시간이 지나면 고통입니다 ...
burzum

1
@burzum : 인터페이스가 루아 스크립트를 생성하게하는 것은 어떻습니까?
TMN

3

각 작업의 다른 "단계"를 결정하는 것으로 시작하겠습니다.

예를 들어, 전투 단계에는 다음이 포함될 수 있습니다.

GetPlayerCombatStats();
GetEnemyCombatStats();
GetDiceRoll();
CalculateDamage();

이러한 방법은 각각 같은 일부 상당히 일반 객체에 접근 할 것이다 Player과를 Monster, 그리고 다른 엔티티 값을 수정하는 데 사용할 수있는 몇 가지 매우 일반적인 검사를 수행합니다.

예를 들어, GetPlayerCombatStats()메소드 에 다음과 같은 내용이 포함될 수 있습니다 .

GetPlayerCombatStats()
{
    Stats tempStats = player.BaseStats;

    player.GetCombatStats(player, monster, tempStats);

    foreach(var item in Player.EquippedItems)
        item.GetCombatStats(player, monster, tempStats);
}

이를 통해 플레이어 클래스, 몬스터 또는 장비 조각과 같은 특정 규칙이있는 엔티티를 쉽게 추가 할 수 있습니다.

또 다른 예로, 오징어를 제외한 모든 것을 깎는 검을 원한다고 가정 해 촉수가 없으면 모든 것을 상대로 +4를줍니다.

이 검의 장비 등급 GetCombatStats은 다음과 같습니다.

GetCombatStats(Player player, Monster monster, Stats tmpStats)
{
    if (monster.Type == MonsterTypes.Tentacled)
    {
        player.Equipment.Drop(this);
        tmpStats.Attack -= 10;
    }
    else
    {
        tmpStats.Attack += 4;
    }
}

이를 통해 나머지 전투 논리에 대해 알 필요없이 전투 값을 쉽게 수정할 수 있으며 장비 (또는 모든 엔티티)의 세부 정보 및 구현 논리만으로도 응용 프로그램에 새로운 조각을 쉽게 추가 할 수 있습니다. 엔터티 클래스 자체에 존재해야합니다.

파악해야 할 핵심 사항은 어떤 점에서 가치가 변할 수 있으며 어떤 요소가 그 가치에 영향을 미치는지입니다. 구성 요소가 있으면 개별 구성 요소를 쉽게 구축 할 수 있습니다. :)


갈 길이야 대부분의 Pen & Paper RPG에는 계산 단계가 있으며 일반적으로 가이드 북에 작성됩니다. 스테이지 순서를 정렬 된 목록에 배치하여보다 일반적인 순서로 만들 수도 있습니다.
Hakan Deryal

이것은 나에게 정적으로 들리며 사용자가 UI에 필요한 규칙을 간단히 입력 / 빌드 할 수 없습니까? 설명하는 내용은 하드 코딩 된 규칙과 비슷합니다. 중첩 된 규칙 목록을 사용하여이 작업을 수행 할 수도 있습니다. 규칙을 하드 코딩하고 싶지 않습니다. 코드로 모든 것을 할 수 있다면 그 질문을 할 필요가 없습니다. 쉽습니다. :)
burzum

@burzum 예, 이는 규칙이 코드에 의해 정의된다는 것을 의미하지만 코드에서 매우 확장 가능합니다. 예를 들어, 새로운 클래스 유형, 새로운 장비 조각 또는 새로운 몬스터 유형을 추가하려면 해당 엔티티에 대한 클래스 객체를 작성하고 클래스의 적절한 메소드를 로직으로 채워야합니다.
Rachel

@ burzum 질문에 대한 수정 내용을 읽었습니다. 당신은 단지 UI를 사용하기위한 규칙 엔진을 원하는 경우에, 나는 엔티티 (풀하게 고려할 것 Player, Monster, Dice의 매개 변수, 등), 그리고 "식"영역으로 드래그 / 드롭 엔티티 조각에 사용자를 허용 뭔가를 설정, 충전 엔터티 (예 : 채우기 player.base_attack)를 사용하고 조각이 서로 맞는 방식에 대한 간단한 연산자를 지정하십시오. 실제로 내 블로그에 게시물을 게시 하여 사용할 수 있는 수학 방정식파싱했습니다 .
Rachel

당신이 묘사하는 @Rachel은 죽은 쉬운 OOP입니다. ROP를 가르치기위한 예로 RPG와 같은 것을 사용하는 많은 예제가 있습니다. 이러한 객체를 가지고 작업하는 것은 쉬운 일이므로 데이터베이스의 데이터를 기반으로 즉시 빌드 할 수 있습니다. 접근 방식의 문제는이 방법이 UI를 통해 어딘가에 정의되어 db에 저장되어 있어야하는 GetEnemyCombatStats ()와 같은 엄격한 규칙입니다. 당신의 기사는 유사 할 것으로 보인다 github.com/bobthecow/Ruler 또는 github.com/Trismegiste/PhpRules .
burzum

0

나는 maptool, 특히 Rumble의 4th ed framework을 살펴볼 것 입니다. 내가 말하고있는 것을 설정하기 위해 본 최고의 시스템입니다. 불행히도 최고는 여전히 끔찍합니다. 그들의 "매크로"시스템은 ... 시간이 지남에 따라 진화했습니다.

"rules parser"에 관해서는 PHP라고해도 편한 프로그래밍 언어를 고수 할 것이다. 시스템의 모든 규칙을 인코딩하는 좋은 방법은 없습니다.

이제 사용자가 THEIR OWN 규칙 세트를 작성할 수있게하려면 고유 한 스크립팅 언어를 구현하려고합니다. 사용자는 자신의 높은 수준의 작업을 스크립팅하여 PHP가 실제로 데이터베이스 값에 영향을 미치는 것으로 해석 한 다음 몇 년 동안 구두로 정교하게 끔찍한 잔인한 시스템이기 때문에 많은 오류가 발생합니다. Jon Purdy의 대답은 바로 공입니다.


0

문제 공간에 어떤 것들이 있을지에 대해 추상적으로 생각하고 어떤 종류의 모델을 찾은 다음 DSL을 기반으로 할 수 있어야한다고 생각합니다.

예를 들어 엔티티 엔티티, 조치 및 이벤트가 최상위 레벨에있을 수 있습니다. 다이 롤은 동작의 결과로 발생하는 이벤트입니다. 액션은 주어진 상황에서 사용 가능한지 여부와 액션을 수행 할 때 발생하는 "스크립트"를 결정하는 조건을 갖습니다. 더 복잡한 것은 다른 동작이 발생할 수있는 일련의 단계를 정의하는 기능입니다.

일단 일종의 개념적 모델이 있다면 (그리고 그것을 표현하기 위해 다이어그램을 작성하거나 다이어그램을 그리는 것이 좋습니다), 당신은 그것을 구현하는 다른 수단을 살펴볼 수 있습니다.

하나의 경로는 구문을 정의하고 antlr과 같은 도구를 사용하여 구문 분석하고 논리를 호출하는 외부 DSL이라는 것을 정의하는 것입니다. 다른 방법은 프로그래밍 언어로 제공되는 기능을 사용하여 DSL을 정의하는 것입니다. Groovy 및 Ruby와 같은 언어가이 공간에서 특히 좋습니다.

피해야 할 함정은 디스플레이 로직을 구현 된 게임 모델과 혼합하는 것입니다. 디스플레이 코드를 모델과 혼합하지 않고 디스플레이가 모델을 읽고 적절하게 표시하도록 투표하고 싶습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.