Game Programming Gems 7

1.1 연령 및 비용 측정을 통한 효율적인 캐시 교체

  • 연령 알고리즘과 페이지 교체 비용을 결합해 캐시 뒤엎기 부담과 캐시 페이지 재적재 추가 부담을 줄인다.
  • 캐시 알고리즘 소개할 때, 강약점 분석을 덧붙여 좋았다.

연령 알고리즘

| 프레임 1 | 00000001 | 쓰임      |
| 프레임 2 | 00000010 | 쓰이지 않음 |
| 프레임 3 | 00000101 | 쓰임      |
| 프레임 8 | 01011001 | 쓰임      |
  • 프레임 별 사용 히스토리 기록
  • 이 정보로 APC(Age Percentage Cost) 계산
  • 오래된 텍스처 편애
    • APC가 50%를 넘기면 캐시에서 잘 밀려나지 않음
  • 확장해서 사용

페이지 교체 비용

  • 캐시 페이지를 새로운 자료로 채우는 데 드는 비용
  • 텍스처가 실제로 쓰이는지 여부나 크기를 기준으로 하는 등 사용자가 정의

캐시 뒤엎기(cache thrash)

  • 필요한 페이지 개수가 캐시 크기를 훨씬 넘길 때 발생
    • 흔히 2배 이상
  • 저장 공간을 마련하려고 캐시 전체가 비워지는 현상
  • 시나리오 중 최악

캐시 교체 알고리즘

OPT

  • 이상적인 최적의 알고리즘
  • Belady’s Min이라고 부르기도 함
  • 다른 알고리즘 벤치마크에 사용

LRU

  • least recently used
  • 가장 오랫동안 쓰이지 않는 페이지 교체
  • 캐시 뒤엎기가 과하게 발생하는 경향

MRU

  • most recently used
  • 제일 최근 교체된 페이지를 교체

MRU, LRU 혼합

  • john carmack이 제시
  • LRU를 사용하다가 매 프레임마다 페이지를 폐기하는 시점부터 MRU 사용
  • 캐시 뒤엎기를 방지

NFU

  • not frequently used
  • 페이지마다 접근 횟수를 관리해서 가장 덜 쓰인 페이지를 교체
  • 페이지 접근 횟수가 접근 패턴을 잘 반영하지 않는 문제점
    • 초반에만 접근하고 뒤에 접근 안 하는 페이지와 지속적으로 접근하는 페이지가 접근 횟수가 같다면 구분할 방법이 없다.

저자

  • Efficient Cache Replacement Using the Age and Cost Metrics - Cold McAnlis

1.2 고성능 힙 할당자

작은 할당자

template<class T> inline T* align_down(T* p, size_t a) {
    return (T*)((size_t)p & -(int)a);
}
static inline page* ptr_get_page(void* ptr) {
    return (page*)(align_down((char*)ptr, PAGE_SIZE) +
                   (PAGE_SIZE - sizeof(page)));
}
  • memory alignment가 필요.
    • 속한 page를 주소 연산으로 간단히 구함
  • 풀 스타일 할당자 (pool-style allocator)

큰 할당자

  • 검색 복잡도 O(log(N))을 보장하는 적흑트리(red-black tree) 사용
  • 노드에 이전/다음 포인터 추가
    • 회전 및 선행 노드 접근을 간단하게 만들기 위해

할당자 조합 방법들

  • 메모리를 해제할 때 어디에서 할당된 지 알아야 한다.
  • 페이지 접근을 해보고 되면 작은 할당자
  • 통 색인과 페이지 정보 주소로 해시 값을 생성
  • 그 외 다른 방법 소개

저자

  • High Performance Heap Allocator - Dimtar Lazarov

reference

1.3 웹캠 기반 비디오 게임을 위한 광류 응용

  • 광류(光流, optical flow)는 동영상 시퀀스의 연속된 프레임들의 픽셀 운동을 서술하는 벡터 배열

첫 번째 방법 : 이미지 차이

  • 이전 이미지에서 현재 이미지를 빼서 활성 픽셀을 식별

두 번째 방법 : 운동 내력(motion history)

  • 이전 프레임 뿐만 아니라 최근 프레임의 활성 픽셀을 기억

세 번째 방법 : Lucas-Kanade 알고리즘

저자

  • Optical Flow for Video Games Played with Webcams - Arnau Ramisa, Enric Martí, Enric Vergara

1.4 다중 플랫폼 스레드 관리 엔진의 설계와 구현

  • 다중 플랫폼 스레드 관리 시스템(threading system) 구현 소개
  • 소스 코드도 첨부되어 있어서 구현하기 전 참고

저자

  • Design and Implementation of a Multi-Platform Threading Engine - Michael Ramsey

1.5 꿀벌과 게이머를 위해: 육각 타일 다루기

육각 타일 장단점 소개

정사각형 타일 단점

  • 변을 공유하는 타일만 이웃으로 쳐야 할 지, 아니면 꼭지점을 공유하는 타일도 이웃으로 쳐야하는지 애매함이 존재
  • 이동 방법에 따라 거리가 최대 41% 차이

육각 타일 장점

  • 변을 공유하는 타일은 이웃
  • 이동 방법에 따라 거리가 최대 15% 차이

육각 타일 단점

  • 좌표축으로 삼을 수 있는 대칭축 방향들이 12가지
  • 정수가 아닌 좌표를 사용하는 직교 좌표계 혹은 한 축이 기울어진 좌표계 중 하나를 선택해야 함

저자

  • For Bees and Gamers: How to Handle Hexagonal Tiles - Jörn Loviscach, Thomas Jahn

reference

1.6 세포자동자에 기초한, RTS 게임을 위한 스케치 기반 인터페이스

마우스로 유닛을 선택해 명령을 내리는 방식 대신 스케치 기반 인터페이스를 소개.

스케치를 격자에 속도로 반영

  • 격자에 스케치 거리를 기반해 속도를 저장
  • 주기마다 합계 세포자동자를 사용해 갱신

합계 세포자동자(totalistic cellular automaton)

  • 칸이 연속적인 값을 가짐
  • 이웃 관계가 단순
  • 이웃 값들 평균을 사용해 갱신 규칙이 간단

저자

  • A Sketch-Based Interface to Real-Time Strategy Games Based on a Cellular Automaton - Carlos A. Dietrich, João L. D. Comba, Luciana P. Nedel

1.7 1인칭 슈팅 게임을 위한 발 기반 항행 기법

ARTookKit과 웹캠을 사용한 발 기반 항행 기법을 소개

저자

  • Foot Navigation Technique for First-Person Shooting Games - Daniela G. Trevisan, Luciana P. Nedel, Marcus Aurelius C. Farias

1.8 함수 지연 호출 시스템

함수를 바로 호출하지 않고 관련 정보를 저장하고 이후에 필요할 때 호출하는 시스템을 소개

저자

  • Deferred Function Call Invocation System - Mark Jawad

1.9 다중 스레드 작업 및 의존성 시스템

  • 작업(job) 시스템.
  • API로 의존성을 설정
    • 의존성을 카운팅해서 의존된 작업이 끝나면(의존 횟수 : 0) 작업을 시작

저자

  • Multithread Job and Dependancy System - Julien Hamaide

1.10 고급 디버깅 기법들

미니덤프, 스택 오버플로우, 메모리 누수에 관한 간단한 팁.

저자

  • Advanced Debugging Techniques - Martin Fleisz

2.1 난수 만들기

난수 발생기의 기초와 여러 주요 알고리즘들(mersenne twister, LFSR113, LFSR258, Well algorithm, …)을 개괄

저자

  • Random Number Generation - Chris Lomont

2.2 게임을 위한 빠른 범용 반직선 질의

  • KD트리 (k-dimensional tree) 설명
  • BSP 트리처럼 공간을 재귀적으로 두 부분으로 분할해가는 구조이나 BSP 트리와는 다르게 축에 정렬된 분할 평면을 사용

저자

  • Fast Generic Ray Queries for Games - Jacco Bikker

2.3 최원 자질 맵을 이용한 빠른 강체 충돌 검출

전처리에서 표본 방향으로 질량 중심(center of mass)에서부터 가장 멀리 떨어진 vertex 정보를 저장한 맵을 생성해 충돌 검출에 사용.

저자

  • Fast Rigid-Body Collision Detection using Farthest Feature Maps - Dillon Sharlet, Rahul Sathe

2.4 투영 공간을 이용한 기하 계산의 정밀도 향상

투영 공간으로 표현함으로써 계산 정밀도를 높이는 방법을 설명. 접근이 신선하다.

생각 흐름

  • floating-point error 때문에 최소 오프셋(주로 입실론)을 사용해 판정.
  • false-positive 결과를 낼 수 있기 때문에 견고함이 떨어짐.
  • 정수 연산만 사용하는 것도 방법이지만 정수를 사용한 선분의 교점이 반드시 정수 좌표가 되리란 보장이 없다.
  • 유리수 연산을 사용하는 방법도 있지만 벡터 당 여섯 개의 정수 값들을 사용해야 함.
  • 개수를 줄일 수 있을까? 투영 공간을 사용하자 그러면 정수 개수를 넷으로 줄일 수 있고 결국 유리수 연산이 된다. (x, y, z, w)
  • 모든 연산은 벡터 비교, 외적, 내적. 즉 덧셈, 뺄셈, 곱셉으로 이루어져 모두 정수였다면 결과도 정수.

저자

  • Using Projective Space to Improve Precision of Geometric Computations - Krzysztof Kluczek

2.5 XenoCollide: 복잡한 충돌을 간단하게 처리하기

민코프스키 관문 정련(Minkowski Portal Refinement, MPR) 기법에 기초한 알고리즘인 XenoCollide 소개

민코프스키 차분 (Minkowski difference)

  • 볼록 도형에서 다른 볼록 도형을 빼서 생긴 도형
  • 겹치면 민코프스키 차분에 원점이 포함. 겹치지 않는다면 원점을 포함하지 않는다.
  • 모든 점에서 다른 모든 점을 빼기 위한 비용이 비싸서 받침함수를 사용

XenoCollide 주요 특징

  • GJK (Gilbert–Johnson–Keerthi) 충돌 검출 알고리즘과 주요 부분들에서 비슷
  • GJK에 비해 간단하고 기하학적이며 분기 판정의 횟사가 적다. 그리고 충돌 여부뿐만 아니라 세부사항도 알아낼 수 있다.

저자

  • XenoCollide: Complex Collision Made Simple - Gary Snethen

reference

2.6 변환 의미론을 이용한 효율적인 충돌 검출

  • 트랜스폼은 scale, rotation, translation의 곱으로 표현. 여기에 착안하면 역행렬을 제곱근 계산 없이도 구할 수 있다.
  • 트랜스폼을 분해하면 교차 판정을 할 수 있는 space는 총 7(3 + 3 + world space)개가 된다. 이 중 하나를 선택해서 판정을 수행하는 방법을 소개.

저자

  • Efficient COllision Detection Using Transformation Semantics - Creto Augusto Vidal, Joaquim Bento Cavalcante-Neto, José Gilvan Rodrigues Maia

2.7 삼각 스플라인

  • 직선과 완벽한 원호(arc) 모두를 만들어 낼 수 있다.
  • 삼차 스플라인(cubic spline)으로는 완벽한 원호가 불가능
  • cos, sin이 내부에 쓰이고 마지막 항 계수인 d를 0으로하면 타원 공식이 나온다

저자

  • Trigonemtric Splines - Anders Hast, Ewert Bengtsson, Tony Barrera

reference

  • GDC 2009 - Interpolation and Splines

2.8 가우스 난수를 이용한 사실적인 탄도 다변화

  • 총을 쏘았을 때 탄착점들이 종 곡선(bell curve) 형태로 분포해야 자연스럽다.
    • 가우스 분포 (gaussian distribution)

가우스 난수 발생기(Gaussian random number generator, GRNG)

  • 극값 거부(polar-rejection)
  • 지구라트(ziggurat)
  • 균등난수들의 합(sum-of-uniforms)
    • 최선의 선택

응용

  • 집단 이동시 속도
  • 캐릭터, 나무, 건물의 높이
  • *평균을 중심으로 조금씩 변동*이 있을 때 도움

저자

  • Using Gaussian Randomness to Realistically Vary Projectile Paths - Steve Rabin

3.1 행동방식 복제를 이용해서 흥미로운 에이전트 만들기

사례기반 기계학습(instance-based machine learning)으로 행동방식 복제

저자

  • Creating Interesting Agents with Behavior Cloning - John Harger, Nathan Fabian

3.2 사실적이고 통합된 에이전트 감각 모형

타원과 확실도를 추가해 시각과 청각 모형을 강화하고 통합된 감각 모형을 제시한다.

저자

  • Designing a Realistic and Unified Agent-Sesning Model - Michael Delp, Steve Rabin

3.3 AI 알고리즘 코드의 복잡도 다스리기: 일반적 프로그래밍 접근방식

파이프와 필터(Pipes and Filters) 설계 패턴을 적용

저자

  • Managing AI Algorithmic Complexity: Generic Programming Apprach - Anatoli Beliaev, Iskander Umarov

3.4 문제는 태도: 여론, 평판, NPC 개성의 구축요소

태도 심리학에 대한 기본 개념 설명. 유의성(valence), 효능(potency), 지속기간이 들어가는 간단한 태도 모형 제시.

저자

  • All About Attitude: Building Blocks for Opinion, Reputation, and NPC Personalities - Michael F. Lynch

3.5 플레이어 궤적과 상호작용적 플레이어 그래프를 이용한 게임

  • 플레이어 궤적과 상호작용을 기록해 상호작용적 플레이어 그래프(interactive player graph, IPG)를 생성
  • 이런 정보로 디버깅을 하거나 AI 문제점을 찾는 건 일반적인 접근
  • IPG 기반 집합화를 해서 AI 에이전트들이 인간 플레이어와 비슷하게 행동했는지 측정을 한다는 접근이 신선

저자

  • Understanding Intelligence in Games using Player Traces and Interactive Player Graphs - G. Michael Youngblood, Priyesh N. Dixit

3.6 목표지향적 계획 병합

  • 목표지향적 행동 계획 시스템(goal-oriented action planning system)
    • 프로그래머가 일일이 인지-사고-행동 주기에 행동을 넣는 부담을 줄이기 위해 고안
  • 계획 병합(plan merging)

저자

  • Goal-Oriented Plan Merging - Michael Dawe

3.7 A*를 넘어서: IDA*와 주변부 검색

IDA*(iterative deepening A)*과 주변부 검색(fringe search) 알고리즘 소개

IDA*(iterative deepening A*)

  • 열린, 닫힌 목록 사용 X
  • 문턱값으로 노드 평가 생략 여부를 결정
  • 노드 전개, 평가 비용이 열린, 닫힌 목록 갱신 비용보다 작다
  • 문턱값 사용
  • 지금 목록(now list)과 나중 목록(later list)을 사용해 변경 노드 관리

저자

  • Beyond A*: IDA* and Fringe Search - Robert Kirk DeLisle

4.1 GPU 프로그램을 이용한 음향 신호 처리

GPGPU 프로그래밍으로 코러스 효과와 콤프레션 효과를 처리하는 방법을 소개

저자

  • Audio Signal Processing Using Programmable Graphics Hardware - Mark France

4.2 MultiStream―차세대 음향 엔진 작성의 예술

PS3 공식 SDK에 포함된 음향 엔진을 만들 때 고려한 여러 사항을 설명

저자

  • MultiStream - The Art of Writing a Next-Gen Audio Engine - Jason Page

4.3 게임 음향 환경에서 되풀이 없애기 및 사운드 설계에 대한 새로운 접근방식

실시간으로 개별적인 원본 구성음들로 복잡한 음을 구축하는 접근.

저자

  • Listen Carefully, You Probably Won’t Hear This Again - Stephan Schütze

4.4 실용적인 실시간 음향 효과

  • 사운드 시스템 구축의 전반적인 원리들에 초점
  • 소리(sound)라고 인식하는 것은 음 표본(sample)들의 차이

저자

  • Real-Time Audio Effects Applied - Ken Noland

4.5 문맥 주도적인 계층적 믹싱

게임의 전반적인 사운드를 사람이 좀 더 잘 제어할 수 있게 하는 믹싱 시스템 소개

저자

  • Context-Driven, Layered Mixing - Robert Sparks

5.1 고급 입자 퇴적

입자 퇴적의 구성 요소인 입자 배치와 입자 동역학 설명

입자 배치 (particle placement)

  • 입자들을 어디에 떨어뜨릴 것인지 정의
  • 특정한 종류의 지형을 만들기 위해 방식을 다르게 해야 함
    • 화산지대
    • 산악지대
    • 모래 언덕
    • 돌출 지형

입자 동역학 (particle dynamics)

  • 떨어진 입자가 어떤 식으로 굴러 떨어져서 안착하는지를 정의
  • 검색 반지름을 무작위로 변화시켜 비슷한 기울기가 반복되는 걸 막는다

저자

  • Advanced Particle Deposition - Jeremy Hayes

5.2 골격 애니메이션의 누적 오차 줄이기

  • 자식 변환을 부모에 상대적으로 만들면 자료 양이 줄어들지만 누적 오차가 생김
  • 오차가 포함된 부모 변환을 얻고 자식 변환이 원점이 아니라 그 변환에 상대적이 되도록 만드는 방법을 제시
  • 전처리 과정에서만 수행

저자

  • Reducing Cumulative Errors in Skeletal Animations - Bill Budge

5.3 거친 재질을 위한 또 다른 분산광 셰이딩 모형

오런-나야르 반사 모델(Oren–Nayar reflectance model)과 비슷한 결과를 내면서 계산이 훨씬 더 간단하고 빠른 모델 제시.

평탄화 효과(flattening effect) 흉내

  • 가장자리를 제외한 부분에서 분산광을 최대 세기에 가깝게 올림
  • 가장자리에서는 분산광의 세기를 급격히 0으로 떨어뜨림

후방 산란(backscattering)

  • 광원이 관찰자와 같은 방향에 있을 때에만 나타나므로 lv로 모형화

저자

  • An Alternative Model for Shading of Diffuse Light for Rough Materials - Anders Hast, Ewert Bengtsson, Tony Barrera

5.4 고성능 세분 표면

  • 세분 표면(subdivision surface) 생성 방법 중 하나인 Loop 세분을 확장한 방법을 소개
  • 각 정점과 변에 가중치를 부여해 Loop 알고리즘에 추가로 경계, 주름, 모서리, 준예리성 특징을 표현

저자

  • High-Performance Subdivision Surfaces - Chris Lomont

5.5 방사 기저 함수 텍스처를 이용한 부조 임포스터의 애니메이션

  • relief imposter를 방사 기저 함수(radial basis function, RBF)를 사용해 애니메이션하는 기법을 소개
    • relief imposter : relief 렌더링 기법을 확장해 텍셀 당 깊이, 법선, 색상 정보가 여러 층으로 쌓여 있는 relief 텍스쳐를 사각형에 매핑

저자

  • Animating Relief Impostors Using Radial Basis Functions Textures - Luciana P. Nedel, Manuel M. Oliveira, Vitor Fernando Pamplona

5.6 셰이더 모형 1.1 이상에서의 클립매핑

  • 클립맵(clipmap) : 각 밉맵 수준의 일부 영역만 적재할 수 있도록 밉맵을 일반화한 것
  • 설명이 친절하다.

핵심

  • 추출한 텍샐이 아직 적재되지 않았다면 대신 이미 적재돼 있는 저해상도 자료를 사용하는 게 핵심
    • 시점 변화가 텍스처 페이징을 앞지르는 경우에도 시각적 결함이 크게 드러나지 않음

장점

  • LOD 수준 전이가 매끈
  • 메모리 사용량이 고정적
  • 시야 독립적
  • 이미지 품질과 클립맥에 할당된 자원 사이에 잘 정의된 관계가 존재.
  • 갱신 단위가 가변적이라서 갱신 특성이 아주 좋다.

단점

  • 가변적인 세부 수준들을 다루지 못함
  • 텍스처 공간 안에서 초점으로부터 선형적으로 세부도가 떨어짐
  • 복잡한 실내 환경에는 적합하지 않다

저자

  • Clipmapping on SM1.1 and Higher - Ben Garney

reference

5.7 개선된 데칼 시스템

nil

  • 전체화면 렌더 타겟 2개 사용
    • DiffuseRenderTarget, BumpRenderTarget
  • 기하구조의 분산 색, 범프 값을 섞어서 표현

저자

  • An Advanced Decal System - Dmitry Andreev, Joris Mans

reference

5.8 실외 지형 렌더링을 위한 대형 텍스처 매핑

  • 커다란 이미지를 더 작은 타일들로 분할해서 저장.
  • 타일들은 하나의 텍스처 스택으로 결합. 클립매핑(clipmapping)과 유사.

저자

  • Mapping Large Textures for Outdoor Terrain Rendering - Alberto Jaspe, Antonio Seoane, Javier Taibo, Luis Hernández

5.9 그래프탈 임포스터를 이용한 회화 기반 렌더링

  • 그래프탈(graftal) : 컴퓨터 그래픽에 사용하기 위해 식물의 모양과 구성을 형식문법(formal grammar)으로 표현하는 수단.
  • 텍스처 도감(texture atlas), 제어 텍스처, 벡터장 텍스처, 색상 텍스처와 기하 셰이더(geometry shader)를 사용

저자

  • Art-Based Rendering with Graftal Impostors - Joshua A. Doss

5.10 동적 실시간 립싱크

시각소 최소 집합으로 그럴듯한 립싱크 애니메이션을 만들어 내는 방법을 소개.

  • 시각소(viseme) : “아”나 “이” 같은 음소(phoneme)의 시각적 표현.
  • 개념 검증 데모용으로 충분

저자

  • Cheap Talk: Dynamic Real-Time Lipsync - Timothy E. Roden

6.1 게임 세계 동기화의 고수준 추상

  • 고수준 추상(high level abstraction, HLA)을 이용해서 게임 세계를 동기화하는 메타프로그래밍 기법 하나를 소개
  • 게임 세계 상태의 동기화를 위한 메시지 교환 코드를 더 높은 수준에서 추상화
  • SWD(Synchronized World Definition) 컴파일러, HLA 런타임, SWD 파일로 구성

저자

  • High-Level Abstraction of Game World Synchronization - 배현직

6.2 온라인 게임의 인증

게임 로그인, 게임 세션 보안에 사용하는 기법을 간단하게 소개

게임 로그인의 보안

  • 시도 해시 인증(challenge hash authentication)
  • 비밀 교환 인증(secret exchange authentication)
  • 공개 키 기반구조

게임 세션의 보안

  • IP 주소로 식별
  • 인증 토큰(authentication token)으로 식별
  • 암호화를 이용한 식별

저자

  • Authentication for Online Games - Jon Watte

6.3 똑똑한 패킷 스니퍼를 활용한 게임 네트워크 디버깅

WinPcap을 패킷 갈무리하는데 사용해 직접 만든다.

  • 게임에서 사용하는 네트워크 구조체 사용.
  • 게임 메시지 형태로 해석.
  • Wireshark 플러그인을 사용하는 것도 한가지 방법.

저자

  • Game Network Debugging with Smart Packet Sniffers - David L. Koenig

7.1 자동 루아 바인딩 시스템

  • 루아 바인딩을 구현하는 기법 소개
  • 구문적 겉치레(syntactic sugar)를 사용해 테이블로 객체지향 스타일을 흉내

저자

  • Automatic Lua Binding System - Julien Hamaide

7.2 내부조사를 이용한 C++ 객체의 직렬화와 데이터베이스 저장

c++ 객체들을 SQL 데이터베이스에 저장하고 필터를 이용해서 특정 객체들을 편하게 조회하는 방법을 소개

저자

  • Serializing C++ Objects into a Database Using Introspection - Joris Mans

7.3 자료운반체

  • 컴파일 시점 의존성을 줄이고 실행시점의 행동을 좀 더 유연하며 자료주도적으로 만들어서 복잡성의 관리를 돕는 한 수단.
  • 고유한 전역 식별자를 가진 하나의 자료 조각
  • 자료운반체 포인터를 하나 만들고 관리자 클래스에게 그것을 특정 자료운반체에 연결시켜 달라고 요청해서 실제 자료에 접근하는 방식.

저자

  • Dataports - Martin Linklater

7.4 그래픽 팀원들을 고려한 자료주도적 셰이더 지원 시스템

셰이더 정의 XML 파일 도입 이야기.

저자

  • Support Your Local Artist: Adding Shaders to Your Engine - Curtiss Murphy

7.5 Python의 AST 다루기

  • AST(Abstract Syntax Tree) : 소스 코드 파싱 과정에서 만들어진다. 코드 생성기는 AST를 입력으로 삼아서 바이트 코드를 생성.
  • 문자열마다 ID 배정은 로컬라이제이션을 위해 필요한 과정.
  • python에서 AST 조작으로 문자열을 쉽게 가져오고 ID로 대체할 수 있다.

저자

  • Dance with Python’s AST - Zou Guangxian

reference