기본 콘텐츠로 건너뛰기

추천 가젯

Tmux 환경에서 Vim 컴파일 시 발생하는 termio/termios 감지 오류 해결 방법

 리눅스 환경에서 소스코드를 직접 빌드하다 보면 의외의 환경 변수나 터미널 세션 설정 때문에 엉뚱한 빌드 에러를 마주할 때가 있습니다. 대표적인 예로 Tmux 세션 내부에서 Vim 소스를 컴파일할 때 발생하는 termio/termios 감지 오류 가 있습니다. 이번 글에서는 해당 에러가 발생하는 원인과, 단순한 clean 으로는 해결되지 않는 이유 및 올바른 해결 방법을 정리합니다. 1. 문제 원인 Vim의 소스 코드 빌드 과정( configure )은 시스템이 System V 계열인지 Linux 계열인지 판별하기 위해 termio.h 와 termios.h 헤더 파일 및 터미널 인터페이스를 검사(Probe)합니다. 하지만 Tmux 내부(세션 안)에서 컴파일을 진행할 경우 , Tmux가 제공하는 PTY(Pseudo-Terminal) 환경과 TERM=screen 등의 특수한 환경 변수 영향으로 인해 Autoconf가 터미널 인터페이스를 검출하는 과정에서 오동작을 일으킵니다. 그 결과, 실제 시스템 조건과 무관하게 설정 에러를 발생시키게 됩니다. 2. 왜 make clean 으로는 해결되지 않을까? 일반적인 개발 과정에서는 빌드가 꼬였을 때 make clean 을 실행하곤 합니다. 하지만 make clean 은 컴파일된 오브젝트 파일이나 바이너리( .o 파일 등)만 삭제할 뿐, Autotools가 시스템 환경을 탐색한 결과로 남긴 캐시( config.cache 또는 내부 매크로 변수)나 설정 파일들은 그대로 유지 합니다. 일반적인 상황에서는 시스템의 하드웨어/OS 정보가 바뀌지 않기 때문에 이 잔여물이 문제가 되지 않습니다. 그러나 Tmux나 Screen 같은 터미널 멀티플렉서 환경에서 탐색된 왜곡된 정보가 캐시에 박혀버리면, 나중에 Tmux 외부(일반 터미널)로 나와서 빌드를 시도해도 이전의 오염된 캐시 때문에 계속해서 오류가 발생하게 됩니다. 3. 해결 방법 이 문제를 해결하기 위해서는 반드시 Tmux 외부 환경 에서 기존의 오염된 설정 파일을 ...

[리버싱 일기/리뉴] 랑그릿사 2: 상태 이상 마법의 확률 공식과 참(Charm)의 메커니즘

랑그릿사 2에서 뮤트, 슬립, 참과 같은 상태 이상 마법들은 단순히 운에 의해 결정되는 것이 아닙니다. 필자는 기드라(Ghidra)를 통해 Apply_Spell_To_Target(0x40ffd3) 함수 내의 switch-case문을 분석하여, 이 마법들이 성공하기 위해 통과해야 하는 수학적 관문들을 찾아냈습니다.

1. 상태 이상 마법의 핵심: 확률 산출 공식 (0x0040f54d)

뮤트(Mute)를 비롯한 대부분의 확률형 마법은 공통적인 성공 확률 함수를 공유합니다. 분석 결과, 이 함수는 시전자와 방어자의 레벨 차이를 마법 방어력(MDF)에 보정하는 방식을 취합니다.

  • 면역 체크: 방어자의 MDF가 100이면 즉시 실패를 리턴합니다.

  • 보정 수치 산출: 100 - ((공격자_LV - 방어자_LV) << 2)

    • 이를 정리하면 **[MDF - (레벨 차이 × 4)]**라는 레벨 보정 마방치가 나옵니다.

  • 난수 비교: 0~100 사이의 난수(rng % 101)를 발생시켜, 이 값이 위에서 구한 보정치보다 크거나 같으면 성공합니다.

[성공 확률 분석표]

동일 레벨 기준, 마방이 99일 때 성공 확률은 2/101(약 2%)로, 일반적인 예상보다 2배가량 높게 설계되어 있습니다.

마법 방어력(MDF)레벨 차 -8 (방어자 우세)레벨 차 0 (동일)레벨 차 +8 (공격자 우세)
2048.5%80.2%100.0%
608.9%40.6%72.3%
990.0%2.0%33.7%

필자의 분석에 따르면, 마방이 20으로 낮아도 레벨 차이가 크면 절반은 저항하며, 반대로 마방이 99로 높아도 레벨 차이로 찍어누르면 1/3 확률로 마법이 걸리게 됩니다.

2. 마법별 특수 제약 조건

  • 뮤트(Mute): 지휘관(Army Number 0 또는 7)에게만 걸립니다. 용병에게 강제로 거는 것은 로직상 불가능합니다.

  • 슬립(Sleep): 타겟의 종족값이 '불사(Undead)'인 경우 하드코딩된 로직에 의해 완전 면역 처리됩니다.

  • 존(Zone): 마법이 실패할 경우 특수한 함수를 호출하여 메모리상의 특정 좌표 값을 이동시키는데, 이는 AI가 실패 후 다음 행동을 결정하기 위한 좌표 저장으로 추측됩니다.

3. 가장 복잡한 난제: 참(Charm)과 진영 변조

참 마법은 단순히 상태 이상 플래그를 세우는 것을 넘어, 유닛의 소속(Camp)을 통째로 흔듭니다. 필자가 추적한 b1(원래 진영)과 b2(현재 진영)의 로직은 다음과 같은 구조를 가집니다.

  1. 진영 백업: if(b1 == 0) b1 = b2; (참이 처음 걸릴 때 원래 진영 정보를 b1에 백업)

  2. 진영 변조: b2 = 시전자의_진영; (현재 소속을 시전자 쪽으로 강제 변경)

  3. 해제 로직: 턴이 돌아올 때마다 지휘관의 MDF 확률로 자가 해제를 시도합니다. 성공 시 b2 = b1; b1 = 0; 과정을 거쳐 원래 진영으로 복귀합니다.

흥미로운 점은 자가 회복 루프가 20개의 포스(Force)를 대상으로 돈다는 것입니다. 이는 전장에 참여하는 전체 지휘관 수와 밀접한 관련이 있어 보입니다. 참이 걸린 적군이 우리 턴에 회복 효과를 받는 등 기묘한 현상이 발생하는 이유도 이 진영 번호 변조 로직 때문일 가능성이 큽니다.

맺으며: 리버싱으로 본 개발자의 설계

분석을 진행할수록 _run_flag_apply의 중요성이 다시금 확인됩니다. AI는 마법을 실제로 시전하기 전, 이 모든 확률 계산과 진영 변조의 결과값을 '가상'으로 미리 돌려보고 최적의 타겟을 선정합니다.

참 마법의 진영 변조 로직은 아직 미궁에 빠진 부분이 많지만, Absolute_Camp와 같은 열거형(enum) 값을 정의하고 사용처를 전수 조사한다면 랑그릿사 2의 진영 시스템 전체를 파악할 수 있을 것입니다.

댓글