2008년 8월 9일 토요일

몬헌 -_-

이런 병신같은 조작감을 가진 게임은 정말 오랜만이네
플스때는 이런겜도 그냥 참고 했었는데 PC 로 이런걸 할려니 짜증만 나는구나.
꼬라지를 보니 플스걸 생각없이 걍 가져온듯.
키보드를 생각해서 인터페이스를 좀 손봤어야지 새퀴들아

한게임 가입 절차도 병신이고 이건뭐..

병신같은 게임을 안그래도 짜증나는 여름에 하려니
정말...




2008년 8월 7일 목요일

tinyscheme 간단한 용도에 임베딩해서 사용할수 있는 BSD 스타일 라이센스의 scheme 인터프리터 구현체

http://tinyscheme.sourceforge.net

문서가 좀 그런면이 있는데 인터페이스 함수들이 워낙 간단하니 적당히 쓰면 잘 돌더라. 심각한 스크립팅이 필요하면 다른걸 찾아보자. 원래 ecl 을 써볼려고 했는데 이건 덩치가 너무 크고 라이센스도 빡세더라. 간단한 일에 부담없이 쓰기엔 요놈이 아주 좋아보인다.


//
// 아래 소스 빌드할때 써먹은 CMakeLists.txt
// 별거없고 USE_INTERFACE 를 디파인했다는것만 기억해두자
// 그외 여러가지 조정할게 많아 보이는데 아직 모름.
//

// PROJECT(play-with-tinyscheme)
// INCLUDE_DIRECTORIES(/home/yoonkn/tmp/tinyscheme1.39)
// LINK_DIRECTORIES(/home/yoonkn/tmp/tinyscheme1.39)
// LINK_LIBRARIES(tinyscheme)
// ADD_DEFINITIONS(-DUSE_INTERFACE)
//
// ADD_EXECUTABLE(a a.cpp)



extern "C" {
#include "scheme-private.h"
#include "scheme.h"
}
#include <unistd.h>
#include <iostream>
using namespace std;

static void die(const char* msg) {puts(msg); exit(-1);}
static pointer c_add(scheme* sc, pointer args);


int main()
{
// 초기화. 전역이 아니라 멀티쓰레드간에 써도 안심?
scheme* sc = scheme_init_new();
if(!sc) die("init failed");

// display 등으로 출력되는 값이 튀어나오는 곳이겠군.
scheme_set_output_port_file(sc, stdout);

// scheme 코드를 실행하려면 load_string 이나 load_file 을 쓰자
// scheme.c 를 보니 init.scm 등을 먼저 읽고 시작하는게 바른
// 사용방법인듯 하다. load_string 류 함수는 코드 실행후 실행여부를
// retcode 에, 평가된 값을 value 에 담아주는 모냥이다.
sc->vptr->load_string(sc, "(define foo \"fuckshit\")");
if(sc->retcode != 0) die("exec failed");

// scheme 내의 값을 읽으려면 요렇게. 심벌만 넣어서 실행하고
// .value 를 읽어오면 되는듯
sc->vptr->load_string(sc, "foo");
const char* foo_value = sc->vptr->string_value(sc->value);
puts(foo_value);

// C 쪽에서 만든 덧셈 함수를 scheme 인터프리터에 추가하자.
sc->vptr->scheme_define(sc,
sc->global_env,
sc->vptr->mk_symbol(sc, "c-add"),
sc->vptr->mk_foreign_func(sc, c_add));

// c_add 함 불러보고 리턴값을 찍어보자
sc->vptr->load_string(sc, "(c-add 111 222)");
if(sc->retcode != 0) die("fucked");
printf("(c-add ..) return : %d\n", sc->vptr->ivalue(sc->value));

// 이번엔 반대로 scheme 쪽에서 함수를 만들어보자
sc->vptr->load_string(sc, "(define (scm-add a b) (+ a b))");
if(sc->retcode != 0) die("fucked");

// 이걸 C 쪽에서 부르자.. 음 물론 scheme 코드 만들어서 load_string
// 써도 되겠지만.. C 레벨에서.. 어라? 인터페이스가 안빠져있네
// scheme_call 이란 함수가 있긴 한데 외부로 노출된 함수는 아니네
// 음.. 뭐 일단 내가 원했던 내용까지는 파악이 됐으니 걍 여기까지



// 정리. 그런데 scheme_init_new 는 안쪽에서 sc 를 malloc 해서
// 주는데 deinit 함수중에는 sc 자체를 free 까지 해주는 함수가
// 안보이네 일단 샘플이니 여기서 그냥 free 를 했지만 정말 써먹을
// 상황이 온다면 dll 간에 malloc/free 가 섞일수도 주의하자.
scheme_deinit(sc);
free(sc);
}



// scheme 에 노출할 함수는 pointer foo(scheme*, pointer) 형태의
// 시그너쳐를 가지고 pointer 를 통해서 인자들이 리스트 형태로
// 들어온다. 복잡한데 쓸거 아니니 이정도만 알면 안심
pointer c_add(scheme* sc, pointer args)
{
// 첫번째 인자가 존재하고 정수가 맞는지 확인
if(args == sc->NIL) return sc->NIL;
pointer a = pair_car(args);
if(!is_integer(a)) return sc->NIL;

// 이거.. 변수 따로 잡기 귀찮아서 그냥 덮어썼는데
// 그래서 arg list 들의 첫번째 car 를 팝 한 효과가 났다.
args = pair_cdr(args);

// 다음 인자가 존재하고 정수가 맞는지 확인 꼴을 보니 좀 머리 쓰면
// 이쁘게 짤수 있을거 같은데 오늘은 샘플이니 그냥..
if(args == sc->NIL) return sc->NIL;
pointer b = pair_car(args);
if(!is_integer(b)) return sc->NIL;

// 더한값을 scheme 자료형태로 리턴
return mk_integer(sc, ivalue(a) + ivalue(b));
}