2025-11-13
Learning LangChain
2025-11-12
Debian Release Notes Korean Translation Work In Progress
처음엔 안 많은 줄 알았다. 파일 몇 개는 내용이 많지 않다. 몇및 파일은 내용이 많다.
수시로 업데이트 보완 중. 언제 완성될 지 모름.
2025-11-11
병천순대감자탕뼈해장국 강서구청
병천 순대 감자탕 뼈해장국. 강서구청 근처. 사람들이 얘기하는데 네이버 지도에 안 나타남. 왜지? 아. 생긴지 얼마 안 되어서 그런가보다.
주소: 서울시 강서구 화곡로 311
2025-11-10
Do Nothing or Do Something
2025-11-07
Linux translation
https://d-i.debian.org/manual/ko.amd64/ch03s03.html
한국어 번역인데 리눅스, Linux 함께 있다. 모두 리눅스로 바꾸어야 하나?
저 페이지의 salsa 저장소는 어떻게 찾아야 하나?
Typo bug report
https://d-i.debian.org/manual/ko.amd64/ch03s01.html 오타 발견
데비안 GNU/리눅스에서는 잘되지 않는 경우, OS를 대체하지 않고 교체할 수 는 케이스가 훨씬 많습니다.
&debian-gnu;에서는 잘되지 않는 경우, OS를 대체하지 않고 교체할 수 는 케이스
영어원문
Under &debian-gnu;, it is much more likely that your OS can be repaired rather than replaced if things go wrong.
https://salsa.debian.org/installer-team/installation-guide/-/blob/master/po/ko/preparing.po?ref_type=heads 에서 발견한 오타.
위 파일에
# 이 번역은 완성 단계로 품질에 많은 신경을 쓰고 있습니다. 반드시
# debian-l10n-korean 메일링 리스트에 번역 사실을 알리고 토의를 하십시오.라는데 자잘한 오타 하나 하나 메일링 리스트에서 얘기 할 필요는 없겠지?
2025-11-06
Debian Release Notes Korean
https://www.debian.org/releases/trixie/release-notes/index.ko.html
알 수 없는 일이다.
저장소 https://salsa.debian.org/ddp-team/release-notes/ 에서는 한국어 번역 지워졌는데.
저 위에 있는 한국어 번역도 언제 지워질 지 모르겠다.
https://salsa.debian.org/sebul-guest/release-notes/-/tree/master/source/locales/ko/LC_MESSAGES?ref_type=heads
여기에서 한국어 번역 업그레이드 진행중.
공식 사이트 https://salsa.debian.org/ddp-team/release-notes 에 머지 요청은 보류.
2025-11-05
Bug Report in Korean translation of salsa Debian release notes
https://salsa.debian.org/sebul-guest/release-notes/-/blob/master/source/locales/ko/LC_MESSAGES/old-stuff.po?ref_type=heads
#: ../old-stuff.rst:40
msgid ""
"As root, open the relevant APT sources file(s) (such as ``/etc/apt/"
"sources.list`` or any file under ``/etc/apt/sources.list.d/``) with your "
"favorite editor, and check all lines beginning with"
msgstr ""
"루트로서, 좋아하는 편집기로 관련된 APT 소스 파일(예: ``/etc/apt/"
"sources.list`` 또는 ``/etc/apt/sources.list.d/`` 아래 있는 파일)을 열고, "
"다음과 같은 모든 줄을 확인합니다"
루트로서, 아니다. 영어 root 그대로 써야 한다. root 사용자로 로그인 해야 된다는 뜻.
2025-11-04
Typo in .po file
https://salsa.debian.org/webmaster-team/webwml/-/blob/master/korean/po/others.ko.po?ref_type=heads
베게? 배개? 베개?
번역 수정 반영 됨.
issue expected prevalence translation
Note that it is impossible to list every known issue and that therefore a selection has been made based on a combination of the expected prevalence and impact of issues.
모든 문제를 열거할 수는 없으므로, 예상되는 발생 빈도와 그 영향력을 종합적으로 판단하여 선정한 것임을 알려드립니다.
2025-11-01
Push mirroring
저장소 원본을 임시 디렉터리에 넣은 후 그것을 내 저장소에 밀어 넣는 방법. 예시.
git clone --mirror https://salsa.debian.org/ddp-team/release-notes.git tmpMir
cd tmpMir
~/tmpMir$ git push --mirror https://salsa.debian.org/sebul-guest/release-notes.git
다시 시작
git clone https://salsa.debian.org/sebul-guest/release-notes.git
2025-10-27
Debian release notes Translation
sudo apt install python3-sphinx-rtd-theme 안 해서 그런 것.
답은 README.md 에 있었네. 결국 해결.
번역 참여 하려면 아래 내용을 읽어야 하며, README.md 도 읽어야 함.
https://salsa.debian.org/ddp-team/release-notes/-/blob/master/README.translators
한국어 번역 시작하려면 아래 글 참고
* Test building html files from the PO files as follows:
* Now you will find different document formats for your translation under build/.
파일 하나 MergeRequest 했는데 얼마 지나지 않아 Merge 되어서 깜짝 놀람.
https://lists.debian.org/debian-doc
2025-10-25
여러 파일 같은 변경 리눅스
*.txt 파일 여럿에서 old_word를 new_word로 한 번에 바꾸기.
find . -type f -name "*.txt" -exec sed -i 's/old_word/new_word/g' {} \;
2025-10-24
To fix typo in Debian install manual
데비안 설치 설명 오타 발견한 거 고치려면?
https://www.debian.org/releases/trixie/amd64/index.ko.html 에
이 한국어 번역은 여러 분들이 자발적으로 참여해 완성되었습니다. 이 번역에 대해 데비안 한국어 지역화 메일링 리스트에 (https://lists.debian.org/debian-l10n-korean/ 참고) 얘기할 수 있습니다.
라고 되어 있다. 그러나 자잘한 번역 오류(단순 오타 등)는 바로 Merge Request 하면 될 듯.
https://www.debian.org/releases/trixie/amd64/ch03s06.ko.html#disable-fast-boot
소상을 막기 위해 - 손상을 막기 위해로
아무 데나 물어보면 안 되고 어디 물어봐야 되는지 먼저 알아보고 제대로 물어보자.
데비안 한국어 번역 관련이라고 https://lists.debian.org/debian-l10n-korean/ 에 물어보면? 답을 얻을 수도 있고, 아닐 수도 있고.
https://salsa.debian.org/installer-team/installation-guide/ fork 해야 됨.
내 리포지토리 다시 만들었음. 하도 오래 되서.
https://salsa.debian.org/sebul-guest/installation-guide 새로 만들어야 되고.
po/ko/preparing.po 에서 소상을 손상으로 오타 수정
Merge request 보내야 됨. 받아줄지는 모름.
운이 좋았다. 요청 보낸 지 얼마 안 되어서 Merge 됨.
https://salsa.debian.org/installer-team/installation-guide/-/merge_requests/37
저장소에 반영된 것이 데비안 홈페이지에 반영되려면 조금 더 기다리면 될 듯.
아. 조금 아니고 한참이 될 수도 있다. 데비안 홈페이지에 바로 반영되지는 않는다.
Generally, we are preparing the manual for the next Debian release here. Not all changings you are seeing in the master branch in git are automatically ported to Trixie on the website. For that to happen, additional steps are needed, which we only do when really needed/for critical errors or similar.
라고 https://lists.debian.org/debian-boot/2025/10/msg00091.html 에서 알려줌.
https://d-i.debian.org/manual/ 에는 매일 업데이트 됨.
내 저장소를 원본과 같게 새로 만들기.
2025-10-21
Debian News weekly contributing
https://www.debian.org/News/weekly/contributing
#use wml::debian::weeklynews::header PAGENAME="기여"
#use wml::debian::translation-check translation="6818995daa5abca0fb79fefc90992c570b47b729"
<p>데비안 프로젝트 뉴스는 기여자가 필요합니다.
데비안 프로젝트 뉴스를 올리는 것은 작은 팀에게는 많은 일이지만, 매주 작은 시간만으로 도울 수 있습니다.
우리가 읽지 않은 메일링 리스트를 읽고 그 스레드를 요약할 사람이 필요합니다.
우리는 또한 <a href="https://planet.debian.org/">데비안 플래닛</a> 및
기타 온라인 리소스에 주목하는 사람들이 필요합니다.
도움에 관심 있으면, 이 페이지를 끝까지 읽고 시간 내에 <a href="mailto:debian-publicity@lists.debian.org">우리에게 연락</a>하십시오.
</p>
<p>더 많은 정보는 <a href="https://wiki.debian.org/">데비안 위키</a>에 있습니다.
가장 중요한 페이지:</p>
<ul>
<li><a href="https://wiki.debian.org/ProjectNews">Project News 시작 페이지</a>.</li>
<li><a href="https://wiki.debian.org/ProjectNews/HowToContribute">기여하는 방법</a>.</li>
<li> <a href="https://lists.debian.org/debian-news/"> debian-news 메일링 리스트</a></li>
<li>프로젝트 뉴스를 위한 <a href="https://wiki.debian.org/ProjectNews/Guidelines">기초 스타일 가이드라인</a>.</li>
<li><a href="https://wiki.debian.org/ProjectNews/Workflow">프로젝트 뉴스를 게시하는 데 쓰이는 흐름</a>에 관한 문서.</li>
</ul>
2025-10-20
2025-10-18
git push without password
git push 할 때 비번 입력 안 하게 하려면
ssh-keygen -t ed25519 -C "나의 이메일 주소"
기본경로
cat ~/.ssh/id_ed25519.pub
Debian Salsa 웹사이트에 로그인.
프로필 설정 또는 Settings 페이지로 이동. (찾기 어려우면 돋보기 아이콘 놀러서 ssh 검색)
보통 SSH Keys 또는 User Settings - SSH Keys 와 같은 메뉴를 찾습니다.
Add an SSH Key 버튼을 클릭하고, 키의 이름(Title)을 지정한 다음, 단계 2에서 복사한 공개 키 문자열을 Key 필드에 붙여넣습니다.
Add Key를 눌러 등록을 완료합니다.
https에서 ssh로 바꾸기
git remote -v
git remote set-url origin git@salsa.debian.org:path/to/your/repo.git
그 다음에는 git push 할 때 아이디, 암호 안 물어봄.
Draft translation. Debian Security
https://www.debian.org/security/
데비안 시스템 보안 유지
최근 권고 사항
보안 정보 출처
데비안은 보안을 매우 중요하게 생각합니다. 우리는 모든 보안 문제를 처리하고 합리적인 기간 내에 문제를 수정할 수 있도록 보장합니다.
경험에 따르면 "모호성을 통한 보안"은 결코 작동하지 않습니다. 따라서 공개를 통해 보안 문제를 더 빠르고 잘 해결할 수 있습니다. 이러한 점에서 이 페이지에서는 데비안 운영 체제에 잠재적으로 영향을 미칠 수 있는 다양한 알려진 보안 허점에 대한 데비안의 현황을 다룹니다.
데비안 프로젝트는 다른 무료 소프트웨어 공급업체와 많은 보안 자문을 조정하며, 그 결과 취약점이 공개되는 날에 이러한 자문이 게시됩니다. 최신 데비안 보안 자문을 받으려면 데비안 보안 공지 메일링 리스트에 가입하세요.
데비안은 보안 표준화 작업에도 참여합니다:
데비안 보안 권고사항은 CVE와 호환됩니다
Debian은 오픈 취약점 평가 언어(Oval)를 사용하여 보안 정보를 게시합니다
데비안 시스템 보안 유지
무인 업그레이드 패키지는 최신 보안(및 기타) 업데이트로 컴퓨터를 최신 상태로 유지하도록 설치할 수 있습니다. 위키 항목에는 무인 업그레이드를 수동으로 설정하는 방법에 대한 자세한 정보가 있습니다.
Debian의 보안 문제에 대한 자세한 내용은 FAQ와 문서를 참조하시기 바랍니다:
최근 조언 RSS
다음은 데비안 보안 공지 목록에 게시된 최근 데비안 보안 권고(DSA)입니다.
T는 데비안 보안 추적기 정보 링크이며, DSA 번호는 공지 메일 링크입니다.
language.conf file Debian translation
Debian Salsa 에 번역 업데이트 할 때
language.conf 파일에 단 한 줄
korean
넣으면 됨.
copypage.pl을 이용해서 번역을 시작하려면 webwml root 디렉터리의 language.conf 파일을 먼저 설정해야 하는데, 그 파일은 번역할 언어를 결정하는데 쓰일 겁니다. 그 파일은 최대 두 줄이 필요합니다: 첫 번째 줄은 언어명(korean 같은)을 써야하고, 두 번째 줄은 선택적으로 유지보수 번역자의 이름을 쓸 수 있습니다. 또한, 여러분은 DWWW_LANG 환경변수를 써서 언어명을 설정할 수도 있으며, DWWW_MAINT 환경변수에 여러분의 이름을 넣을 수 있습니다. 이러한 정보는 번역 유지보수자(Maintainer)로서 wml 파일 헤더에 추가될 겁니다. 셋째로 가능한 방법은 명령행에서 언어명과 필요하면 유지보수자를 -l korean -m "Hong Gildong"와 같이 사용하고 language.conf 파일을 안 쓰는 방법입니다. 스크립트의 다른 기능들도 있는데, 도움말을 보려면 인자를 전달하지 말고 그냥 실행하면 됩니다.
https://www.debian.org/devel/website/translating
2025-10-16
https://lists.debian.org/debian-project/ or not
데미안 메일링 리스트 여러 종류.
적절한 메일링 리스트 찾아가는 것도 쉽지 않다.
https://packages.debian.org/en/trixie/task-korean
rec: zhcon
Fast console CJK system using FrameBuffer (main program)
https://packages.debian.org/en/forky/task-korean
rec: zhcon
Package not available
https://packages.debian.org/en/sid/task-korean
rec: zhcon
Fast console CJK system using FrameBuffer (main program)
https://lists.debian.org/debian-project/ 에 물어보면 되려나?
2025-10-14
gmail plain text mode
Turn plain text mode on or off
On your computer, open Gmail.
At the top left, click Compose.
At the bottom of the message, click More options and then Plain text mode.
Translation of Salsa interface
https://salsa.debian.org/webmaster-team/webwml/-/merge_requests
열기 머지됨 닫힘 전체
여기서 열기는 열림 으로 바꾸는 게 나을 것 같다.
열림 머지됨 닫힘 전체
이렇게 번역을 바꾸려면? 어디에 물어봐야 되려나.
2025-10-13
git commit hash
데비안 문서 번역하면 해시 붙이는데, 번역 이후 워문이 바뀌면?
최근 영문 보고 번역을 하면 되는데 해시는?
git log -1 --pretty=format:"%H" english/원문파일명.wml
이런 식으로 영어 원문 파일의 해시를 찾아서 그것을 번역본에 붙이면 된다.
더 쉬운 방법이 있다.
git log 원문파일명.wml 첫 줄 보면 된다. 결국은 그 얘기가 그 얘기.
2025-10-12
salsa git restart
내 저장소에서 작업 하던 것이 꼬여서 새로운 마음으로 하려면 어떻게 하나?
git clone --mirror https://salsa.debian.org/webmaster-team/webwml.git webwml-mirror-temp
cd webwml-mirror-temp
git push --mirror https://salsa.debian.org/sebul-guest/webwml.git
잘 된 것 확인하고 rm -rf webwml-mirror-temp
새롭게 시작
git clone https://salsa.debian.org/sebul-guest/webwml.git
cd webwml
2025-10-11
xrandr
a
xrandr | grep '*'
1920x1080 59.93*+ 60.00 60.00 50.00 59.94
m
$ xrandr | grep '*'
1920x1080 59.93 + 60.00* 60.00 50.00 59.94
xrandr
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected (normal left inverted right x axis y axis)
HDMI-2 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 510mm x 290mm
1920x1080 59.93*+ 60.00 60.00 50.00 59.94
1920x1080i 60.00 50.00 59.94
1680x1050 59.88
1280x1024 75.02 60.02
1152x864 75.00
1280x720 60.00 50.00 59.94
1024x768 75.03 60.00
832x624 74.55
800x600 75.00 60.32 56.25
720x576 50.00
720x480 60.00 59.94
640x480 75.00 60.00 59.94
720x400 70.08
GRUB example
GRUB 예시. 무조건 따라하는 게 아니고 본인 환경에 맞게 설정하면 됨.
cat /etc/default/grub
# If you change this file or any /etc/default/grub.d/*.cfg file,
# run 'update-grub' afterwards to update /boot/grub/grub.cfg.
# For full documentation of the options in these files, see:
# info -f grub -n 'Simple configuration'
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`( . /etc/os-release && echo ${NAME} )`
GRUB_CMDLINE_LINUX_DEFAULT="i915.modeset=1"
GRUB_CMDLINE_LINUX=""
# If your computer has multiple operating systems installed, then you
# probably want to run os-prober. However, if your computer is a host
# for guest OSes installed via LVM or raw disk devices, running
# os-prober can cause damage to those guest OSes as it mounts
# filesystems to look for things.
#GRUB_DISABLE_OS_PROBER=false
# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
# Uncomment to disable graphical terminal
#GRUB_TERMINAL=console
# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE/GOP/UGA
# you can see them in real GRUB with the command `videoinfo'
GRUB_GFXMODE=1920x1080
GRUB_GFXPAYLOAD_LINUX=keep
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true
# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"
# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"
2025-10-10
Draft. Debian package Korean
Package: task-korean
rec:zhcon 그런데 zhcon 오래도록 유지관리 안 되는 듯. 이거 필요한 건가?
그럼 zhcon 대신 fbterm으로 바꾸려면?
apt source tasksel
# 소스 디렉토리로 이동
cd tasksel-*/
sudo apt build-dep tasksel
해당 파일을 찾아서 수정 tasks/korean.desc (또는 비슷한 이름
korean.desc 파일 수정:
korean.desc 파일을 열어 Packages: 섹션을 수정합니다. 현재 zhcon이 포함된 라인을 찾아 이를 fbterm으로 대체합니다.
dch -i
Package: task-korean-desktop
Package: task-korean-gnome-desktop
Package: task-korean-kde-desktop
2025-10-09
ibus Dvorak and Qwerty and Hangul
![]() |
| Uncheck Use system keyboard layout |
National Museum of the World Writing Systems
한글날. 국립세계문자박물관 다녀옴.
세계 여러 나라의 글자를 볼 수 있었다. 지금까지 남아있는 문자도 있지만 한 때 있었다가 사라진 문자들도 많다. 그 중 한글은 참 독특하다. 다른 문자들은 언제 만들었는지 정확한 시기를 모른다. 그런데 한글은 다르다.
![]() |
| 훈민정음 서문 |
국립세계문자박물관 가려면?
전철 타면 인천1호선 센트럴파크 역 3번 출구로 나와 10분 쯤 걸어가면 나온다.
(우) 22004 인천광역시 센트럴로 217(송도동 24-8)
https://mow.or.kr/kor/
Debian task-korean zhcon or fbterm
https://packages.debian.org/ko/trixie/task-korean
zhcon 이 궁금하다.
구글 검색. github 보니 오래도록 변하지 않고 있는 듯. https://github.com/catroll/zhcon/issues/2
그렇다면 task-korean에 zhcon 대신 fbterm 넣는 게 낫지 않을까?
https://packages.debian.org/trixie/task-japanese 보니 zhcon 없고 fbterm 있다.
Console Hangul input output fbterm with uim
요즘 리눅스 괜찮다. 옛날에는 리눅스를 설치했다는 것만으로도 자랑할 수 있는 시절이 있었다. 요즘은 많이 좋아졌다. 콘솔에서 한글 입력하는 건 어떨까? 요즘도 쉽지는 않은 것 같다.
fbterm 쓰면 한글 출력 된다. 한글 입력은?
sudo apt install uim-fep 로 uim-fep 설치하고, fbterm 과 uim-fep 실행
fbterm -- uim-fep -u byeoru
콘솔에서 한영전환은 키보드에 있는 한/영 키로 안 된다. Ctrl-space, Shift-space 도 시도해봤는데 안 된다. 여러 번의 시행착오를 거친 결과.
X Window에서 uim-pref-gtk 실행시켜서 한영전환을 F2 키로 하는데 성공.
![]() |
| 한영전환 키 설정 |
direct 모드에서는 영어만, byeoru 모드에서는 F2 로 한영전환 하면서 쓸 수 있다.
한글 세벌식 쓸 수 있다.
![]() |
| 세벌식, 두벌식 설정 |
direct 모드와 byeoru 모드 전환은 F12로 하게 설정해 두었다.
![]() |
| direct 모드 byeoru 모드 전환 |
.fbtermrc 파일에서는 자기가 원하는 폰트, 크기 등을 설정할 수 있다.
아래 내용은 .fbtermrc 예시.
# Configuration for FbTerm
# Lines starting with '#' are ignored.
# Note that end-of-line comments are NOT supported, comments must be on a line of their own.
# font family names/pixelsize used by fbterm, multiple font family names must be seperated by ','
# and using a fixed width font as the first is strongly recommended
font-names=D2Coding
font-size=16
# force font width (and/or height), usually for non-fixed width fonts
# legal value format: n (fw_new = n), +n (fw_new = fw_old + n), -n (fw_new = fw_old - n)
font-width=8
font-height=20
# default color of foreground/background text
# available colors: 0 = black, 1 = red, 2 = green, 3 = brown, 4 = blue, 5 = magenta, 6 = cyan, 7 = white
color-foreground=7
color-background=0
# max scroll-back history lines of every window, value must be [0 - 65535], 0 means disable it
history-lines=1000
# up to 5 additional text encodings, multiple encodings must be seperated by ','
# run 'iconv --list' to get available encodings.
text-encodings=
# cursor shape: 0 = underline, 1 = block
# cursor flash interval in milliseconds, 0 means disable flashing
cursor-shape=0
cursor-interval=500
# additional ascii chars considered as part of a word while auto-selecting text, except ' ', 0-9, a-z, A-Z
word-chars=._-
# change the clockwise orientation angle of screen display
# available values: 0 = 0 degree, 1 = 90 degrees, 2 = 180 degrees, 3 = 270 degrees
screen-rotate=0
# specify the favorite input method program to run
input-method=
# treat ambiguous width characters as wide
#ambiguous-wide=yes
위와 같이 하면 영어 qwerty 와 한글(두벌식, 세벌식) 쓰는데 지장 없을 듯.
다만, 영어 Dvorak 과 한글을 함께 쓰는 건 미해결.
현재 상태. 쿼티와 한글 쓰는 건 됨.
Dvorak 상태에서 한글 쓰면 한글 나오긴 하는데 한글이 꼬임.
쿼 상태에서 한글 쓰면 한글 나오긴 하는데 Qwerty 아닌 영어 자판 쓰는 사람은 불편.
여러 방법 시도했으나 아직은 성공 못 함.
관련 이슈 https://github.com/uim/uim/issues/33 댓글 따라가면서 읽어보면 아래 커밋으로 해결되었다고 하는데 나는 모르겠음. 관련 글 https://github.com/uim/uim/issues/145
https://github.com/uim/uim/commit/f28132d48fc443dd73a945464e194a9af2d4bacb
2025-10-07
fbterm fcitx5 retry
WeHappyCh Admin Memo
우리행복한교회 홈페이지 관련 간단한 메모
우리행복한교회 홈페이지: wehappyc.org
회원가입하려면 위 홈페이지에서 JOIN 클릭.
회원레벨은 새싹회원과 성도회원이 있음. 가입하면 새싹회원. 관리자에게 요청하면 성도회원 레벨로 변경가능.
관리자 페이지는 관리자 페이지 권한 있는 사람만 접속 가능함.
관리자 권한을 받으려면 기존 관리자 중 한 사람에게 요청.
우리행복한교회 관리자 홈페이지: admin.wehappyc.org
관리자페이지 admin.wehappc.org 접속. ID password 입력하여 로그인
* 주일설교 동영상은 유튜브에 올리고 있으며, 우리행복한교회 홈페이지에는 설교 영상 유튜브 링크를 게시.
주일설교 등록방법은
콘텐츠 관리 - 주일설교 - 등록하기
* 영상보기 란에 입력할 사항 주의
유튜브 링크 에서 watch?v= 을 embed/ 로 바꾸어 영상보기 란에 입력
예시
유튜브 링크 https://www.youtube.com/watch?v=3jGYOzSn9jw
영상보기 란에 https://www.youtube.com/embed/3jGYOzSn9jw
아래 화면 참고
![]() |
| 클릭하면 큰 이미지 보임 |
다른 메뉴들은 특별한 설명이 필요 없을 듯. 관리자 페이지 관련 궁금하신 분은 기존 관리자 중 아무에게나 물어보면 될 것임.
fbterm input Hangul and English
![]() |
| Global |
![]() |
| Byeoru |
![]() |
| Byeoru key bindings1 |
Various Dvorak
2025-10-06
sudo update-alternatives --config editor
sudo update-alternatives --config editor
기본 에디터가 나노. 그런데 나는 익숙하지 않아서 vi로 바꿈.
2025-10-05
fbterm uim-fep
![]() |
| 벼루 |
![]() |
| 전역 설정 |
F12로 direct와 byeoru 전환 가능, F2도 됨.
![]() |
| 벼루 1메뉴 F2한영전환 |
Before choosuk
Solve fbterm errors
2025-10-02
memo uim dvorak hangul issue
Refresh keyboard map at each switch into Hangul mode
Global settings 탭: "Specify default IM engine" 활성화하고, 기본 엔진을 "byeoru"로 설정.
Byeoru 탭으로 이동:
"Korean keyboard layout"을 "3beol" (또는 "strict3final" 등 사용 중인 레이아웃)로 확인.
중요 옵션: "Refresh keyboard map at each switch into Hangul mode"를 활성화하세요. (한영 전환 시마다 키맵을 새로 고침하여 Dvorak 레이아웃을 반영합니다.)
"Use romaja input" 옵션을 활성화해 보세요. (로마자 기반 입력으로 전환하면 위치 매핑 문제가 사라집니다. Dvorak 문자를 로마자로 입력해 한글로 변환. 예: "annyeong" → "안녕". 한글 자판 학습 중이라면 임시로 유용.)
아직 안 해 봄.
byeoru hangul 3beol with Dvorak issue.
현재 상황. 벼루에서 한글 입력시 드보락과 함께 사용하면 한글 배열이 제대로 안 나옴. 그 문제 해결하려고 시도 중 망함.
같은 문제가 이미 github 에 보고되었다. 결론은 뭐지? https://github.com/uim/uim/issues/33 closed 되었는디? 나는 왜 아직도 같은 문제로 헤매고 있을까? 답은 뭘까?
사실 세벌식 만의 문제가 아니고 Dvorak 자판 쓰면 두벌식 사용자에게도 같은 문제 있을 듯.
아직은 미해결. gemini 설명대로 따라 하다가 uim-pref-gtk 죽는 상황 됨. 어디를 고쳐야 될지 몰라서 환경 설정 초기화
uim-pref-gtk 환경 설정 초기화 방법: .uim.d/ 디렉토리를 다 지우고 uim-pref-gtk 실행하면 기본 파일 자동 생성 됨. 다시 시도해 볼것 아래 내용
~/.uim.d/customs/custom-byeoru.scm
파일에 아래 두 줄 추가
(define byeoru-x-keyboard-layout "us")
(set! default-byeoru-x-keyboard-layout byeoru-x-keyboard-layout)
아래 내용 확인
(define byeoru-refresh-xkb-map-at-switch-on? #f) ; <-- 이 라인을 찾아 #f 로 설정
~/.uim.d/customs/custom-direct.scm
파일에
(define direct-x-keyboard-layout "dvorak")
(set! default-direct-x-keyboard-layout direct-x-keyboard-layout)
custom-byeoru-keys1.scm 파일 내용? 아래 내용 있는지 볼 것.
(define byeoru-on-key '("<Alt>Right")) ; 한글 켜기 (Right Alt)
(define byeoru-on-key? (make-key-predicate '("<Alt>Right")))
(define byeoru-latin-key '("<Alt>Right")) ; 로마자 켜기 (Right Alt)
(define byeoru-latin-key? (make-key-predicate '("<Alt>Right")))
(define byeoru-conversion-key '("F9"))
(define byeoru-conversion-key? (make-key-predicate '("F9")))
; ... 나머지 generic 키들은 그대로 둡니다.
custom-global-keys1.scm 파일 내용?
2025-10-01
sudo Without entering the password
특정 명령어를 암호 입력 없이 실행하기 예시.
터미널에서 'sudo visudo' 명령을 실행합니다.
2. 파일의 가장 마지막에 다음 두 줄을 추가합니다.(여기서 YOUR_USERNAME 부분을 실제 사용자 이름으로 변경해야 합니다.)
이 설정은 YOUR_USERNAME이 비밀번호 없이 loadkeys us와 loadkeys dvorak를
루트 권한으로 실행할 수 있도록 허용합니다.
YOUR_USERNAME ALL=(root) NOPASSWD: /usr/bin/loadkeys us
[input] can't change kernel keymap table, all shortcuts will NOT work, see SECURITY NOTES section of man page for solution.
[input] can't change kernel keymap table, all shortcuts will NOT work, see SECURITY NOTES section of man page for solution.
에러 날 때 여러 가지 경우가 있는데, fbterm에서 이런 에러가 난다면
sudo setcap 'cap_sys_tty_config+ep' /usr/bin/fbterm
2025-09-30
My .fbtermrc
2026 trend korea horse power
2025.09.29. 19:30 교보문고 전미영 발표
![]() |
| 2026 trend |
![]() |
| HORSE POWER |
2025-09-28
fbterm input hangul success
fbterm 실행하면 한글이 잘 나온다. 그런데 입력은? 어렵다. 불가능하다는 얘긴 아님.
uim 설치해서 uim으로 설정. 환경 설정하는 건 GUI 도움 받음.
LANG=en_US.UTF-8 uim-pref-gtk 에서 설정하면 됨.
한영 전환 Ctrl-space 그런데 한글이 안 나옴. Shift-space 한영전환 안 됨 이거 저거 시도하다가 Ctrl-Space 로 한영 전환 성공. 그런데 한글 배열이 이상하게 나옴. 내가 영어 드보락 쓰는데 이것과 세벌식이 얽히면 이런 문제가. 이 설정 관련 시도는 앞으로 계속할 예정.
일단 콘솔에서 한글과 영어 다 나오게 하는 건 성공.
fbterm -- uim-fep -u byeoru
이 명령으로 콘솔에서 한글 입력과 출력 성공.
한글이 이상하게 나오는 건 아래 글 참고해서 해결할 수 있을 듯.
https://sebuls.blogspot.com/2025/09/fcitx5-configtool.html
2025-09-27
When login: Not shown
이게 버그인지 아닌지는 모르겠는데 콘솔에서 Ctrl-D 여러번 치다 보면 login: 화면도 안 나오고 커서만 깜빡일 때가 있다.
아래와 같이 해주면 된다 tty1의 숫자를 2, 3, 4 등으로 바꾸면 해당 가상 콘솔에 login: 보여준다.
sudo systemctl restart getty@tty1.service
2025-09-26
fbterm give up. retry
2025-09-24
fcitx5-configtool Dvorak and 3beolsik
![]() |
| Dvorak 자판과 한글 자판 |
2025-09-21
nabi REMOVED from testing
2025-09-20
ddtp
2025-09-14
xfce4-kbdleds work in debian 13
Debian 12에서 잘 되던 게 Debian 13 으로 올린 다음 안 된다.
NumLock 상태를 보여주는 플러그인.
여러 시행착오 끝에 해결 했는데 나중에 보니 답이 README.md에 있었네.
그게 왜 안 보였던 걸까?
https://github.com/oco2000/xfce4-kbdleds-plugin/blob/master/README.md
여기서
./autogen.sh
./configure --prefix=/usr
sudo make install이것만 보고 따라 하다 왜 안 되지? 하고 여기 저기 헤매다가 바로 아래 줄에 있는 걸 못 봤네요.
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu
이 한 줄을 무심히 넘겼다가 수많은 시행착오의 반복.
--libdir=/usr/lib/x86_64-linux-gnu 이 한 줄 안 쓴 것 때문에 설치 다 된 플러그인이 화면에 안 나타남.
헤매면서 이것 저것 얻은 것도 많긴 하다.
lks-indicator
Debian 12에서 잘 쓰던게 13으로 올리니 안 되는 게 있다.
NumLock 상태를 보여주는 LED가 키보드에 없어서 프로그램 하나 설치해서 쓰던 게 있었는데... 그 프로그램에 13에서 안 된다.
대안 프로그램을 찾았다. lks-indicator
그런데 이 프로그램은 NumLock 켜지면 빨간색 꺼지면 녹색을 표시해준다.
내 맘에 안 들어서 켜지면 녹색, 꺼지면 빨간색으로 되게 살짝 바꿈.
바꾼 부분에 Sebul Change 라고 코멘트.
소스 코드를 여기에 그대로 붙이니 이상하게 나오네.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
###########################################################
# Author: Serg Kolo <1047481448@qq.com>
# Date: July 16, 2012
# Purpose: Simple indicator of Caps, Num, and Scroll Lock
# keys for Ubuntu
#
# Written for: http://askubuntu.com/q/796985/295286
# Tested on: Ubuntu 16.04 LTS
# Color changed by Sebul See below. Tested on Debian 13. Sep 14, 2025
###########################################################
#
# Licensed under The MIT License (MIT).
# See included LICENSE file or the notice below.
#
# Copyright © 2016 Sergiy Kolodyazhnyy <1047481448@qq.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the 'Software'), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import gi
gi.require_version('AyatanaAppIndicator3', '0.1')
from gi.repository import GLib as glib
from gi.repository import AyatanaAppIndicator3 as appindicator
from gi.repository import Gtk as gtk
import os
import subprocess
import argparse
class LockKeyStatusIndicator(object):
def __init__(self, show_all=False, ignore_keys=None, monochrome=False):
self.app = appindicator.Indicator.new('LKS', '',
appindicator.IndicatorCategory.APPLICATION_STATUS)
self.app.set_status(appindicator.IndicatorStatus.ACTIVE)
self.monochrome = monochrome
self.show_all = show_all
self.app_menu = gtk.Menu()
self.quit_app = gtk.MenuItem('Quit')
self.quit_app.connect('activate', self.quit)
self.quit_app.show()
self.app_menu.append(self.quit_app)
if ignore_keys is None:
self.ignore_keys = []
else:
self.ignore_keys = ignore_keys
self.app.set_menu(self.app_menu)
self.app_path = os.path.dirname(os.path.realpath(__file__))
self.icon_path = self.app_path
if self.app_path == '/usr/bin':
self.icon_path = '/usr/share/lks-indicator/'
else:
self.icon_path = self.app_path
self.red_icon = os.path.join(self.icon_path, 'red.png')
self.green_icon = os.path.join(self.icon_path, 'green.png')
self.monochrome_icon = os.path.join(self.icon_path, 'lks-icon-monochrome.png')
self.update_label()
def run(self):
try:
gtk.main()
except KeyboardInterrupt:
pass
def quit(self, data=None):
gtk.main_quit()
def run_cmd(self, cmdlist):
try:
stdout = subprocess.check_output(cmdlist)
except subprocess.CalledProcessError:
pass
else:
if stdout is not None:
return stdout.decode('utf-8').rstrip('\n')
def key_status(self):
label = ''
status = []
keys = {
'3' : 'C',
'7' : 'N',
'11' : 'S'
}
for line in self.run_cmd(['xset', 'q']).split('\n') :
if 'Caps Lock:' in line:
status = line.split()
for index in 3, 7, 11:
if keys[str(index)] in self.ignore_keys:
pass
elif status[index] == 'on':
label += ' [' + keys[str(index)] + '] '
elif self.show_all:
label += keys[str(index)]
return label
def update_label(self):
label_text = self.key_status()
if not self.monochrome:
if '[' in label_text:
self.app.set_icon(self.green_icon) # Sebul change
else:
self.app.set_icon(self.red_icon) # Sebul change
else:
self.app.set_icon(self.monochrome_icon)
label_text = label_text.replace('[C]',u'\u24B8')
label_text = label_text.replace('[N]',u'\u24C3')
label_text = label_text.replace('[S]',u'\u24C8')
self.app.set_label(label_text, '')
glib.timeout_add_seconds(1, self.set_app_label)
def set_app_label(self):
self.update_label()
def main():
arg_parser = argparse.ArgumentParser(
description='''lks-indicator - Indicates on/off status of Lock keys.''',
formatter_class=argparse.RawTextHelpFormatter)
arg_parser.add_argument(
'--show-all', action='store_true',
help='Show all keys in label', required=False)
arg_parser.add_argument(
'-m','--monochrome', action='store_true',
help='Use monochrome icon')
arg_parser.add_argument(
'--ignore-keys', type=str,
help='Ignore specified keys (C, N or S)',
nargs='+', required=False)
args = arg_parser.parse_args()
indicator = LockKeyStatusIndicator(
show_all=args.show_all,
ignore_keys=args.ignore_keys,
monochrome=args.monochrome)
indicator.run()
if __name__ == '__main__':
main()
2025-09-13
9.5-9.8
2025.9.5 - 9.8 수안보 여행
수안보연수원, 충주박물관, 탄금대
영화식당: 여러가지 나물. 고기만 좋아하는 사람들은 아쉬울 수도. 나물만 나오는데 가격은 그리 싸지 않음.
청운식당: 수안보 주민이 추천한 꿩고기 집.
2025-08-16
SigolHyanggi
경기 김포시 고촌읍 신곡로 114-8
방송에 나온 곳은 운양걸포점.
2025-08-11
Rolling Rice
롤링 라이스. 강화도 용흥궁 근처 식당
강화군 강화읍 북문길 14
롤링 세트 메뉴 18500원
단품으로 하면 롤링떡볶이 4500 김치치즈볶음밥 8500 라면 5000원
음료 1을 500원에 주는 꼴.
사진은 나중에.
사장님 건강해보이기에 나이 물으니 이 가게 12년 했다고 하시며 여러가지 운동 이야기. 나이는 안 가르쳐주심.
2025-05-10
ai06_5 NalMok
#import pdb
import sys
import random
from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox, QPushButton
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt, QTimer, QPoint
BOARD_SIZE = 19
CELL_SIZE = 40
STONE_RADIUS = CELL_SIZE>>1
EMPTY = 0
BLACK = 1
WHITE = 2
#보드 바탕색
BOARD_COLOR = QColor(222, 184, 135)
# 나이트 이동 방향
NALMOK_DIRECTIONS = [(1, 2),(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (2, -1), (2, 1)]
class NalmokGame(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("날목")
self.setFixedSize(BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE +50)
self.board = [[EMPTY for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
self.move_history = []
self.game_over_flag = False
self.winning_line = [] # 승리한 5개 돌의 좌표를 저장할 리스트
self.last_black_move = None
self.last_white_move = None
undo_button = QPushButton("Undo", self)
undo_button.move(10, self.height() - 40)
undo_button.clicked.connect(self.undo_move)
# 컴퓨터가 흑으로 시작
center = BOARD_SIZE // 2
self.place_stone(center, center, BLACK)
self.turn = WHITE
self.show()
def paintEvent(self, event):
qp = QPainter()
qp.begin(self)
self.draw_board(qp)
self.draw_stones(qp)
self.draw_winning_line(qp) # 승리한 돌을 표시하는 함수 호출
qp.end()
def draw_winning_line(self, qp):
if self.winning_line:
qp.setPen(QPen(QColor(0, 255, 0), 3)) # 녹색으로 강조
for x, y in self.winning_line:
cx = STONE_RADIUS + x * CELL_SIZE
cy = STONE_RADIUS + y * CELL_SIZE
qp.drawEllipse(cx - STONE_RADIUS // 2, cy - STONE_RADIUS // 2, STONE_RADIUS, STONE_RADIUS)
def draw_board(self, qp):
qp.setBrush(BOARD_COLOR)
qp.drawRect(0, 0, self.width(), self.height())
qp.setPen(QPen(Qt.black, 1))
for i in range(BOARD_SIZE):
qp.drawLine(STONE_RADIUS, STONE_RADIUS + i * CELL_SIZE,
STONE_RADIUS + (BOARD_SIZE - 1) * CELL_SIZE, STONE_RADIUS + i * CELL_SIZE)
qp.drawLine(STONE_RADIUS + i * CELL_SIZE, STONE_RADIUS,
STONE_RADIUS + i * CELL_SIZE, STONE_RADIUS + (BOARD_SIZE - 1) * CELL_SIZE)
star_points = [(3, 3), (3, 9), (3, 15), (9, 3), (9, 9), (9, 15), (15, 3), (15, 9), (15, 15)]
for x, y in star_points:
cx = STONE_RADIUS + x * CELL_SIZE
cy = STONE_RADIUS + y * CELL_SIZE
qp.setBrush(BLACK)
qp.drawEllipse(cx-3, cy-3, 6, 6)
def draw_stones(self, qp):
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] != EMPTY:
qp.setBrush(QColor(0, 0, 0) if self.board[y][x] == BLACK else QColor(255, 255, 255))
qp.drawEllipse(
STONE_RADIUS + x * CELL_SIZE - STONE_RADIUS,
STONE_RADIUS + y * CELL_SIZE - STONE_RADIUS,
STONE_RADIUS * 2,
STONE_RADIUS * 2
)
last = self.last_black_move if self.turn == WHITE else self.last_white_move
# pdb.set_trace()
if last:
x, y = last
cx = STONE_RADIUS + x * CELL_SIZE
cy = STONE_RADIUS + y * CELL_SIZE
qp.setPen(QPen(BOARD_COLOR, 2))
qp.drawRect(cx-1, cy-1, 3, 3)
def mousePressEvent(self, event):
if self.game_over_flag or self.turn != WHITE:
return
x = int((event.x() - STONE_RADIUS + CELL_SIZE / 2) // CELL_SIZE)
y = int((event.y() - STONE_RADIUS + CELL_SIZE / 2) // CELL_SIZE)
if 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE and self.board[y][x] == EMPTY:
self.place_stone(x, y, WHITE)
if self.check_win(x, y, WHITE, True): # 승리 시 winning_line 업데이트
self.update()
self.game_over("사용자(백) 승리!")
return
self.turn = BLACK
self.update()
QTimer.singleShot(1, self.computer_move)
def place_stone(self, x, y, stone):
self.board[y][x] = stone
self.move_history.append((x, y, stone))
if stone == BLACK:
self.last_black_move = (x, y)
else:
self.last_white_move = (x, y)
def undo_move(self):
if len(self.move_history) >= 2:
for _ in range(2):
x, y, stone = self.move_history.pop()
self.board[y][x] = EMPTY
if stone == BLACK:
self.last_black_move = None
else:
self.last_white_move = None
self.turn = WHITE
self.winning_line = [] # Undo 시 승리선 초기화
self.update()
def check_win(self, x, y, stone, update_winning_line=False):
winning_stones = []
for dx, dy in NALMOK_DIRECTIONS:
line = [(x, y)]
count = 1
for dir in [1, -1]:
for i in range(1, 5):
nx, ny = x + dx * i * dir, y + dy * i * dir
if 0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE and self.board[ny][nx] == stone:
line.append((nx, ny))
count += 1
else:
break
if count >= 5:
if update_winning_line:
self.winning_line = line
return True
return False
def should_block_nalmok(self, x, y, stone, length):
for dx, dy in NALMOK_DIRECTIONS:
count = 0
blocked = 0
for dir in [1, -1]:
temp_count = 0
temp_blocked = 0
for i in range(1, length):
nx = x + dx * i * dir
ny = y + dy * i * dir
if 0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE:
cell = self.board[ny][nx]
if cell == stone:
temp_count += 1
elif cell == EMPTY:
continue
else:
temp_blocked += 1
break
else:
temp_blocked += 1
break
if dir == 1:
count += temp_count
blocked += temp_blocked
else:
count += temp_count
blocked += temp_blocked
if count == length -1 and blocked < 2:
# Check if placing a stone at (x, y) would complete the sequence
placed = False
for dir in [1, -1]:
nx_check = x + dx * length * dir
ny_check = y + dy * length * dir
if 0 <= nx_check < BOARD_SIZE and 0 <= ny_check < BOARD_SIZE:
if self.board[ny_check][nx_check] == stone:
continue # Already blocked on this side
else:
continue # Already blocked on this side
temp_board = [row[:] for row in self.board]
temp_board[y][x] = stone
win = False
check_count = 1
for check_dir in [1, -1]:
for i in range(1, 5):
cx, cy = x + dx * i * check_dir, y + dy * i * check_dir
if 0 <= cx < BOARD_SIZE and 0 <= cy < BOARD_SIZE and temp_board[cy][cx] == stone:
check_count += 1
else:
break
if check_count >= 5:
win = True
if count == length - 1 and blocked < 2:
can_extend = False
for dir in [1, -1]:
nx_extend = x + dx * length * dir
ny_extend = y + dy * length * dir
if 0 <= nx_extend < BOARD_SIZE and 0 <= ny_extend < BOARD_SIZE and self.board[ny_extend][nx_extend] == EMPTY:
can_extend = True
break
if can_extend or blocked == 0:
return True
return False
def evaluate_board(self, stone):
score = 0
opponent = WHITE if stone == BLACK else BLACK
# Evaluate score for the given stone
for length in range(2, 5):
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY and self.should_block_nalmok(x, y, stone, length):
if length == 4:
score += 1000
elif length == 3:
score += 100
elif length == 2:
score += 10
# Evaluate score for the opponent to subtract potential threats
for length in range(2, 5):
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY and self.should_block_nalmok(x, y, opponent, length):
if length == 4:
score -= 900 # Less priority to block than to create own 4
elif length == 3:
score -= 90
elif length == 2:
score -= 9
return score
def computer_move(self):
if self.game_over_flag:
return
# 우선순위 1: 컴퓨터 승리 수 (5개)
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY:
self.place_stone(x, y, BLACK)
if self.check_win(x, y, BLACK, True): # 승리 시 winning_line 업데이트
self.update()
self.game_over("컴퓨터(흑) 승리!")
return
self.board[y][x] = EMPTY
self.move_history.pop()
# 우선순위 2: 컴퓨터가 만들 수 있는 열린 4
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY and self.should_block_nalmok(x, y, BLACK, 4):
self.place_stone(x, y, BLACK)
self.turn = WHITE
self.update()
return
# 우선순위 3: 상대방의 즉각적인 승리 차단 (5개)
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY:
self.place_stone(x, y, WHITE)
if self.check_win(x, y, WHITE, True): # 승리 시 winning_line 업데이트
self.board[y][x] = EMPTY
self.move_history.pop()
self.place_stone(x, y, BLACK)
self.turn = WHITE
self.update()
return
self.board[y][x] = EMPTY
self.move_history.pop()
# 우선순위 4: 상대 열린 4 차단
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY and self.should_block_nalmok(x, y, WHITE, 4):
self.place_stone(x, y, BLACK)
self.turn = WHITE
self.update()
return
# 우선순위 5: 컴퓨터 공격 - 열린 3 만들기
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY and self.should_block_nalmok(x, y, BLACK, 3):
self.place_stone(x, y, BLACK)
self.turn = WHITE
self.update()
return
# 우선순위 6: 상대 열린 3 차단
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY and self.should_block_nalmok(x, y, WHITE, 3):
self.place_stone(x, y, BLACK)
self.turn = WHITE
self.update()
return
# 우선순위 8: 평가 기반 최적 수
best_score = -float('inf')
best_move = None
center = BOARD_SIZE // 2
search_range = 5 # 중앙 근처 탐색으로 연산량 감소
for y in range(max(0, center - search_range), min(BOARD_SIZE, center + search_range)):
for x in range(max(0, center - search_range), min(BOARD_SIZE, center + search_range)):
if self.board[y][x] == EMPTY:
self.board[y][x] = BLACK
score = self.evaluate_board(BLACK) - self.evaluate_board(WHITE)
self.board[y][x] = EMPTY
if score > best_score:
best_score = score
best_move = (x, y)
if best_move:
x, y = best_move
self.place_stone(x, y, BLACK)
self.turn = WHITE
self.update()
return
# 대체 수: 최근 돌 근처 나이트 이동 (더 안전한 수)
possible_moves = []
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == BLACK:
for dx, dy in NALMOK_DIRECTIONS:
nx, ny = x + dx, y + dy
if 0 <= nx < BOARD_SIZE and 0 <= ny < BOARD_SIZE and self.board[ny][nx] == EMPTY:
possible_moves.append((nx, ny))
if possible_moves:
move = random.choice(possible_moves)
self.place_stone(move[0], move[1], BLACK)
self.turn = WHITE
self.update()
return
# 정말 둘 곳이 없다면 랜덤으로
empty_cells = []
for y in range(BOARD_SIZE):
for x in range(BOARD_SIZE):
if self.board[y][x] == EMPTY:
empty_cells.append((x, y))
if empty_cells:
move = random.choice(empty_cells)
self.place_stone(move[0], move[1], BLACK)
self.turn = WHITE
self.update()
return
def game_over(self, message):
self.game_over_flag = True
self.update() # 마지막 돌을 포함한 승리선을 표시하기 위해 update 호출
QMessageBox.information(self, "게임 종료", message)
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
game = NalmokGame()
sys.exit(app.exec_())




















