브레인 만들기
컴퓨터 자리 하나를 플레이하는 .oabrain: 폴더, 모든 매니페스트 키, 태그, 레벨, 전체 시야, 스크립트가 실행되는 곳, 예산, 그리고 중단될 때 일어나는 일.
이 장은 docs/brains/oabrain-standard.md, docs/brains/authoring.md, docs/playing-with-brains.md 문서를 요약합니다. 규범이 되는 텍스트는 이 문서들입니다.
브레인이란
기본값은 계속 엔진의 기본 제공 컴퓨터 플레이어이며, 그 플레이어는 엔진 안에 남아 있습니다. 브레인은 컴퓨터 자리 하나를 플레이하며, 플레이어가 그 브레인을 지정한 자리만 맡습니다. 빈 브레인 ID는 기본 제공 플레이어를 뜻합니다. 브레인이 없는 자리, 맞지 않는 브레인, 중단된 브레인은 모두 그 기본 제공 플레이어가 플레이합니다. Classic은 Lua로 작성되었고 그 플레이어와 똑같이 플레이합니다. 그 플레이어를 문서로 옮긴 것이지, 대체하는 것이 아닙니다.
컴퓨터 플레이어를 자리에 앉히는 기기만 스크립트를 실행하므로, 다른 플레이어는 아무것도 설치할 필요가 없습니다. 다른 기기는 그 자리의 유닛을 그대로 반영합니다. 녹화를 재생할 때는 스크립트를 실행하지 않습니다. 브레인은 Lua 소스와 데이터입니다. 네이티브 코드, 파일, 네트워크, 시계가 없습니다. 전체 시야는 매니페스트의 플래그입니다. 브레인은 이 플래그를 설정할 수 있고, 네트워크 게임에서도 그 상태로 플레이할 수 있으며, 자리에 플래그가 표시됩니다.
패키지
브레인은 .oabrain 파일 하나이거나, 그 파일을 풀었을 때 나오는 폴더입니다. 매니페스트는 모드 프로필과 같은 엄격한 YAML입니다. 문서 하나, 최상위 매핑 하나이며 앵커와 블록 스칼라는 쓸 수 없습니다. 패키지 최상위에 oabrain.yaml이 있습니다. 그 옆의 파일은 다음 중 하나여야 합니다. 이 목록 밖의 파일은 거부됩니다.
my-brain.oabrain플레이어가 받는 파일├─ oabrain.yaml필수 매니페스트, 최대 256 KiB├─ brain.lua진입 스크립트. 기본 이름은 brain.lua입니다. entry로 다른 이름을 지정할 수 있으며, 그 파일은 패키지 안에 있어야 합니다├─ lua/추가 Lua 소스. require는 이 파일만 읽습니다. 각 부분은 소문자, 숫자, _로 이루어집니다├─ nets/매니페스트가 지정하는 네트워크. nets/ 뒤에 .oann으로 끝나는 이름├─ data/데이터 테이블 하나, 폴더 한 단계 깊이: .csv, .tdf, .json, .txt├─ icon.png그림. icon이 지정할 때만 허용됩니다. 이 키가 없으면 목록 밖의 파일입니다├─ README.md최상위의 메모. 게임은 불러오지 않습니다└─ LICENSE최상위의 라이선스. licence라는 이름이나 하위 폴더의 readme는 목록 밖입니다비교할 때는 표준에서 바이트가 일치해야 한다고 정한 곳을 빼고 ASCII 문자의 대소문자를 무시합니다. entry가 다른 파일을 지정하면 brain.lua는 목록 밖입니다. Lua 파일 하나는 최대 1 MiB입니다. 아이콘은 정사각형 PNG이며, 한 변은 최대 256픽셀, 파일 크기는 최대 256 KiB입니다. OA는 브레인을 Brains/ 아래 매니페스트의 ID 폴더에 설치합니다.
매니페스트
리더는 어긋난 규칙을 모두 모으며, 하나라도 어긋나면 매니페스트를 바꾸지 않습니다. 표준에 없는 키는 거부됩니다. 프로필 키는 모드에 속합니다. 뮤테이터 키는 ‘뮤테이터의 키’라는 이유로 거부됩니다. 버전은 따옴표로 감싸세요. 따옴표 없는 1.0은 숫자입니다. 별표도 따옴표로 감싸세요. 따옴표 없는 별표는 YAML 별칭입니다.
| 키 | 필수 | 하는 일 |
|---|---|---|
oabrain | 예 | 형식. 정수 1. 1.0과 따옴표로 감싼 1은 거부됩니다. |
id | 예 | 소문자 케밥 케이스, 1~64바이트. 하이픈은 앞뒤에 오거나 연달아 올 수 없습니다. Brains/ 아래의 폴더 이름입니다. |
name | 예 | 1~64바이트, 제어 문자 없음. 플레이어에게 보이는 이름입니다. |
version | 예 | 따옴표로 감싸며, 뮤테이터 버전과 같이 1~3개 부분입니다(예: "2.0"). 일반 숫자는 거부됩니다. 2, 2.0, 2.0.0은 같은 것으로 비교됩니다. |
author | 예 | 매핑. name은 필수이며 1~128바이트. email은 선택 사항입니다. |
description | 예 | 필수, 1~2,000바이트. 줄 바꿈은 쓸 수 있습니다. 그 밖의 제어 문자는 거부됩니다. 첫 줄을 200바이트로 자른 것이 요약입니다. |
homepage | 아니요 | http 또는 https 주소. |
icon | 아니요 | 패키지 최상위의 그림인 icon.png만 허용됩니다. 다른 것은 거부됩니다. |
tags | 예 | 아래 아홉 가지 태그 중 1~4개, 중복 없음. |
works-with | 예 | 조건 1~32개, 같은 ID는 두 번 쓸 수 없습니다. 별표는 모든 모드와 기본 게임을 뜻하며, 그때는 유일한 항목이어야 합니다. ta-3.1c는 모드 없는 기본 게임입니다. 그 밖의 ID는 모드이며, 버전 범위를 붙일 수 있습니다. |
requires | 아니요 | engine과 expansions만 씁니다. engine은 범위이며, > 기호로 시작하면 따옴표로 감쌉니다. expansions는 번들 ID 1~16개입니다. 브레인은 뮤테이터를 요구할 수 없습니다. |
levels | 예 | 레벨 1~6개. 각 매핑은 정확히 id, name, difficulty로 이루어집니다. |
fullAwareness | 아니요 | true 또는 false. 없으면 false입니다. 따옴표로 감싼 true는 거부됩니다. |
networks | 아니요 | 1~16개, 각각 정확히 id, file, sha256으로 이루어집니다. file은 nets/ 뒤에 .oann으로 끝나는 이름입니다. sha256은 따옴표로 감싼 소문자 16진수 64자리입니다. |
options | 아니요 | 최대 16개, 뮤테이터의 옵션 규칙을 따릅니다. toggle은 true 또는 false, number는 숫자, choice는 그 텍스트입니다. me.options로 읽습니다. |
strings | 아니요 | 최대 16개 언어. 언어마다 name, description, options, labels, levels를 담을 수 있습니다. |
entry | 아니요 | 패키지 최상위의 Lua 파일로, 이름은 소문자, 숫자, _로 이루어집니다. 없으면 brain.lua입니다. |
아홉 가지 태그
태그는 이 아홉 가지 중 하나이며, 바이트 단위로 비교합니다. 공통 태그 규칙을 이미 통과했는데 4개를 넘으면 그것은 별도의 문제로 보고됩니다. 아홉 가지에 없는 태그는 거부됩니다.
| 키 |
|---|
classic |
economy |
rush |
turtle |
air |
naval |
learned |
teaching |
experimental |
레벨과 난이도
levels는 매핑 1~6개의 리스트입니다. 각 매핑은 정확히 id, name, difficulty로 이루어지며 모두 필수입니다. id는 1~32바이트의 소문자 케밥 케이스이며, 같은 id는 반복할 수 없습니다. name은 제어 문자 없는 1~64바이트입니다. difficulty는 easy, medium, hard 중 하나이며 바이트 단위로 일치해야 합니다.
이 세 이름은 값 0, 1, 2입니다. 레벨을 고른 자리는 그 값을 수입 규칙으로 씁니다. 게임이 이미 쓰는 것과 같은 난이도입니다.
전체 시야
fullAwareness는 true 또는 false입니다. 없으면 false입니다. 이 플래그가 있는 브레인은 기본 제공 컴퓨터 플레이어처럼, 안개 속의 자리라면 보지 못할 유닛을 보며, 건설 위치 검사에 배치하는 플레이어가 필요하지 않습니다. 이 플래그는 네트워크 게임에서도 허용됩니다. 라이브러리에는 Total Annihilation의 원래 컴퓨터처럼 맵의 모든 유닛이 보임이라고 표시됩니다. 이 플래그는 매니페스트 자체의 것입니다. 패키지 ID로 주어지지 않으며, Classic에만 주어지는 것들에도 속하지 않습니다.
브레인이 실행되는 곳
컴퓨터 플레이어를 자리에 앉히는 기기에만 패키지가 필요하며, 그 기기만 스크립트를 실행합니다. 자리는 이 기기의 컴퓨터 플레이어입니다. 사람 자리는 거부됩니다. game.mode는 skirmish, campaign, network 중 하나입니다.
| 상황 | 실행되는 것 |
|---|---|
| 스커미시 | 플레이어가 브레인을 지정한 경우, 이 기기가 플레이하는 각 컴퓨터 자리. 빈 ID는 기본 제공 컴퓨터 플레이어입니다. |
| 캠페인 미션 | 캠페인 자리는 플레이어가 설정한 기본 브레인을 따릅니다. 미션이 그 기본값을 무시하지는 않습니다. |
| 네트워크 게임 | 컴퓨터 자리를 소유한 기기가 전체 시야를 포함해 브레인을 실행합니다. 다른 기기는 실행하지 않습니다. |
| 나중에 불러온 저장된 게임 | 저장 파일에는 자리마다 브레인이 기록됩니다. 패키지가 없거나 버전이 다를 때 어떻게 되는지는 표준이 정합니다. |
| 녹화 재생 | 녹화에는 브레인 텍스트가 저장됩니다. 재생은 녹화된 패킷을 적용할 뿐, 브레인을 자리에 앉히거나 훅을 호출하지 않습니다. |
| 데스매치 또는 토너먼트 | 실행할 때 컴퓨터 플레이어를 자리에 앉히지 않습니다. |
자리에서 어떤 브레인이 플레이하는지는 시뮬레이션 해시의 입력이 아닙니다. 앉힌 브레인만 다른 두 경기는 같은 경기 상태 해시를 유지합니다. 모드의 ai.* 수정 항목 값은 그 해시가 다루는 모드 프로필의 일부이므로, 여전히 모든 기기에 전달됩니다.
런타임 예산
브레인은 샌드박스 하나에서 Lua로 실행됩니다. 두 브레인은 모듈, 전역 변수, 예산을 공유하지 않습니다. 스크립트에는 파일, 시계, 환경 변수, 프로세스, 네트워크가 없습니다. 모든 청크는 텍스트로 불러옵니다. pcall과 xpcall로 다 쓴 단계를 살려 둘 수 없습니다. 턴은 자리의 컨트롤러 시점, 유닛 순회 뒤에 이루어지는 적립식 호출 한 번입니다. 훅이 내린 명령은 다음 틱에 효과를 냅니다.
| 예산 | 값 |
|---|---|
| load, fits, start, save, report의 명령 수 | 50,000,000 |
| 틱 하나가 더하는 명령 수 | 2,000,000 |
| 적립할 수 있는 틱 수(현재 틱 포함) | 30, 따라서 잔액은 60,000,000에서 시작합니다 |
| Lua 메모리 | 64 MiB(67,108,864바이트). 단계 사이에 초기화되지 않습니다. |
| 네트워크 메모리 | 64 MiB, Lua 상한과 별도 |
| 턴이 아닌 단계의 실시간, 밀리초 | 10,000 |
| 턴 하나의 실시간, 밀리초 | 250 |
| 문자열 하나, 바이트 | 65,536 |
브레인이 실패할 때
브레인은 훅이나 타이머의 오류, 명령 허용량 소진, 실시간 안전장치, Lua 메모리 상한, 65,536바이트를 넘는 문자열, 자리가 거부하는 불러오기 때문에 중단됩니다. 실패한 턴은 그 턴이 돌아오기 전에 샌드박스를 닫고 훅을 지웁니다. 실패한 턴도 플레이한 것으로 칩니다. 다음 명령 틱에는 훅이 없으므로 기본 제공 컴퓨터 플레이어가 맡습니다. 거부되거나, 시작하지 못했거나, 맞지 않는 브레인은 훅을 갖지 못하므로 처음부터 그 플레이어가 플레이합니다. 알림에는 매니페스트 이름과 160바이트로 자른 이유가 다음과 같이 표시됩니다.
- `{brain} stopped ({reason}); the engine plays this seat on`
- `{brain} could not start ({reason}); the engine plays this seat`
- `{brain} does not fit this game ({reason}); the engine plays this seat`
자리에 고유한 이유가 없으면 이유는 the brain could not be seated입니다. 패배한 플레이어는 더 이상 호출되지 않을 뿐입니다. 샌드박스는 경기와 함께 닫힙니다.