1.레시피 정보를 추출한다
2.추출한 레시피 정보를 정리한다. 레시피의 생산품, 재료를 정리해야한다
a라는 레시피가 b,c를 재료를 이용해서 c,d,e를 생산한다고하면
c->a, d->a,e->a로 가도록 매핑 테이블에 추가한다.
item | recipe
c | a
d | a
e | a
이런식으로
3.모든 레시피에 대하여 반복하여 매핑 테이블을 완성한다.
4. getRawIngredient라는 함수를 만든다고 치자
이 함수는 특정 레시피를 인자로 받는다.
이 레시피가 만약 재료로 f, g, h를 요구한다고 치자
그럼 각각 f, g재료에 대하여 위의 매핑테이블을 참고한다.
만약 f라는 재료에 대해 위에서 만든 매핑테이블을 참고했을때 해당하는 레시피가 0개면 그것은 원재료다. f를 리턴리스트에 추가한다.
g라는 재료에 대해 매핑테이블을 참고했을 때 해당하는 레시피가 2개이상이면 어떤 레시피를 선택해야할지 알 수 없으므로 그냥 자기자신 g를 리턴리스트에 추가한다.
h라는 재료에 대해 매핑테이블을 참고했을 때 해당하는 레시피가 딱 1개면 그 레시피를 다시 getRawIngredient로 재귀호출한다.
이렇게 하면 순환하는 레시피가 없다면 각 레시피의 원재료를 알 수는 있다.
5. 추가로 고려해야하는 것이 있다
순환하는 레시피가 있다고 치면 위의 함수는 무한루프를 돌게 될 것이다
묘목1 => 목재1
목재1+물10 => 묘목5
이런 레시피가 있다고 가정을 하자
만약 목재 레시피를 얻고자 위 함수 getRawIngredient를 호출하게 된다면 묘목의 레시피에 대해서 getRawIngredient를 재귀호출할 것이다
그런데 묘목의 레시피에는 또 목재가 있기 때문에 목재에 대해 다시 getRawIngredient를 호출하게 될 위험성이 있다.
목재1
=>묘목1
=>목재0.2+물2
=>묘목0.2+물2
=>(목재0.04+물0.4)+물2
=>(묘목0.04+물0.4)+물2
=>((목재0.008+물0.08)+물0.4)+물2
=>...
목재의 묘목의 목재의 묘목의 목재의 묘목의 목재의 묘목의... 레시피를 알아내기 위해 무한루프를 돌것이다.
이걸 막기위해선 getRawIngredient를 호출할때 현재 방문했던 아이템들의 정보를 같이 전달해야한다.
만약 이미 방문했던 아이템이라면 더이상 재귀호출을 하지 않고 그대로 그 아이템을 리턴해서 무한루프를 막아야한다.
이게 잘 적용된다면 목재의 레시피 탐색은 이렇게 될것이다
목재1
=>묘목1
=>목재0.2 + 물2 //목재는 이미 방문했던 아이템이기 떄문에 더 이상 탐색하지 않음
6. 여기까지 처리하면 무한루프가 발생하지는 않을 것이라고 생각한다.
하지만 고려할게 또 있다
원유100=>윤활유100 을 만드는 레시피가 있다고 가정하고 이 외에는 윤활유 없는 레시피가 없다고 쳐보자
그런데 윤활유는 배럴링을 할 수가 있다고 치자
그럼 사실상 윤활유를 얻는 방법은 원유를 통해 얻는 방법밖에 없지만 배럴링이라는 요소때문에 게임적으로 레시피는 2개가 된다.
그렇다면 getRawIngredient를 호출할 때 레시피가 2개 이상이기 때문에 더 이상 탐색하는 것을 포기할 수도 있다
즉 배럴링 레시피는 좀 예외처리를 할 필요가 있다는 뜻이다.
7. 위와 같이 레시피의 원재료를 알기위해서는 처리할게 꽤나 많다
아직도 뭔가 빠진부분이 있을 수 있고 그렇다면 제대로 된 원재료를 추출해 낼 수 없을 것이다.
아래는 샌드박스에서 확인한 한 엔밥 레시피의 모습이다.
...?
단지 산소,수소를 얻고싶었을 뿐인데 재료에 정제수가 들어간다는 이유 하나때문에 저 많은 재료와 3시간이 걸린다고 대환장쇼를 하고 있다
4번에서 설명했듯이 정제수를 얻는 중복레시피가 있으면 더이상 재료탐색을 그만두고 반환을 해야하는데 아무래도 인게임에서는 다른 방식으로 구현이 되어버린듯 하다
8. 요약
중복레시피 처리해야한다
배럴링 레시피는 중복레시피에서 제거해야한다
순환하는 레시피도 처리해야한다
윽.... 그냥 손으로 베껴적는게 나을듯. 생각보다 엄청 복잡하네