全破了一輪。遊戲是橫向捲軸、類惡魔城遊戲。遊戲長度只有幾小時就能全破一輪。目前好像沒多周目要素。作為動作遊戲簡單爽快,裡面有些小機制,例如風火抗性要即時、輪流切換才能順利破關和打王有趣。
不過遊戲最香的,還是長腿精靈大姊姊蒂德莉特,哪怕是像素版一樣香。遊戲聽說還是羅德斯島戰記小說原作者的監督下完成的。
唯一小遺憾的是結局,雖然從小說續作已經知道了,但看到和帕恩的相遇只是夢一場,恢復記憶醒來後蒂德莉特去墳前告別,仍然是有點心酸。
壓力好像真的是寫程式的動力。
大富翁系列是小時候很喜歡的遊戲之一,特別是二代、三代、四代(五代以後玩不習慣,都是玩了秒刪)。Steam 出了 DOSBox 版就入手了,二三代是重溫,四代是補票 XD
這幾天花了八小時把三代破過一輪,實現了孫小美的勝利 XD 以現在眼光來看,遊戲不困難,AI 太笨,特別是不會濫用道具和炒股存股。三代的道具店遙控骰子和路障還可以無限制買,搭配黑市存夠道具和卡片後基本就鎖定勝局,連 S/L都不大需要。
這塊地很值錢呢,他是我的了(使用購地卡)~
踩到噴錢的地點了,喔嫁禍卡和免費卡的複合式反應裝甲還有四層那沒事了~
AI 真是好心人有高價卡片都捨不得用拿來送我呢,看我用搶奪卡搶奪你所有的搶奪卡再搶走你其他高價卡~
不過 AI 雖笨,但回憶無價,當年玩二代三代的時候還是國小屁孩。現在重溫兼補票,很遺憾 Steam 版四代目前沒有超時空之旅,看未來官方會不會補了。
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
Docker container 長時間執行後常遇到大量佔據硬碟空間,docker system prune 沒用,一個可能兇手就是大量 container log。用指令把冗餘 log file 清掉就能取回空間。新版 docker 好像有 log rotation 機制,有機會再研究
全文連結
工作累積太多疲勞,剛好遇到中秋連假,就額外多請幾天,湊了六天連假來自助小旅遊。
本來考慮去九族文化村和日月潭,但想到本肥年近 40、體重近 90,續航力不佳,戶外景點很怕玩三小時人就沒力,然後就得回飯店待機。所以後來決定去台北。台北戶外玩累還可以玩室內行程,最不濟還有書局。這次行程玩了許多過去沒玩過,或很久沒來過的點。
這次去了陽明山。但這次沒做太多功課,純粹隨緣,結果有點失敗。大部分時間花在走路和搭公車移動上,吸了很多芬多精但沒看到太多景點有點可惜。
陽明山上散步吸芬多精,來的時間不對,動線沒規劃完整,沒看很多景點,但至少吸了芬多精 XD
路上遇到野怪 -- 貓貓。貓貓看來並不怕人。至少肯擺 pose 給拍照
數位放大後的貓貓,不親人但也不怕人
回來前一天去了貓空。貓空是從來沒玩過的景點。貓空景點相對集中,下捷運動物園站後搭纜車到貓空站,然後徒步移動走玩右線和一部分左線。貓空真的有點日本小鎮的感覺。
貓空天恩宮,路過拍照,沒進去看
在貓空纜車上照到的街景
貓空夕陽照,剛好抓到太陽下山的 timing
Y 區地下街照片,Y區地下街這次沒玩到太多,室內行程都去天瓏書局看書了
西門町夜景,新換的 S20FE 夜拍確實比前一支 LG V20 給力。
虎之穴店門口,還沒進店門在樓梯應該是可以拍照的 XD
台北宅行程必逛安利美特,就算什麼都沒買來吸吸宅氣也好。永恆不變的入口照 XD
永遠的經典新世紀福音戰士。動畫擺了 N 年但永遠沒看完的一天 XD
新流行的作品,但個人對腐是完全不能接受的 XD
這次旅行唯一小遺憾就是沒掀到 Twsam,他說可愛小寶寶剛回家應該無法分身!看來未來幾年掀到的機率也非常渺茫了 QQ。當年 TFCIS iii 程設組五人,kochi 已知結婚生子,DNA 結婚更早,現在 Twsam 的狀態也從已知單身忽然跳到有小孩(看過低調的沒看過這麼低調的 XDDDD),DreamLinuxer 在美國,所以進度停滯不前的單身漢就剩下我了嗎?
好久沒廢寢忘食打 FPS 。這款躺在 Steam 吃灰很長一段時間,忘記為什麼忽然想拿出來打,但來了興趣就一口氣破完。
遊戲充滿了各種對立、矛盾元素。遊戲發生在海底遠離主世界塵囂的的烏托邦 -- 銷魂城(Rapture city)。裡面建築風格明明是幾十年前的美國,卻有遠超地表的超級黑科技,例如能讓人飛簷走壁、發射火球、閃電、甚至粒子化瞬間移動的基改技術。
但美侖美奐的城市卻因濫用基改物質(ADAM)和內鬥等因素,最後變成反烏托邦。美麗如渡假飯店的城市,內部最常見的住民卻是被 ADAM 侵蝕神智、精神失常的瘋子,或是被肉體心靈雙重改造蒐集 ADAM 的 Little girl 和其保護者 Big daddy。
遊戲的主線故事也牽涉到善惡兩極反轉,遊戲以主角墜機剛好來到銷魂城開始,在戰友透過收音機指導棋的幫助下,一路披荊斬棘幫自己逃生,並尋找殺死戰友家人、控制城市的惡魔。最後真相揭曉,惡魔也許不是好人,但戰友卻不是戰友。最後主角成功解除自身被埋下的心靈暗示,踏過屍山血海打死最終 BOSS,迎來結局。
遊戲的戰鬥系統有其特色,在後續系列作也持續使用。主角有 FPS 標配的槍械類武器的同時,也能透基改 plasmid 掌控各種能力,例如放電、引火、召喚蟲群、催眠他人等類法術能力、或提昇駭客技術、提高抗性等自我改造。主角也有駭客技術,遇到機械類敵人也能選擇解拼圖、改寫敵人邏輯取得控制權。遊戲連貨幣都有兩種,能買槍械子彈恢復藥劑的金錢,還有可以用來買 plasmid 或提自己能力的 ADAM。
遊戲過關還是要用點心思,特別是跟 Big Daddy 的戰鬥,對手攻高血厚硬拼往往拼不過,特別是什麼都缺的前期。要打贏必須用策略,例如激怒 Big Daddy 後把他引到被我方控制的火箭炮台。透過能造成麻痺的電擊 plasmid 不停強控、直到他被火箭炮擊殺。或是用催眠 plasmid 控制另外一個 Big Daddy 製造內鬥再減尾刀等。地圖本身也有少量解謎元素,例如被冰封的門要用點火能力打開、放在拿不到地方的鑰匙要用格空取物能力取得。
遊戲武器、Plasmid 都有升級系統。武器可以透過特定地點升級,解鎖更強的威力、豁免自己武器傷害等升級。Plasmid 可以在遊戲過程中買、合成更強的版本,付出 ADAM 解鎖更多安裝位置等。
遊戲有多重結局。結局好壞取決於怎麼處理 Little Sister。打倒 Big Daddy 後選擇殺掉 Little Sister 可以獲得更多 ADAM 卻會導向壞結局。選擇救贖 Little Sister 解除讓其變回常人,得到的 ADAM 會少一些,但從頭到尾都選救贖,遊戲才能有好解局。但救贖之路科學家其實會送禮表達感謝,算上禮物價值後其實 ADAM 沒少拿多少,我選擇救贖、最後看到好結局。
破關後再選 new game 發現有二周目 new game plus,但暫時沒力氣玩了。
在公司打報告,希望用 OCR 判讀螢幕數字並自動抄錄以減少作業時間。這功能需要每個螢幕的長寬大小(pixel)才能讓程式知道 OCR 該看螢幕截圖的哪個位置。
原本是用 Autohotkey 的 SysGet Monitor 解決。但 SysGet 傳回的資料是錯的,也沒體力除錯了。為了省工不想寫額外程式,希望能用簡單的腳本解決。後來發現 powershell 可以做這件事情
Get-WmiObject -Class Win32_VideoController | Out-File screen.out輸出結果導向到檔案儲存,然後回 Autohotkey 從檔案中用 regex 從 VideoModeDescription 讀出解析度數值,然後做些加減乘除就有各螢幕大小和座標了。 值得一提的是其他的失敗方案:
Add-Type -AssemblyName System.Windows.Forms
System.Windows.Forms.Screen]::AllScreens這個 powershell 方法能得到全螢幕解析度,但會受到 scaling factor 干擾,得到的 width、height 必須乘以該螢幕的對應 scaling factor 才能還原為真實的螢幕解析度,但找了一陣子沒發現快速得到 scaling factor 的方法,因此就放棄此法。
[System.Windows.Forms.SystemInformation]::PrimaryMonitorSize 這個方法則是只能得到主螢幕解析度,看不到第二第三顆的。
年紀真的大了,花了一個半小時研究城市又開始眩暈 QQ
--------------------------------------------
$pinvokeCode = @"
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace Resolution
{
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE1
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
};
[Flags()]
public enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>The device is part of the desktop.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x10,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct DISPLAY_DEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public string DeviceKey;
}
class User_32
{
[DllImport("user32.dll")]
public static extern int EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE1 devMode);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(ref DEVMODE1 devMode, int flags);
[DllImport("user32.dll")]
public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
public const int ENUM_CURRENT_SETTINGS = -1;
public const int CDS_UPDATEREGISTRY = 0x01;
public const int CDS_TEST = 0x02;
public const int DISP_CHANGE_SUCCESSFUL = 0;
public const int DISP_CHANGE_RESTART = 1;
public const int DISP_CHANGE_FAILED = -1;
}
public class Displays
{
public static IList<string> GetDisplayNames()
{
var returnVals = new List<string>();
for(var x=0U; x<1024; ++x)
{
DISPLAY_DEVICE outVar = new DISPLAY_DEVICE();
outVar.cb = (short)Marshal.SizeOf(outVar);
if(User_32.EnumDisplayDevices(null, x, ref outVar, 1U))
{
returnVals.Add(outVar.DeviceName);
}
}
return returnVals;
}
public static string GetCurrentResolution(string deviceName)
{
string returnValue = null;
DEVMODE1 dm = GetDevMode1();
if (0 != User_32.EnumDisplaySettings(deviceName, User_32.ENUM_CURRENT_SETTINGS, ref dm))
{
returnValue = dm.dmPelsWidth + "," + dm.dmPelsHeight;
}
return returnValue;
}
public static IList<string> GetResolutions()
{
var displays = GetDisplayNames();
var returnValue = new List<string>();
foreach(var display in displays)
{
returnValue.Add(GetCurrentResolution(display));
}
return returnValue;
}
private static DEVMODE1 GetDevMode1()
{
DEVMODE1 dm = new DEVMODE1();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
return dm;
}
}
}
"@
Add-Type $pinvokeCode
[Resolution.Displays]::GetResolutions();結果本以為能用的方法失敗,最後換了這個方法,在 Autohotkey 中呼叫 powershell.exe 執行這段腳本,用 Out-File 導出成文字檔用 regex parse。 話說 powershell 可以直接執行 C# 代碼耶,作為「腳本語言」這會不會太強了點?XDDDDD
全文連結 改自 ptt 的發文
以個人經驗來說,醫療人會點程式有沒有用?個人經驗是有的,我自己弄的東西:
有引擎前,蒐集 case 主要靠自己作筆記。有引擎後 keyword 和查詢條件丟下去 case就噴出來。可能辛苦作筆記收了不曉得多久才能收一兩百個,引擎只要用正確的搜尋條件一分鐘就生出一千個。
最近做回溯研究收案超過兩千個。這幾天弄出 RPA 機器人可以自動填病歷號查資料,申請通過正式上線。一樣的事情,別人可能要弄經費、請助理、花不知道多久搞定。我自己做可能電腦多開幾個晚上還不用想辦法找錢。
學會 Autohotkey,可以打 fu 自動變成 Advise follow-up,一鍵自動從其他表單帶入資料、一鍵文字自動排版...
隨著技能樹越來越深廣,能做的事情還能越來越炫炮,例如
幫普通表單程式加上改字型、拼字檢查、自動完成、顏色佈景...等功能。潛在應用的地方很多,例如 HIS 或 RIS 各式表單程式。
以前會想:這種事委託專門單位、學校、或是外包廠商不就能做?自己會的價值在哪裡?
後來發現專門單位可以非常忙,手上待處理的案件可以到四位數。需求如果對全院不夠重要、急迫不一定能可以做,可以做也可能要排隊,排隊成功程式開始做也可能要反覆修改處理眉角問題,每次修改可能又是另一個循環。學校或外包廠商做,要想辦法弄資源,弄計畫、請經費、etc,一個程式綁一堆東西,原始碼還可能在別人手上、以後只能一直投入。自己弄就沒有上述一堆問題、程式想改就開記事本改就好。
「又快又好」是可能形成價值的。以大規模撈 case 查資料做回溯性研究為例,別人流程是:
1. 寫申請單委託資訊單位
2. 花時間排隊(可以等很久)
3. 得到結果,發現眉角問題、協商修正 * N(用 nodule 查結果 Nodule、nodlue 沒撈到 etc.)
4. 請助理一筆筆查資料整理
5. 生成那張跑統計的 Excel 表格。
而如果都能自己做呢?可能 IRB 通過的當天,下班前搜尋引擎就把 case 列出來了。然後多花幾個晚上用機器人把資料查好。最後用 python 字串、報表分析,很快就能統計好大部分資料,這時候可能別人還在排隊。大幅改善效率,就能大幅降低投入成本和時間,就能顯著提高研究成功率。這時哪怕作為醫療人員和研究者的本職技能都不頂尖,別人也會願意合作。
就算一時做不了這些事,起碼也能讓自己上班更輕鬆。別人花時間按 Enter 和空白幫報告排版還是從其他系統抄數字,你一鍵就無腦完成,更快下班不好嗎?如果喜歡寫,替自己節省精力,創造機會的同時還能做喜歡的事,緩解 burnout 不香嗎?
所以如果本來就有寫程式的興趣,可以繼續鑽研深入,然後設法找自己周圍有必要但別人顧不到的事,遵循法規、看好政治和環境允許的限度,抓準機會切進去,programming skill 不會虧待我們。
至於學哪些語言,我是學 Python 和 Autohotkey 為主。AHK 主攻辦公室自動化,Python 補一些 AHK 不好做的事情,例如運用瀏覽器自動化測試套件自動點頁面之類。Python 也可以銜接 Machine Learning 和 Deep learning。另外零碎玩過一些 Rust、C/C++、PHP 之類的東西,但這些對醫療職業可能就不那麼直接有用。
值得一提的是數學,有後悔沒趁年輕的時候學好數學,最近鑽研 Deep learning 和統計都遇到數學的檻,回頭補同濟的高等數學。結果現在奔四體質變差很多,用腦一多就 tinnitus 甚至 vertigo,而且有些基礎的東西忘了還要「復健」。所以如果還在學校,學習數學其實是好選擇。程式語法那些在有明確目的的情形下快速入門不難,但數學就不行。線性代數和微積分剛好也是現在 deep learning 會用到的東西。
最近又一次受 VB6.0 荼毒迫害。
最近和其他單位同事合作回溯性分析,分析公司用戶資料。資料能透過資訊系統一筆筆查,問題是筆數多(N>2K),資料分散在不同報表程式和網頁表單上。因各種因素,不能直連 production DB 下 SQL。反覆請人代撈實務不可行。但政策不禁自動化軟體代替鍵盤滑鼠操作報表軟體,只要遵循審查流程。
然後就又跟 VB6.0 槓上了。很大部份資料需透過一 VB6.0 報表軟體查詢。報表軟體上有 ListView 顯示用戶的多筆紀錄,操作者點選 ListView 上的紀錄,程式跳出對應該紀錄的進一步細節。
真人鍵盤滑鼠操作沒啥問題,用自動化 VB6 就開始不講武德。
在家中做模擬,就發現 MSDN 上的東西很多對 VB6 沒用。例如,MSDN 說 LVM_SETITEMSTATE 可以改變 ListView 目前被圈選的 item。實際使用畫面上 ListView 被 highlight 的 item 會變,但後續 side effect 不會觸發。又例如 MSDN 說 LVM_SETITEM 可改變 ListView 呈現的資料,結果實際使用只會改畫面上的資料,隨便重排資料修改就不見了。
那用 code injection 解決呢?很久前就試過,VB6 編出來的 code 本質是編成 native code 的虛擬機操作,大量意義不明的中間變數和莫名操作,一切 control flow 最終回歸 MSVBVM60.DLL 和元件庫。有效操作被嚴重稀釋。逆向天然自帶虛擬機的 binary 嚴重超過我業餘用戶的能力,我連自己寫的 mock 都沒辦法分析,生產環境中的報表軟體就不用試了。
最後,又一次倒在 VB6 鐵拳之下,還是只有模擬鍵盤滑鼠按鍵的方式可行。方案沒技術含量,而且使用期間電腦不能操作,但自動點選存資料還是弄出來了,之後走審查流程後就在公司內正式開發、使用。順利的話能解決分析需求,還有機會與另外一個 side project (搜尋引擎)形成連動,做成一條龍。
業餘 side project 坑好像越挖越大,一開始是好玩,然後是實用,現在目標變成發展產業鏈了 XDD。但還是要吐槽 VB6,根本就上個時代的遺毒...
別人的遊玩影片 XD
某次趁特價入手的 Steam ARPG 小品黃油(羞)。最近剛普通難度通過一輪。
故事中規中矩,就英雄巫女拯救世界。特色是動作非常有打擊感確實夠要求技術。另外有豐富的收集、再挑戰和多周目元素。第一周照攻略花了很多時間弄了釣魚、蒐素材繼承武器 etc.。破台一輪後出現挑戰模式,可以獎勵點數強化下週目角色等。
攻略中那種無傷打出幾百連擊實在太誇張了,我劇情黨後期只用一兩招反覆搭配食物補血硬換而已....哪天想打困難、地獄模式再開來研究吧 XD
雖說在 Windows 下寫 Python 大多時候我靠 WinPython 解決,但特殊情況下可能需要可攜、精簡的 Python 執行環境。官方的 python windows embeddable package 內容簡單,但缺少 PIP,而這篇文提供了裝好 PIP 的方法。
第一行加入 Lib/site-packages,最後一行 import site 移除註解,改好後檔案類似
Lib/site-packages
python39.zip
.
# Uncomment to run site.main() automatically
import site接下來進 python 根目錄,下載 get-pip.py,然後用 python 執行
python get-pip.pyset PATH=%PATH%;%CD%;%CD%\Scripts寫好存檔後在 python 目錄下執行。
一切弄好後,試驗 pip install selenium 成功!
全文連結
小時候 DOS 時代的的回憶,中文操作手冊還保留很久當成故事書看 XD。真的二十年沒玩了,趁最近上架 Steam 就買回來懷舊。Steam 版還是有小問題,就是沒有雲端存檔,要手動備份同步存檔,不過 DOS 遊戲目錄結構簡單,存檔位置很好找。
以現在眼光來看,遊戲有些機制其實太 hard core。高難模式死掉強制刪存檔。某些會負能量攻擊或石化的敵人太強,一打中就是掉等級或秒殺。遊戲還很少鑑定手段拿了一堆藥和裝備不知道幹麻,等快過了才從攻略網站知道有艾恩石可以防石化即死或負能量打落等級。
遊戲平衡也不大行,牧師太強勢了,治療、提供食物、防負能量打落等級、水下呼吸、解詛咒裝備、解毒....都集中在同一個職業,導致有沒有兼職牧師打起來根本就是兩款遊戲。
不過這遊戲不是玩遊戲性,是玩懷舊時光穿梭回憶小時候的,小時候很害怕陰暗地下城的氣氛,英文還不好,好像從來沒下過第二層,這次 Steam 版終於破了一輪 XD