최근 수정 시각 : 2024-02-10 04:25:28

TIS-100

파일:zachtronics_logo.png 의 퍼즐 게임 시리즈
{{{#!folding [ 펼치기 / 접기 ] SpaceChem Infinifactory
TIS-100 SHENZHEN I/O
Opus Magnum EXAPUNKS
MOLEK-SYNTEZ Last Call BBS }}}
TIS-100
파일:external/4d688956c68e1eec30648af0f4db33dbb1fab25a35a345bb5be81069f32fa065.jpg
<colbgcolor=#000000> 개발 Zachtronics
유통 Zachtronics
플랫폼 파일:Windows 로고.svg | 파일:macOS 로고.svg | 파일:Linux 로고.svg | 파일:iOS 로고.svg
ESD 파일:스팀 로고.svg | 파일:GOG.com 로고.svg | 파일:itch.io 로고.svg | 파일:App Store 아이콘.svg
출시 PC
2015년 7월 21일
IOS
2016년 1월 8일
장르 프로그래밍 퍼즐 게임
한국어 지원 미지원
웹사이트 공식 홈페이지
파일:스팀 로고.svg 파일:GOG.com 로고.svg 파일:itch.io 로고.svg
파일:레딧 아이콘.svg
1. 개요2. 스토리3. TIS-100
3.1. 노드3.2. 명령어3.3. 시각화 모듈의 사용법
4. 엔딩5. 기타6. 커스텀 퍼즐

[clearfix]

1. 개요

두뇌고문의 명가 Zachtronics에서 출시한 프로그래밍 게임. TIS-100이라는 의문의 메시지 패싱 병렬처리 아키텍처를 가진 가상의 기계에 어셈블리어 프로그램을 작성하여 퍼즐을 풀어나가는 게임이다. 본격 게임에서도 프로그래밍

TIS-100P라는 이름으로 앱스토어에도 출시했다. 메인 캠페인 퍼즐은 동일하지만 TIS-NET의 퍼즐을 이용할 수 없다.

2016년 11월 18일, 정신적 후속작으로 SHENZHEN I/O가 출시되었다.

2. 스토리

게임을 처음 시작하면 매뉴얼을 읽겠냐는 메세지가 나오며, 매뉴얼을 열면 도전과제 RTFM이 달성된다(...).

매뉴얼의 처음 시작은 주인공의 이모[1]인 도리스(Doris)가 주인공에게 보내는 편지로 시작된다. 편지의 내용은, TIS-100을 만든 주인공의 삼촌 랜디(Randy)가 갑작스럽게 죽음을 맞았으며, 이모는 그의 유품을 정리하던 중 이 장치를 발견하게 되어 주인공에게 이 장치를 보내며 '너라면 너의 삼촌이 무엇을 하고자 했는지 알아낼 수 있을 것이다.'라는 말로 편지가 끝나며 이후 매뉴얼이 시작된다.

이 게임에서 다루게 될 기계장치인 TIS-100은 게임 시작 시점에서 자가진단 세그먼트를 제외한 다른 세그먼트들이 고장난 상태이다. 하나의 세그먼트에는 12개의 노드가 있으며, 주어진 조건에 맞춰 노드에 어셈블리어 소스 코드를 집어넣어 조건에 맞춰 동작시키면 세그먼트가 복구됨과 동시에 다른 고장난 세그먼트들에도 접근할 수 있게 된다. 게임을 진행하다보면 통신을 전혀 할 수 없는 노드들 중에 디버그 버튼이 있는 노드가 있다. 세그먼트 하나당 하나씩은 나오며, 이 노드들을 통해 게임의 배경이 90년대라는 것을 알 수 있으며, 주인공의 삼촌이 작성해놓은 것으로 추정되는 텍스트들을 볼 수 있다.

3. TIS-100

본 게임의 플레이 대상이 되는 기계로 node라는 개별 스칼라 단위의 프로세서가 병렬로 작동하며 각각의 node는 인접한 node와 메시지 패싱으로 통신이 가능한 구조다. node 자체는 주석과 라벨을 제외한 명령어가 13개 밖에 안되는 매우 간단한 프로세서지만 메시지 패싱을 이용하여 인접 코어와 통신하여 병렬연산을 하거나 파이프라인을 만드는 등 다양한 응용이 가능하다.

3.1. 노드

  • 일반 모듈 : 게임 내내 일반적으로 보게 되는 것. 명령어와 값들을 입력받아 이를 수행하는 역할을 한다. 실제로 명령어를 입력하는 모듈은 이거 하나 뿐이다.
  • 스택 메모리 모듈 : 여러 개의 값을 저장하는 모듈. 어느 방향에서 입력을 받기만 하면 그 값을 저장하고, 또 어느 방향에서든 값을 읽으려 하면 그 값을 출력해준다. 쌓인 값들은 반대 순서로 출력되고, 출력된 값은 이 메모리에서 지워진다.
  • 시각화 모듈 : 게임 중반부부터 보게 되는 모듈. 특정한 순서로 값을 입력받아 화면에 도트를 찍는다. 샌드박스 모드에서 이걸 이용해 동굴을 빠져나가는 게임이나 공을 받아내는 게임을 만드는 괴수들도 존재한다. 자세한 사용법은 하단의 '시각화 모듈의 사용법'을 참고하자.

게임에서 등장하는 모듈은 위 세 개이나, 매뉴얼을 보면 다른 몇 개의 모듈이 개발중이었음을 알 수 있다. 랜덤 액세스 메모리 모듈이 가장 유용할 것 같다

3.2. 명령어

아키텍처 구조
  • LEFT, RIGHT, UP, DOWN : 노드의 입출력 방향이다.
  • ANY : 노드의 어느 방향에서든 입력을 받거나 출력할 때 사용한다. 읽을 때는 먼저 들어온 것부터 읽고, 동시에 들어오면 LAST에 기록된 방향을 읽는다. 출력도 마찬가지.
  • LAST : ANY를 사용하여 마지막으로 입력을 받거나 출력한 방향.
  • ACC : 노드별로 하나씩 붙어 있는 레지스터. 값을 넣어두고 더하거나 빼는 등의 조작을 할 수 있다.
  • BAK : ACC의 임시 저장 장소. 역시 노드마다 하나씩 붙어있다. 이 부분은 직접 조작할 수 없고, 명령어 SWP를 사용하여 ACC와 자리를 바꾸거나, SAV를 사용하여 ACC의 값을 복사하는 것만이 가능하다.
  • NIL : 일종의 Null값과 비슷한데, 숫자로는 0으로 취급된다. 이동시키는 값의 목적지가 NIL이라면 그 값은 그냥 지워지고, ACC에 NIL을 옮기면 ACC의 값이 0이 된다.

명령어 세트
  • # : 주석. # 뒤의 글자는 모두 주석이 된다.
  • : : 라벨. 'LOOP:'와 같이 사용한다.
  • ! : 중단점. 이 부분에 도달하면 프로그램의 실행이 일시 정지된다.
  • NOP : 아무것도 하지 않는다. 다른 노드와 타이밍을 맞출 때 넣기도 하며, JRO 명령어를 사용할 때 끼워넣기도 한다. 자세한 설명은 JRO 부분에서 후술.
  • MOV (위치 또는 값), (위치) : 특정한 위치의 값이나 상수를 다른 쪽으로 넘긴다.[2][3][4] MOV 명령어가 실행 중일 때는 값을 입력받거나 출력할 때까지 그 노드의 실행이 중단된다.
  • SWP : ACC와 BAK의 값을 서로 바꾼다.
  • SAV : ACC의 값으로 BAK의 값을 덮어쓴다.
  • ADD (값) : 값을 ACC에 더한다. 'ADD 3'과 같이 사용한다. 숫자 뿐만이 아니라 다른 노드에서 넘어오는 입력을 더할 수도 있다. 'ADD ACC'도 가능하여 ACC의 값을 2배로 만들 수 있다.
  • SUB (값) : 값을 ACC에서 뺀다. 이 외에는 ADD와 동일.
  • NEG : ACC가 음수이면 양수로, 양수이면 음수로 바꾼다.
  • JMP (라벨) : 해당 라벨로 건너뛴다.
  • JEZ (라벨) : ACC의 값이 0이면 해당 라벨로 건너뛴다.
  • JNZ (라벨) : ACC의 값이 0이 아니면 해당 라벨로 건너뛴다.
  • JGZ (라벨) : ACC의 값이 0보다 크면 해당 라벨로 건너뛴다.
  • JLZ (라벨) : ACC의 값이 0보다 작으면 해당 라벨로 건너뛴다.
  • JRO (값) : 현재 명령어가 위치한 라인에서 값 만큼 떨어진 위치에 있는 명령어를 실행한다. 방향은 양수이면 아래 방향, 음수이면 위 방향이다. 예를 들어, 'JRO 0'은 JRO 명령어로부터 아래로 0줄 떨어진 명령어인 'JRO 0'을 실행하게 되므로 해당 모듈의 실행상태가 완전히 정지된다. 이 명령어를 사용할 때 주의해야 할 점이, JRO 명령어가 있는 위치를 0으로 처리하므로 'JRO 1'과 같은 명령어는 그냥 아무것도 안하고 다음 명령어를 수행하는 NOP 명령어와 다를게 없다. 또한, JRO 명령어로는 아무리 큰 값을 입력해도 마지막 줄에 있는 명령어를 건너뛸 수가 없다. 따라서 음수값을 넣어 맨 위로 보내거나 맨 아래에 NOP 명령어를 삽입하여 해결할 수 있다. 여담으로, 'JRO ACC'와 같이 ACC를 사용할 수도 있다. 가장 핵심적인 기능은 JRO UP, JRO RIGHT 등과 같이 주변 노드에서 받아온 값을 곧바로 JRO에 대입하는 방식이다. 노드의 ACC에 저장된 값을 그대로 보전하면서 다른 노드와 동기화된 동작을 가능케하는 매우 강력한 명령어이다. 도전과제 UNCONDITINAL은 플레이어가 이러한 풀이 방식을 습득하도록 유도하고 있으며, 이 방법을 아냐 모르냐에 따라 후반 과제들의 난이도가 천양지차로 달라진다.
  • HCF[5] : 기계를 강제로 종료시킨다. 물론 염소 시뮬레이터 마냥 완전히 꺼지지는 않고, 곧바로 기계가 다시 실행된다. 이 명령은 숨은 명령으로, 이 명령을 실행하는 일 자체가 스팀 과제로 등록되어 있다.

3.3. 시각화 모듈의 사용법

시각화 모듈은 크게 좌표설정, 색상입력(반복), 입력 종료의 세가지 단계를 통해 이미지를 출력한다.
  • 좌표설정 : x좌표와 y좌표를 순서대로 입력받는다. 입력받은 좌표가 이미지 출력의 시작점이 된다. 좌표는 왼쪽 위 모서리를 (0, 0)으로 잡으며, x좌표는 0~29의 30칸, y좌표는 0~17의 18칸 범위를 가진다.[6] 음수는 입력 종료에 해당하므로 입력할 수 없다.
  • 색상입력 : 좌표가 설정된 이후부터 입력 가능하며, 설정된 좌표로부터 오른쪽으로 한 칸씩 이동하며 입력된 색상의 이미지를 하나씩 출력한다. 색상은 0-검정[7], 1-어두운 회색, 2-밝은 회색, 3-흰색, 4-빨간색 으로 대응된다. 단, 콘솔의 가로길이인 30을 초과하더라도 자동으로 줄 바꿈 처리가 되지 않으므로 두 줄 이상 이미지를 출력하려면 반드시 입력을 종료한 후 좌표를 새로 설정해야 한다.
  • 입력 종료 : 언제든지 0보다 작은 값을 입력하게 되면 입력이 종료된다. 입력이 종료된 이후에는 다시 시작좌표를 설정해야 이미지가 출력된다.

4. 엔딩

이 문서에 스포일러가 포함되어 있습니다.

이 문서가 설명하는 작품이나 인물 등에 대한 줄거리, 결말, 반전 요소 등을 직·간접적으로 포함하고 있습니다.



TIS-100의 세그먼트를 일정 개수 이상 수리하면, TIS-NET이 열리면서 새로운 25개의 세그먼트에 접근할 수 있다. 이 세그먼트에도 하나씩 DEBUG 버튼이 달린 노드가 있는데, 이 버튼을 누르면 두 사람의 대화로 추정되는 내용이 나온다. 이후에는 주인공의 삼촌인 Randy까지 합세하면서 전개가 점점 급박해지는데, 이 내용을 해석해보면 TIS-100의 정체를 알아낼 수 있다.

TIS-100은 그냥 컴퓨터가 아니라, 다른 비슷한 평행세계들을 연결하기 위한 더 큰 시스템의 일부였다. 평행세계는 일반적인 방법으로 알아낼 수 없지만, TIS-100을 양자역학에서 말하는 '관측'의 도구로 사용함으로써 다른 TIS-100이 있는 세계를 '확정'하고, 그 세계로 포탈을 열어 그 세계에 있는 자원을 가져오려 한 것. 이 때문에 TIS-100끼리 양자적으로 얽혀있어서 서로 다른 연도, 다른 나라의 세 명이 같이 대화할 수 있었던 것이다.[8] 이를 피하기 위해서 이들은 TIS-100의 프로그램들을 할 수 있는대로 파손시켜 그들이 자신들의 세계를 관측하지 못 하게 막으려 한다.

맨 마지막 세그먼트를 풀면 이들이 마지막으로 남긴 대화를 볼 수 있다. 내용인즉, 이들은 결국 포탈을 막는 데 성공했으나, 그 부가적인 효과로 시간의 루프가 만들어졌다. 즉, 자신들이 찾아낸 TIS-100은 자신들이 파손시킨 TIS-100이었고, 이 세 명은 모두 이 루프를 영원히 떠돌게 되었다. 이 때 주인공의 삼촌인 랜디가 자신의 TIS-100을 창고에 넣어놨다고 말하는데, 이게 바로 플레이어가 다루고 있는 TIS-100이다.

이 이전에도 설정을 뒷받침하는 근거를 찾을 수 있는데, 대표적으로 메인 화면에서 F2를 누르면 나오는 메시지에 미 국방부와 함께 양자 정보 과학 연구소가 언급된다. 메모리 변조가 발견되는 즉시 국가안보국에 신고하라는 내용도 있는 것으로 보아, TIS-100 자체가 국가 기밀 기계로 취급된 것으로 보인다. 덤으로, 이 화면에서 독수리를 클릭하면 스팀 과제가 걸린 숨은 퍼즐을 풀 수 있다.

5. 기타

일반인 기준으로는 충공깽한 진입 난이도를 자랑한다.[9] 일단 튜토리얼이 따로 없고 사용자 매뉴얼만을 제공하고 있다. 문제는 매뉴얼이 정말 TIS-100 프로그램 개발에 쓰는 레퍼런스 매뉴얼이라 게임플레이에 대한 안내가 단 한줄도 없다는 것. 더불어 이 레퍼런스를 다 이해 못하면 플레이가 어렵다. 그러니 일단 플레이하려면 게임과 매뉴얼을 잘 읽어보고(...) 알아서 이해한 뒤 플레이해야 한다. 단 어셈블리는 매우 간단하고 명령어 종류도 적어서 이해하는 것 자체는 크게 어렵지 않다. 매뉴얼을 읽는 것이 귀찮다면 'F1'를 눌러서 간단히 정리된 명령어 목록을 볼 수 있다.

이 게임에는 '정답'이 없다. 일단 과제를 성공시키고 나면 지금까지 플레이어들의 통계와 자신의 위치를 보여줄 뿐... 즉 '얼마나 효율적으로 프로그램을 짤 수 있는지'를 보는 게 목적이다. 일례로 도전과제중 'PARALLELIZE'라는 도전과제는 신호 증폭기(SIGNAL AMPLIFIER) 세그먼트를 100 사이클 이내로 푸는 것이다.[10]

몇몇 과제는 버그가 있거나 난이도가 너무 높아서 그런지 업데이트되면서 짤렸다. 예를 들어 주어진 수가 소수인지를 판단해야 하는(...) 'PRIME DETECTOR' 과제는 삭제되었고, 입력값에서 연속된 특정 패턴을 찾는 'PATTERN DETECTOR'는 과제로 제시되는 패턴이 좀 더 간단한 것으로 수정되었다. 원래 과제는 입력에서 1, 5, 4가 연속으로 나오면 1을 출력하라는 것인데, 1, 1, 5, 4나 1, 5, 1, 5, 4 같은 함정 문자열[11] 탓에 패턴 체크 난이도가 어려운 편이었다.[12] 현재는 0, 0, 0이라는 상대적으로 쉬운 패턴이 제시되고 있다.[13] 업데이트 이전의 과제가 게임상에서 아예 사라진 것은 아니고, PRIME DETECTOR는 주어진 입력을 소인수분해하여 모두 나열하는 PRIME FACTOR DETECTOR로, PATTERN DETECTOR는 매 테스트마다 새로 주어지는 임의의 패턴을 체크하는 DYNAMIC PATTERN DETECTOR로 보다 심화된 과제로 남아있다.

본래 메시지 패싱이 병렬 컴퓨팅에 적합한 구조라고는 해도 TIS-100은 queue를 이용하여 비동기 통신을 하는 고급 메시지 패싱 기계가 아니기 때문에 데드락을 포함해 오만가지 거지같은 일들을 다 당해볼 수 있다.

해외 유저포럼을 보면 플레이어 가운데 프로그래머가 압도적으로 많다는 느낌이다. 당연한건가

6. 커스텀 퍼즐

열혈한 유저들의 끊임없는 고통을 보장해주기 위해 무려 토너먼트(...)를 주최하며 실제 프로그래밍 문제들을 구현한 커스텀 퍼즐들이 있다.

가끔씩 내가 똑똑하다는 자만심이 들 때마다 한번씩 풀어주면 겸손해지는 마법이 걸려있다.[14]

설치법은 C:/Users/유저명/내 문서/My Games/TIS-100/0/custom 폴더안에 LUA 파일을 넣어주면 된다.

2018년도 공식 토너먼트 퍼즐 모음집
유저 퍼즐 모음집


[1] 원문에는 Aunt라고 적혀있다. 편지 내에서 주인공과의 관계는 정확히 알 수 없다. [2] 예를 들어 'MOV UP, DOWN'은 노드의 위에서 받는 입력을 아래의 노드로 패스한다. [3] ANY를 넣으면 모든 방향에서의 입력을 받는다. [4] MOV 0,DOWN과 같이 아예 상수를 넘기는 것이 가능하다. [5] Halt and Catch Fire의 약자이다. 시스템 360을 위해 농담조로 작성되던 어셈블리어 용어집에서 유래하여, 한 번 실행하면 CPU가 하드 리셋 등 물리적 수단을 동원하지 않고는 탈출할 수 없는 무한 루프 빠지는 일련의 명령어를 의미하는 단어가 되었다. Catch fire (불이 붙음)은 비유적 의미로, 아무 짓도 안 하는데 CPU는 최대 출력이니 언젠가는 타오르지 않을까 하는 농담이다. [6] 즉, 왼쪽 상단 끝의 좌표가 (0, 0), 오른쪽 하단 끝의 좌표가 (29, 17)이 된다. [7] 검은색이 바탕이라 안찍히는 것 같지만 제대로 찍히고 있다! [8] 쉽게 풀어 설명하면, 원자의 '상태'는 관측하기 전까지는 여러 가능성이 공존하고 있다가, 관측을 하면 하나의 상태로 확정된다는 논리를 확장한 것이다. 포탈을 안정되게 여려면 어떤 세계로 향하는 지 정확히 알아야 하는데, 그러기 위해서 TIS-100을 사용하여 다른 세계를 관측, 확정시킨 것. 본격 스토리까지 두뇌고문 [9] 프로그램이 아니라 퍼즐로 생각하고, 좀 불친절한 게임이라는 점을 감안하면 그다지 진입 난이도가 높은 편은 아니다. [10] 방법을 대강 설명하자면 주어지는 입력값을 두 방향으로 분산시켜서 한 번에 두 개를 처리하는 것이다. [11] 2, 3번째 패턴 체크 실패와 동시에 1번째 패턴 체크 성공으로 회귀되는 동작은 생각은 쉽지만 구현이 매우 복잡해진다. [12] 그렇다고 풀이가 불가능한 과제는 아니다. 예를 들어, 숫자 1을 출력하는 경우는 오직 3개의 문자열 중 마지막 4가 체크에 성공한 시점이므로, SIGNAL WINDOW FILTER 과제에서처럼 최근 몇개의 입력값을 보존하고 있다가, 새로 들어온 입력값 4가 감지되었을 때 비로소 직전의 두 입력값을 첫번째 패턴, 두번째 패턴과 비교하는 방식을 사용한다면 최소한의 노드와 코드만으로 구현이 가능하다. 쉽게 말해 1, 5, 4 순서로 체크하는 것이 아니라, 4, 5, 1 순서로 체크하는 것이다. [13] JEN, JNZ만으로 손쉽게 판별이 가능하므로, 뺄셈을 사용한 크기 비교 같은 복잡한 과정이 일절 필요가 없는 패턴이며, 0 이외의 값이 들어왔을 경우 그 지점에서 패턴 연속성은 완전히 종결지어지므로 기존 과제의 1, 1, 5, 4나 1, 5, 1, 5, 4 같은 경우를 감안할 필요가 없다. [14] 퍼즐을 열어보면 어렵다는 생각보다 파일이나 퍼즐에 오류가 있는거 아니냐는 생각부터 드는 경우가 부지기수이다.