기획자 본인만큼 잡다한 블로그

greentec.egloos.com

포토로그


통계 위젯 (블랙)

767
380
51650

flag counter

Flag Counter


Python 3.x curses 라이브러리에서 한글 출력 - Windows 10 프로그래밍

배경 설명


이직 후 여러 가지 작업을 하고 있는데 그 중 서브 작업으로 간단하게 파이썬 툴을 만들던 중,
윈도우 환경 터미널에서 키 입력을 바로 받고 싶은 간단한 문제에 봉착했다.
curses 라는 라이브러리를 깔았지만 한글 출력이 잘 보이지 않았다.
인터넷에는 관련된 레퍼런스가 없어서 못 찾다가, 반나절 동안 삽질 후 해결책을 여기에 공유한다.


핵심 요약


addstr() 대신 addch() 를 사용해서 한 글자씩 출력하자.
[optional] 터미널 글씨체를 래스터 글꼴로 바꾸자(굴림체 등의 경우 글의 끝부분이 잘릴 수도 있음).


상세


어떤 숫자를 입력받을 때 보통 알고리즘 문제 같은 곳에서는 이렇게 입력을 받는다.
n=int(input())




그런데 이런 경우에는 숫자를 입력한 후 엔터를 쳐줘야 문장의 다음 부분으로 넘어가게 된다. 하지만 숫자 키 하나만 눌렀을 때 바로 다음으로 넘어갈 수는 없는 걸까? 찾다 보니 curses 라는 라이브러리가 있었다. pip install curses 라고 입력하면 windows 에서는 설치되지 않고, 링크의 curses‑2.2‑cp36‑cp36m‑win_amd64.whl 파일을 다운받아서 해당 경로에서 직접 설치했다. 자신의 시스템에 설치된 python 버전에 따라 알맞은 파일을 설치하면 된다.
pip install curses‑2.2‑cp36‑cp36m‑win_amd64.whl




이제 getch() 함수를 이용해서 키 입력을 바로 받을 수 있다. 간단한 예제 프로그램을 만들어서 테스트를 해보면,
import curses

def main(screen):
screen.clear()
screen.addstr(0, 0, 'Hello World')

while True:
c = screen.getch()
screen.addstr(1, 0, str(c))

if c == 3: # Ctrl+C
break


curses.wrapper(main)




터미널에서 다음 스크립트를 실행하면 이런 화면이 표시된다.
현재 키 입력을 y=1, x=0 위치에 출력한다. 키 값은 int 이고 출력할 때는 str 이어야 하기 때문에 형 변환을 해줬다.
Ctrl + C 의 키 값은 3인데, 누르면 프로그램을 빠져나가게 된다. 달리 프로그램을 빠져나가는 방법은 찾아본 바로는 없었다. 터미널 창을 끄거나 해야한다.



그럼 한글을 출력해보자.
인터넷에서 유니코드 출력을 위해서는 locale 을 바꿔줘야 한다고 해서 그 부분을 추가하고, 한글 텍스트를 넣어보았다.
import curses
import locale
locale.setlocale(locale.LC_ALL, '')

def main(screen):
screen.clear()
screen.addstr(0, 0, '터미널에서 다음 스크립트를 실행하면 이런 화면이 표시된다.')

while True:
c = screen.getch()
screen.addstr(1, 0, str(c))

if c == 3: # Ctrl+C
break


curses.wrapper(main)




결과는 아래와 같다. 한글이 깨져서 나온다.



문제를 해결하기 위해 여러 가지 시도를 해봤는데 해답은 의외로 간단한 곳에 있었다. addstr() 함수 대신에 addch() 함수, 즉 한 글자씩 떼어서 출력하면 잘 나왔다. 알고나니 허무한 해결책이었다.
참고로 글씨 중간에 커서가 있으면 글씨가 밀리는 문제가 있어서 한글 출력 후 커서 위치를 바꿔주기 위해 빈 칸을 출력했다.
import curses
import locale
locale.setlocale(locale.LC_ALL, '')

def main(screen):
screen.clear()
s = '터미널에서 다음 스크립트를 실행하면 이런 화면이 표시된다.'
for idx, char in enumerate(s):
screen.addch(0, idx, char)
screen.addstr(1, 0, ' ')

while True:
c = screen.getch()
screen.addstr(1, 0, str(c))

if c == 3: # Ctrl+C
break


curses.wrapper(main)




이제 한글이 정상적으로 출력된다.




알고나니 무척 간단한 방법이었다. 그리고 내 경우에는 파일에서 한글을 읽어들일 때 글씨의 중간이 잘리는 문제가 있어서 터미널의 기본 글꼴을 바꿔서 문제를 해결했다. 같은 현상을 겪는 경우 참고가 될 수 있을 것 같다.



<머신러닝을 이용한 알고리즘 트레이딩 시스템 개발> 코드 일부 정리 프로그래밍






얇아보여서 산 책인데 생각보다 코드 따라가는 데에 시간이 걸렸다. 이 책이 작성되던 시점과 현재 시점 사이에는 Yahoo financial 데이터를 받아오는 부분 등 여러 개가 달라져 있어서 코드 수정이 필요했다. 그리고 결과도 한번에 보고 싶어서 코드를 따라가는 김에 Jupyter notebook 으로 돌아갈 수 있도록 .ipynb 파일로 새롭게 작성했다. 다만 Ch.5 가 트레이딩 시스템 실전 부분인데 여기는 며칠을 잡고 있어도 답이 안나와서 결국 안올리게 되었다.






Ch.5를 작업하지 못했기 때문에 웹에 올리지 말까 생각했지만 어쨌든 올리면 누군가에게는 도움이 될 거라는 생각에 올려본다.

Brawl Stars - 슈퍼셀. 더 이상 시간으로 여는 상자는 없다. 게임기획

그 유명한 슈퍼셀의 신작이 캐나다 앱스토어에만 소프트 런칭을 해서, 캐나다 앱스토어 계정을 만들고 플레이해봤다. 게임은 역시 슈퍼셀답게 무척 중독적이고 재밌다. 그런데 이런 뻔한 얘기를 하려고 글을 쓴 것은 아니고...


브롤 스타즈



내가 이 게임에서 제일 놀랐던 건 오버워치 같은 실시간 PVP 멀티플레이를 채택한 것도 아니었고, 모바일에서 가상패드 혹은 드래그를 쓰는 불편한 조작을 망설임없이 선택한 점도 아니었다.
그것은 바로 슈퍼셀의 세계적 히트작이자 바로 전작인 <클래시 로얄>을 해봤던 사람에게라면 너무나도 익숙한 상자, 시간이 지나면 열리는 상자가 사라졌다는 점이었다.


클래시 로얄의 상자



사실 시간으로 열리지는 않지만 상자가 있긴 있다. 이 상자는 100골드를 모으면 열리고 랜덤한 영웅이나 엘릭서(영웅 업그레이드에 쓰임)를 내놓는다.




어디서 많이 본 것 같지 않은가? 캐쥬얼 모바일 게임도 다양하게 하는 사람이라면 금방 알 것이다. 바로 <길 건너 친구들>에서 시작된 '한 번 더 플레이하게 만드는' 모델이다.


길 건너 친구들



길 건너 친구들의 상자(가챠폰)



왜 <클래시 로얄>의 상자를 버리고 <길 건너 친구들>의 상자를 택했을까? 무과금으로 영웅 16개 중 11개를 열고 트로피 500이 되어가는 현재 내가 추측한 이유는 다음과 같다.
이 게임은 <클래시 로얄>의 1대 1과 다르게 3대 3, 10명 데스매치 등 2개의 매칭 형태를 제공한다. 매칭에 필요한 인원 수가 무척 많다. 아직도 <클래시 로얄>이 매칭을 어떻게 하는지는 모르지만 정말 미스테리하게 빠르다. 하지만 그 이유 중에 하나는 매칭에 필요한 인원이 2명이기 때문도 있었다고 생각한다. 그에 비해 한 경기에 6명 혹은 10명이 필요한 <브롤 스타즈>는 매칭에 필요한 시간이 길어질 수밖에 없다. 비슷한 시기에 나온 <탱고 파이브>가 5대 5 매칭을 지원하고, 매칭 시간이 오래 걸릴 때 기다릴 때마다 보상을 지급한다는 점을 생각해보면 이와 비슷할 것이라고 생각할 수 있다.


탱고 파이브 매칭 보상



그러면 <길 건너 친구들>의 상자를 채택한 이유는? 바로 '한 번 더 플레이하게 만드는' 모델로 인해 사람들이 좀 더 많은 게임을 하도록 하기 위해서라고 생각한다. 실제로 게임을 해보면 돈이 금방 모이는데 조금만 더 모으면 100이 될 것 같다고 느껴진다. 한 번 이길 때 8골드, 지더라도 3:3 게임에서는 4골드를 얻고, 경험치가 쌓여서 계정 레벨이 올라가거나 영웅 레벨이 올라가도 골드를 받는다. 내가 게임에 들어갔을 때 100골드가 아니라면 어떻게든 100골드는 만들어서 상자를 뽑고 싶다. 100골드를 만들고 돈이 애매하게 남는다면 또 100골드를 만들어서 상자를 뽑고 싶다. 이게 꽤 효과적으로 반복된다.


상자,플레이,매칭의 매커니즘



정리하면 슈퍼셀은 전작의 가장 핵심 요소였던 시간을 써서 여는 보상 상자를 과감하게 버렸다. 왜냐하면 자신들의 새로운 게임 메커니즘에는 새로운 보상 시스템이 필요했기 때문이다. 그리고 그것은 꽤 효과적으로 작동하고 있는 것 같다.



idle 게임의 설득력 게임기획

요즘 인기 있는 idle 게임에 처음 들어가면 보통 초반 자원 획득 속도가 무척 낮다. 그런데 이 불편함이 설득력이 있다면 유저들은 계속 이 게임에 붙어있게(attached) 된다. 자원 획득 속도를 빠르게 만들기 위해 노력을 하는 과정에서 게임에 더 익숙해지고 게임에 더 시간을 많이 쓰게 된다. 수많은 비슷한 게임이 있는 가운데 어떤 게임에 시간을 일단 소비하고 나면 그 게임에 유저가 머물 확률은 더 높아진다.

위에서도 말했듯이 이런 불편함의 메커니즘이 유저에게 설득력을 가지기 위해서는 자원을 얻기 위해 하는 행동이 처음에는 시간을 소비하지만 그럴듯해 보여야 한다. revolution-idle-2 의 로딩 게이지처럼 우리가 일상 생활에서 봐서 친숙하면서도 시간이 걸리는 행동. punch-bag-clicker 처럼 샌드백을 한번 쳤으면 돌아와서 제자리로 올 때까지 기다려야 하는 행동. SNG의 작물을 심고 수확할 때까지 기다리는 것도 이와 비슷하다고 할 수 있다. 현실을 완벽하게 모사하지 않더라도 현실의 환상을 일부 제공하면 유저는 그 기억을 떠올리고 그에 맞는 보상을 받으며 게임에 머물게 된다.

windows7 에서 anaconda2 를 이용할 때 nolearn 설치 딥러닝

개발환경 때문에 삽질을 너무 많이 해서 잊어버리기 전에 적는 게 나을 것 같다.
일단 nolearn은 conda install nolearn 이렇게 쳐봤자 잡히지 않는다. anaconda2 에서 사용할 수 있는 기본 라이브러리로 등록되어 있지 않기 때문이다. 0.1 버전이 잡히는 lasagne 도 결국 pip로 설치해야 하지만, nolearn 은 그마저도 되지 않는다. scipy 가 윈도우7 환경에서는 문제를 일으키기 때문에 pip를 사용해서는 제대로 설치가 안된다.
설치하려면 아래와 같은 명령어를 커맨드 창(cmd)에 입력하자.

> conda install -c hobs nolearn=0.7.0

이렇게 치면 누군가 윈도우 환경에서도 nolearn 0.7 버전을 사용할 수 있게 커스터마이징 해놓은 버전을 다운받을 수 있다. 몇몇 라이브러리는 downgrade 되지만 목적이 nolearn 이라면 크게 상관없다. 안전한 사용을 원하면 개발환경(source)을 나눠서 쓰면 될 것 같다. 어쨌든 이렇게 진행하면 nolearn 을 윈도우7에서도 사용할 수 있다. 윈도우10은 이런 과정 없이 잘 사용할 수 있었다.


1 2 3 4 5 6 7 8 9 10 다음

애드센스