2025/01/13

王國的興起

《王國的興起》(Rise of Nations) 是一款即時戰略遊戲。遊戲由 Big Huge Games 公司開發,並由微軟公司在 2003 年 5 月 20 日發行。 2004年 4月 28 日又發行了資料片《王國的興起:政權保衛戰》(Rise of Nations: Thrones and Patriots)。 《王國的興起:擴展版》(Rise of Nations: Extended Edition) 是本作的擴展版, 於 2014 年 6 月在 Steam 發行,於 2017 年 9 月在 Windows 10 商店發行,但是擴展版有 Object Masks Bug 會影響平衡。 《王國的興起》主要是以城市為單位的發展模式,並且有國家疆界的概念,遊戲中隨著時代演進,還能夠興建包括金字塔、泰姬陵等各種世界奇觀。

可以參考的資料:

《王國的興起》如果使用光碟安裝,需要 MFC 4.2(輸入 CD key 時會用到),以及遊戲中需要 DirectMusic 播放音樂。 如果要使用 WINE 執行,建議要特別為這個遊戲建立 WINE 目錄,使用下列的方式:

WINEPREFIX=~/.ronwine WINEARCH="win32" wine wineboot

使用 winetricks 安裝 MFC 4.2 與 DirectMusic:

WINEPREFIX=~/.ronwine winetricks -q mfc42 directmusic

如果使用光碟安裝,原版需要 H87TM-6GFHQ-B3KGJ-KTFV3-64JT6 這樣的序號,資料片需要 KKJ2J-XG989-3968D-MK4KH-PD47Y 這樣的序號。 安裝後,需要在 rise2.ini(我的檔案位置是在 users 目錄裡,使用者名稱下的 AppData/Roaming/Microsoft Games/Rise of Nations/rise2.ini) 修改設定如下:

AllowAllResolutions=1
SkipIntroMovies=1
ForceGDICursor=1
ForceLowCPUBackgroundVid=1

分別是允許全部的 screen resolutions,略過開頭動畫,修正滑鼠指標以及讓開頭的選單背景正常。

原版最新的 patch 為 02.04.04.2903,資料片最新的 patch 為 03.02.12.0800。

最後,因為《王國的興起》採用 SafeDisc 2.7 保護,在 Windows 10 無法正確執行,最好尋找免光碟破解。 另外,如果在 WINE 中執行,原版的畫面是正常的,資料片的畫面則是有時候會出現問題(但是除了畫面,其它部份都可以正常執行, 無法確定是哪一方面的問題)。


《王國的興起》資源可以分為二種,Basic 與 Rare。 Basic Resources 有 6 種,其中 Food, Timber, MetalOil 由 Citizens 採集, Wealth 由 Caravans 採集,Knowledge 由 Scholars 採集。Rare Resources 則由 Merchants 採集。

下面是原版的國家:

  • The Aztecs who have the Power of Sacrifice
  • The Bantu who have the Power of Migration
  • The British who have the Power of Empire
  • The Chinese who have the Power of Culture
  • The Egyptians who have the Power of the Nile
  • The French who have the Power of Leadership
  • The Germans who have the Power of Industry
  • The Greeks who have the Power of Philosophy
  • The Inca who have the Power of Gold
  • The Japanese who have the Power of Honour
  • The Koreans who have the Power of Tradition
  • The Maya who have the Power of Architecture
  • The Mongols who have the Power of the Horde
  • The Nubians who have the Power of Trade
  • The Romans who have the Power of Caesar
  • The Russians who have the Power of the Motherland
  • The Spanish who have the Power of Discovery
  • The Turks who have the Power of Siege

下面是資料片新增的國家:

  • The Americans who have the Power of Innovation
  • The Dutch who have the Power of Commerce
  • The Indians who have the Power of Majesty
  • The Iroquois who have the Power of Nation
  • The Lakota who have the Power of the Plains
  • The Persians who have the Power of Ceremony

Lakota 是一個特別的國家,人口增加的不是建立 Farms, 而是 +4 Food Food for every Citizen, Scout, and Cavalry unit (except when garrisoned) 。

遊戲中總共分為 8 個時代:Ancient Age, Classical Age, Medieval Age, Gunpowder Age, Enlightenment Age, Industrial Age, Modern Age 與 Information Age。
研發主要是在 Library 中研發,可以分為下列 5 項: Advancing through ages, Military technologies, Civic technologies, Commerce technologies 與 Science technologies。

異塵餘生

《異塵餘生》(Fallout: A Post Nuclear Role Playing Game)是款由 Interplay 製作公司開發,並於 1997 年發行的角色扮演遊戲。 遊戲背景設定於 22 世紀中期的後末日和復古未來世界,席捲全球的核戰爭摧毀了現代文明,戰後不少人在地表掙扎求存, 也有部分幸運兒在戰時躲進了地下放射性落塵避難所。選擇或自行創建角色後(玩家可以從三個既有角色中選擇一個開局, 或者按照自己的喜好來建立角色和分配屬性),玩家操縱通稱「避難所居民」的主角離開生活已久的避難所,踏入廢土, 與其他倖存者互動,以完成數項重要任務。遊戲採用回合制戰鬥,使用行動點數系統,每個回合玩家可以執行多項動作,直至花光行動點數。

如果是 DOS 版,在完全安裝以後,修改 FALLOUT.CFG 的路徑,將使用光碟的目錄指向安裝的目錄,就可以免光碟。 如果需要自行安裝 patch,DOS 版最後一版 patch 為 v1.1。

可以參考的資料:

下面是來自 SAVE.DAT File Format Player and inventory的資料:

Offset Size (bytes) Description
0x00 0x04 0x0,0x0,'FP' [0x00004650] - these characters are always here. Also, they appear only once in the file. They're followed by a list of the player's characteristics.
0x04 0x04 Player's coordinates on the map.
0x08 0x04 Unknown
0x0C 0x04 Unknown
0x10 0x04 Unknown
0x14 0x04 Unknown
0x18 0x04 Unknown
0x1C 0x04 Player's facing: 0 - northeast 1 - east 2 - southeast 3 - southwest 4 - west 5 - northwest
0x20 0x04 Player FID number (appearance). Changes depending on what armor is worn. [0100000B] is the jumpsuit. Note that the engine will always change this value back to what you are wearing, so it's pointless to edit it here.
0x24 0x04 Unknown, usually 0x60002420. The last byte has some interesting properties. Setting the 0x10 bit puts the player in a permanent, always-successful sneak mode. Setting the 0x08 bit will draw the player under other critters and scenery. Setting the last byte to 00 will turn off the player light source.
0x28 0x04 Which level of the map the player is on.
0x2C 0x04 Unknown
0x30 0x18 Unknown - Light distance and intensity? Some of it have to to with lighting up the player.
0x48 0x04 Number of items in inventory.
0x4C 0x18 Unknown.
0x64 0x04 Bit field. Each bit indicates a crippled body part: 0x0001 - eyes 0x0002 - right arm 0x0004 - left arm 0x0008 - right leg 0x0010 - left leg 0x0080 - dead
0x68 0xC Unknown
0x74 0x04 Current hitpoints.
0x78 0x04 Radiation level.
0x7C 0x04 Poison level.
0x80 variable A list of items in inventory.

2025/01/12

三國志英傑傳

《三國志英傑傳》(三國志英傑伝)是日本 KOEI 光榮公司 1995 年出品、由第三波代理發行的策略角色扮演遊戲(MS-DOS 版)。 玩者主要扮演劉備,由群雄討伐董卓開始,直到擊敗魏國,復興漢室。除了第四章外,其他大致上照三國演義進行。

可以參考的資料:

修改:
找檔案 MSAVE*.R3S,每位武將佔 18 Byte,第一位為劉備,需要比對檔案變化以後修改。

    1.不明 - 5 byte,最後一個固定為64h
    2.兵力 - 2 byte
    3.兵種 - 1 byte,詳如後述
    4.等級 - 1 byte
    5.經驗 - 1 byte
    6.道具 - 8 byte,每個道具佔1 byte,詳如後述

兵種列表:

    00 短兵         01 長兵         02 戰車         03 弓兵
    04 連弩兵       05 發石車       06 輕騎兵       07 重騎兵
    08 近衛隊       09 山賊         0A 惡賊         0B 義賊
    0C 軍樂隊       0D 猛獸軍團     0E 武術家隊     0F 妖術師
    10 異民族       11 民眾         12 運輸隊

道具列表(FF表無物品):

    00 遁甲天書     01 青囊書       02 鼓吹具       03 孫子兵法
    04 孟德新書     05 黃爪飛龍     06 的盧         07 赤兔馬
    08 玉璽         09 倚天劍       0A 蛇矛         0B 七星劍
    0C 青龍偃月刀   0D 三尖刀       0E 方天畫戟     0F 蛇矛
    10 弓術指南書   11 馬術指南書   12 劍術指南書   13 長槍
    14 步兵車       15 連弩         16 發石車       17 馬鎧
    18 近衛鎧       19 無賴精神     1A 俠義精神     1B 酒
    1C 特級酒       1D 老酒         1E 豆           1F 麥
    20 米           21 炸藥         22 落石書       23 山崩書
    24 山洪書       25 漩渦書       26 濁流書       27 海嘯書
    28 焦熱書       29 火龍書       2A 猛火書       2B 濃霧書
    2C 雷陣雨書     2D 豪雨書       2E 援隊書       2F 援部書
    30 援軍書       31 平氣書       32 活氣書       33 勇氣書
    34 傷藥         35 中藥         36 茶           37 赦命書
    38 援軍報告     39 雌雄雙劍     3A 英雄之劍     3B 霸王之劍
    3C 六韜         3D 三略         3E 吳子兵法

2025/01/11

魔域傳說4: 波斯戰記

First Queen 是日本吳氏工房開發的一個即時戰略遊戲系列,目前共開發了 6 個作品(包括JAVA版),曾在多個平台上發行。 日本吳氏工房為日本的小型遊戲公司,社長為吳英二先生, 以開創敵我雙方在大地圖上即時戰鬥的小人混戰模式(ゴチャキャラシステム)而聞名。

《魔域傳說4:波斯戰記》(First Queen IV) 是日本吳氏工房製作,華義國際中文化以後在 1995 年出品的策略角色扮演遊戲, 為 DOS 平台的遊戲軟體。 雖然在一些小地方中文化的翻譯有些問題,但是因為遊戲內容相當充實,所以仍然在台灣十分暢銷。 劇情描寫波斯王塞內爾受魔法師宙的影響,開始對鄰國進攻,於是卡利恩國王艾雷斯奮起抵抗,終於將之消滅的故事。 遊戲主要採用組織軍隊攻城略地的方式進行(大地圖回合制),戰鬥則使用即時方式戰鬥。 每個隊員均可升級,亦有武器、法術與道具可使用與買賣,為綜合回合策略、即時戰鬥、角色扮演的遊戲。

可以參考的資料:

2024/12/20

戰神:狂神天威3

《戰神:狂神天威3》(Warlords Battlecry III,也有翻譯為《呼嘯戰神3》)是由 Infinite Interactive 開發並於 2004 年發行的即時戰略遊戲, 共有16 個種族,28 種職業,為《戰神:狂神天威》系列的第三部作品。《戰神:狂神天威》系列以首創將角色扮演要素融入即時戰略而聞名, 導入了英雄和昇級系統,藉由戰鬥提升經驗值,學習魔法和技能,特點在於英雄的等級與技能會在戰役後持續保留, 並且有隨從 (Retinue) 的設計。GOG 有販售此遊戲, 已更新到 patch 1.03。

可以參考的資料:

在單人遊戲方面,可以分為 Campaign(在 Etheria 世界的劇情故事) 以及對抗電腦對手的 Skirmish。
在成功的達成結局之後,玩家仍然可以在 Campaign 的地圖繼續遊玩與執行任務,同時在這個界面整理自己的裝備。 不管是什麼理由,如果想重玩,可以使用遊戲提供的 Reset Campaign 來達到這個目的。

遊戲中使用下列四種資源,每個種族各有其偏重使用的資源:
Gold, Metal, Stone 和 Crystal

和一般遊戲不同,玩家需要使用英雄或者是具有轉化 (Convert) 能力的單位轉化資源為己方的資源,而後才開始有收入。

魔法有以下的法術類別 (Time Magic 為 unofficial patch 引入,故不在此列入):

  • Alchemy - A sphere of magic specialised in creating Golems and Items.
  • Arcane Magic - A sphere of magic that improves other magics or the hero himself.
  • Chaos Magic - A mystic magic that summons the fickle powers of chaos. This power manipulates the stats of others.
  • Divination Magic - A sphere of magic focusing on the experience of the hero's followers.
  • Healing Magic - A sphere of magic specialised in healing allies and destroying Evil creatures.
  • Ice Magic - A sphere of magic which summons the power of ice to bend into a force of whatever the hero deigns to use it for.
  • Illusion Magic - A sphere of magic specialised in creating distractions for Enemies.
  • Nature Magic - A sphere of magic specialised in summoning beasts and controlling nature.
  • Necromancy - A sphere of magic specialised in summoning undead creatures.
  • Poison Magic - A sphere of magic specialised in inflicting Poison and Disease on enemy units.
  • Pyromancy - A sphere of magic mostly specialised in Offense.
  • Rune Magic - A sphere of magic that controls the earth and structures upon it.
  • Summoning Magic - A sphere of magic specialised in controlling and summoning Demons and other outworldlers.

可玩的種族有 16 種:

  • Dwarf
  • Empire
  • High Elf
  • Knight
  • Barbarian
  • Fey
  • Minotaur
  • Ssrathi
  • Wood Elf
  • Daemon
  • Dark Elf
  • Dark Dwarf
  • Orc
  • Plaguelord
  • The Swarm
  • Undead

《戰神:狂神天威》系列採用 5 級科技樹,主堡最高為第 5 級。

三代故事建立在 Dark Elf 嘗試召喚 Daemon Lord,而因為如此有 Four Horsemen 進入 Etheria 世界。 其中代表戰爭的 Lord Sartek 創造了 Minotaur,代表饑荒的 Lord Melkor 創造了 The Swarm, 代表瘟疫的 Lord Antharg 創造了 Plaguelord,代表死亡的 Lord Bane 創造了 Undead。 其中 Minotaur 為 Neutral alignment,其餘三者為 Evil alignment。 劇情故事就是主角走遍 Etheria 世界,最後封印 Fifth Horseman 的故事。

二代的 Human 在三代分裂為二個陣營,EmpireKnight

Empire 具有二代中原有的對騎兵有攻擊加成的步兵 Pikeman,三種法師 (White Mage, Red Mage, Black Mage, 其中 White Mage 擁有 heal 能力) 並且新增加了騎兵兵種 Elephant。Empire 有個要注意的點,如果要生產騎兵單位 Mercenary, 最好先在三級主堡才能夠建造的 Archway 研發 Fame 降低其生產成本以後再生產。 如果試著以 Mercenary 作為主力,那麼有 Wealth 技能的 Merchant 是最好的選擇; 其次的選擇是 Bard。如果想試著使用法師類的英雄,可以考慮 Sage(但是注意 Empire 沒有 mana regeneration 研發的支援)。

Knight 則是繼承了二代的騎兵體系(Knight, Knight Champion, Knight Lord), 加上新的基本步兵 Swordsman、可對空對地的單位 Dancing Sword, 價格偏貴但是有 Cure 技能的飛行單位 Archon 與新的法師 Inquisitor。 因為 Knight 是以 Gold 為中心的經濟,所以英雄技能一樣有 Divination Magic 同時又有 Wealth 技能的 Bard 是不錯的選擇。 如果想要偏向戰士類的,可以考慮 Warrior(因為與 Knight 種族技能相合), 以及 Paladin(因為其 Healing Magic 與 Knight Protector 技能)。 如果是法師,可以考慮 Priest 或者是 Healer, 另外因為種族英雄的法術為 Divination,也可以考慮 Sage(但是注意 Knight 沒有 mana regeneration 研發的支援)。

Dwarf 在初期需要建設其經濟(因為其價格較貴的單位,而升級與單位生產大多數都需要 Gold), 同時其大多數的單位移動速度較慢,在一開始的時候通常需要採取守勢。 Dwarf 主堡 Citadel 並不生產工人,而是由 Foundry 生產 Smith。Smith 如果進入礦產挖礦,會被計算為放入 2 個工人。 Dwarf 除了 Tower,還有主堡升到第三級以後可以建造對地的炮塔 Mortar。 還有要注意在步兵、弓箭手、騎兵、攻城武器、法師以及飛行單位中,Dwarf 沒有騎兵單位, 同時弓箭手 Dwarf Crossbow 的價格偏貴。雖然缺乏 mana regeneration 研發的支援, 不過因為 Rune Magic 是 Dwarf 英雄的技能,所以可以嘗試 Runemaster 這個職業。 另外因為 Dwarf 升級時使用較多的 Gold 與 Stone,所以可以嘗試使用有 Wealth 技能的英雄職業。

High Elf, Wood ElfDark Elf 分別是代表 Elf 中 Good alignment, Neutral alignment 與 Evil alignment 的種族,都是擁有優秀弓箭手與法師的種族,同時都需要在主堡研發相關 Rune 的科技才能夠生產相關的兵種。 三個種族的工人 Wisp 無法進入礦產挖礦加快資源的收入, 而是需要在二級主堡研發 Ancient Wisp,而後 4 個 Wisp 合成一個 Ancient Wisp 增加 Crystal 的收入, 也因此 Elf 三個種族都需要在資源管理上耗費心力。要注意 Wood Elf 與 Dark Elf 沒有攻城武器單位。

High ElfWood ElfHealing 科技可以提升 health regeneration rate。 High Elf Unicorn 作為騎兵單位具有 heal 能力。 因為 High Elf 種族英雄技能已經提供了兵種加強(lv10 Life Rune, lv30 Arcane Rune),再加上 Healing Magic 法術, 而又有提升 health regeneration rate 的相關研發以及 Unicorn 提供醫療,所以可以嘗試戰士類的英雄職業,例如 Warrior。

Wood Elf 是一個初期弱勢的種族,但是有一些不錯的單位,如果覺得可以, 英雄隨從中帶一個 Ancient Wisp 是一個不錯的主意。 Wood Elf 有個優點是在第四級主堡的時候可以建造 Magic Well 增加 Gold 收入。 以英雄選擇來說,同樣有 Nature Magic 技能的 Ranger 或者是 Druid 可以考慮 (但是注意 Wood Elf 有 health regeneration rate 的研發項目,沒有 mana regeneration 研發的支援)。

Dark Elf 可以在 Reformatory 召喚 Thrall 並且讓他們進入資源挖礦, 以及 Sorceror 可以召喚 Zombie 並且讓他們進入資源挖礦。 Sorceror 還具有強大的攻擊法術(Pillar of Fire, Darkstorm),是很優秀的法師單位。 適合 Dark Elf 的英雄為 Assassin,技能的組合是最搭配的。因為Dark Elf 種族英雄技能中有 Summoning Magic, 也可以考慮 Summoner。如果想嘗試不同的英雄,可以考慮有多種法術的 Archmage(需要高等級才能發揮潛力的英雄,很難用好的進階英雄)。

Fey 是二代新增的種族,擁有數目頗多的飛行單位,Unicorn 作為騎兵單位具有 heal 能力,Leprechaun 可以用來增加 Gold 的收入, 不過 Fey 缺少攻城武器單位。Fey 的 Crystal Tower 有個特別的地方是如果殺死敵人的單位會得到 85 Crystal。 Fey 在一開始的時候單位較為弱小,是需要資源升級單位並且度過初期弱勢的種族。 一般而言,英雄應該選擇 Merchant 來取得生產折扣以及更多的資源,因為高等級的 Merchant 有 Gemcutting 技能; 還可以的選擇是也有 Gemcutting 技能的 Ice Mage; 或者選擇能夠幫助 Fey 有更多機會度過初期弱勢情況的英雄。 雖然 Fey 的種族英雄技能中有 Illusion Magic,但是 Illusionist 能夠提供的幫助不如 Merchant。

Ssrathi 為三代新增的種族。主堡並不生產工人,而是建造 Worker Sect 後才在 Worker Sect 生產 Chameleon。 Chameleon 是高效率的工人。要注意的是,Ssrathi 一般單位通常都可以使用 Poison 或者相關的技能。 嚴格的說 Ssrathi 並沒有弓箭手,而是使用法師 Snakepriest 作為替代品, Snakepriest 在早期就可以生產並且投入戰場(並且有 Cauterize 法術可以補血), 最好在 Sacred Pool 研發 Power of Couatl(總共有 3 級)加強 Snakepriest, 可以攻擊距離 +2, +4 以及 +6。Lizard Rider 則是其移動速度快速的騎兵。 Triceratops 與 Tyrannosaurus Rex 是 dinosaurs,是有較高血量的單位。 Poison Magic 對於 Ssrathi 而言並沒有技能十分符合的英雄,而因為 Snakepriest 的關係,可以考慮選擇戰士類的英雄。 一個有趣的英雄選擇是 Dragonslayer,如果在 unofficial patch 會非常適合,因為 Dragon Master 被修改為其技能, 與 Ssrathi 種族英雄技能相符,但是在 1.03 也可以考慮使用。如果想要嘗試輔助類的英雄,可以考慮 Thief。 如果想要偏向法師類的,可以考慮 Pyromancer。

BarbarianMinotaur 二個種族能夠生產的種類較少,二個種族的工人 Thrall 還是整個遊戲中建造效率最差的工人。

Barbarian 缺少攻城武器以及法師,優點是經濟均衡,單位生產資源主要是使用 Metal (Barbarian, Rider) 和 Stone (War Dog), 生產速度不慢。有個有趣的點是,Barbarian Summon Mana 是在 Altar of Tempest 研發, 而 Altar of Tempest 還可以生產 Lightning Hawk,雖然只能對地,卻是 Barbarian 的單位中少數具有不同攻擊類型的單位。 Chieftain 是為了加強 Barbarian 的優點而出現的英雄(Barbarian King 技能用來加強 Barbarian, Rider 與 Warlord), 但是無法解決 Barbarian 缺少法師的問題。 在 unofficial patch 因為覺得 Chieftain 這樣太強而將 Barbarian King 改為 Riding,也就是只加強騎兵, 我認為是錯誤的修改方向,這樣只是讓不強的 Barbarian 變得更弱(不過增強了 Chieftain 的泛用性)。其它的英雄選擇是啟用法師類的英雄, 因為 Barbarian 有 mana regeneration 研發的支援,所以使用英雄作為法術輸出以及補強弱點的部份。 雖然 Barbarian 的種族英雄技能中有 Ice Magic,但是 Ice Magic 大多數為攻擊法術的法術系列, Ice Mage 並不完全適合 Barbarian(可以用但是感覺不夠好)。如果考慮 Barbarian 沒有醫療的方式,可以考慮 Healer。

Minotaur 缺少騎兵單位,單位強壯可靠但是造價較為昂貴, 不過 Minotaur 可以生產 Sheep 以及食用動物讓 Minotaur 英雄以及單位 (Minotaur, Axe Thrower, Minotaur Shaman, Minotaur King)自我醫療。 Minotaur 可以考慮選擇戰士類的英雄,或者因為 Minotaur 的種族技能為 Pyromancy 法術又有 mana regeneration 研發的支援, 可以考慮 Pyromancer 這個職業。或者想要嘗試團隊型的法師英雄,那麼可以嘗試 Illusionist。 另外可以嘗試的英雄職業為 Elementalist,這是 Barbarian 和 Minotaur 這二個種族可以嘗試的英雄, 因為 Minotaur 的種族技能為 Pyromancy 法術,Barbarian 的種族英雄技能中有 Ice Magic, 雖然 Elementalist 要到高等級才有比較好的表現,不過想要挑戰的可以嘗試。 另外,如果你真的受不了 Thrall,Barbarian 和 Minotaur 這二個種族還可以考慮嘗試 Ranger, 除了有 Taming 技能加強 monsters(Barbarian 加強 War Dog,Minotaur 加強 Basilisk), 而 Griffonmaster 也適合 Minotaur,還可以使用 Nature Magic 的 Summon Treant 嘗試使用其它的 builder。

Orc 有不錯的戰鬥單位組合,非飛行單位都有免疫疾病的優勢,生產速度不慢。 Orc 在研發 Shaman research 之後可以建造對空的 Totem,但是注意 Orc 所有的建築都有一個嚴重的缺陷,那就是無法花錢修理 (Repair) , 只能使用 Earthpower 法術回復!因為 orc 已經有良好的戰鬥單位組合,所以可以考慮以輔助為主的英雄, 在戰鬥輔助方面可以考慮 Thief,在加強建築以及增加資源方面可以考慮 Tinker。如果想要改善建築修復的問題, 可以考慮 Runemaster。也可以考慮使用 Shaman 來輔助戰鬥,因為 Chaos Magic 是 Orc 的種族英雄技能 (但是注意 Orc 沒有 mana regeneration 研發的支援)。

Barbarian, Minotaur, Orc 這三個種族都有掠奪敵人資源的方式。 Barbarian 如果摧毀敵人的建築可以取得 100 Gold; Minotaur 如果摧毀敵人的建築可以取得 100 Metal,Basilisk 每殺死一個敵人就可以拿到 50 Stone, Gnoll 如果 Assassination 技能暗殺敵人成功可以拿到 100 Gold(在 1.03 patch 的數值); Orc 如果摧毀敵人的建築可以取得 100 Stone。

Dark Dwarf 是二代新增的種族,其大多數單位移動速度稍慢,在兵種上 Dark Dwarf 缺少騎兵和法師單位, 使用多種 Golem,例如 Stone Golem, Iron Golem 以及 Bronze Golem; 以及擁有不錯的攻城武器。Bronze Golem 除了轉化 (Convert),還有一項能力是 scavenge building rubble for resources, 施展後可以從敵人被摧毀的建築取得資源。Dark Dwarf 主堡 Furnace 並不生產工人,而是由 Guild 生產 Engineer。 Engineer 是高效率的工人,經過研發升級後可以使用 Earthpower 法術,同時 Engineer 如果進入礦產挖礦,會被計算為放入 2 個工人。 Dark Dwarf 除了 Tower,還有主堡升到第三級以後可以建造對地的炮塔 Mortar。 在考慮英雄技能以後,有 Engineer 技能以及 Alchemy 法術的 Tinker 是個不錯的選擇。 如果想要試著使用法師類的英雄,可以考慮 Alchemist。因為種族英雄的法術為 Chaos Magic, 也可以考慮使用 Shaman 施法試著加速單位的移動速度(但是注意 Dark Dwarf 沒有 mana regeneration 研發的支援)。

Daemon 是二代新增的種族,其英雄擁有 Ferocity 以及可以學習 Regeneration 技能和 Pyromancy 法術技能, 在英雄的個人技能上頗為優秀。在建築方面,除了防禦塔 Summoning Tower,也有替代的 Lightning Spire。 在設定上 Daemon 是被 Summoning 法術召喚而來的,而 Daemon 也確實是十分適合 Summoning 法術的種族, 因此 Summoner 是適合 Daemon 的英雄。雖然有點惡趣味,但是如果要嘗試使用偏向戰士的英雄職業, 可以考慮 Daemonslayer。

Plaguelord 為三代新增的種族,大多數的單位具有免疫 Disease 的能力。 Plaguelord 的主堡並不生產工人,需要建立 Cess Pool 後由 Cess Pool 生產工人 Zombie, Cess Pool 還可以生產基本步兵 Ghoul 以及有一定機率會散播 Disease 的偵查步兵 Slime, 而 Ghoul 與 Slime 的科技研發則在 Laboratory。 要注意 Plaguelord 是個需要良好資源管理的種族(因為主堡升級、技能升級和生產可能會有資源衝突)。 Plaguelord 有個很微妙的點,就是 Hydra Cave 可以研發科技升級為 Fire Cave 或者是 Ice Cave, 但是升級以後就無法生產 Hydra,只能生產升級以後的 Pyrohydra 或者是Cryohydra! 還有要注意的是,Plaguelord 沒有騎兵單位。 以英雄選擇來說,Defiler 有二個技能是用來加強 Plaguelord 的兵種(lv5 Slimemaster 與 lv15 All-Seeing Eye), 所以是還可以的選擇,但是 Ranger 的 Taming 技能卻有更廣泛的加強效果。考慮種族英雄有 Summoning 法術, 也可以考慮 Daemonslayer。

The Swarm 為三代新增的種族,是以大量生產為主的種族。 主堡 Dunekeep 並不生產工人,需要建立 Hive 後由 Hive 生產工人 Giant Ant, 而 Hive 升級之後則可以生產更多種類的單位(注意,是每一個 Hive 都需要升級,這是 The Swarm 的潛在弱點)。 Scarab 是 The Swarm 主要(也是惟一的)弓箭手,如果要生產 Scarab 那麼 Hive 至少要升到第二級。 Watcher 則是 The Swarm 可以對空對地的防禦塔替代品。 Dunekeep 在研發 Famine 技能之後可以偷取資源。在 Egg Chamber 研發 Incubation 則可以加快建造建築的速度。 以英雄選擇來說,因為 unofficial patch 修改了種族英雄法術技能,所以如果要符合大多數的版本,那麼是 Warrior; 如果是 1.03,可以考慮 Deathknight,因為 Necromancy 是其英雄的法術技能之一。 如果想嘗試法師類的英雄,可以考慮 Lichelord。

Undead 是一個需要良好操作與資源管理的種族。主堡並不生產工人,而是建造 Graveyard 後由 Graveyard 生產 Zombie。 Undead 生產方式在各種種族中是比較特別的,有一些單位並不是直接從相關建築生產, 而是從 Skeleton、Wight 或者是 Wraith 升級而來(Skeleton 可以從 Graveyard 或者是 Gravestone 生產, 再來花費資源成為 Wight 或者是 Wraith)。Skeleton Cavalry 則是 Undead 的騎兵單位。 Necromancy 是其英雄的法術技能之一,是十分適合該種族的法術,所以 Necromancer 是適合 Undead 使用的英雄。 如果想嘗試戰士類的英雄,可以考慮 Deathknight。

每個種族都有設計其 general,在第五級主堡的時候可以生產,為英雄之外有轉化 (Convert) 能力的單位, 包含 Dwarf Lord (Dwarf), White Mage, Red Mage, Black Mage (Empire), Moonguard (High Elf), Inquisitor (Knight), Reaver (Barbarian), Banshee (Fey), Minotaur King (Minotaur), Naga (Ssrathi), Dryad (Wood Elf), Summoner (Daemon), Blackguard (Dark Elf), Bronze Golem (Dark Dwarf), Giant (Orc), Plague Priest (Plaguelord), Scorpionpriestc (The Swarm), Vampire (Undead)。

一些種族有 Income 可以研發, 包含 Barbarian, Dark Dwarf, Dwarf, Empire, Fey, High Elf, Knight, 研發後可以自礦產增加收入 (第一級 +1,第二級 +2,第三級 +4,第四級 +6); 其中 Dark Dwarf 和 Empire 可研發到第二級,Barbarian, Dwarf, High Elf, Kight 可研發到第三級, Fey 可研發到第四級。另外,Daemon 的 Hard Labor 也具有一樣的效果, 研發後可以自礦產增加收入 (第一級 +1,第二級 +2,第三級 +4)。

一些種族有 Trade 可以研發,包含 Barbarian, Dark Dwarf, Dwarf, Empire, High Elf, Knight, Wood Elf,功用是讓玩家可以交換資源(例如 Gold 交換 Metal),不過交換後只能換到 50% 的資源。 有二個法術系列的法術也有同樣的效果,一個是 Alchemy 的 Transmute,一個是 Chaos Magic 的 Morph Resources。

FletcherBowyer 為加強弓箭手的科技研發, 前者 +5 damage,後者 +2 range,包含 Dark Elf, Dwarf, Empire, High Elf, Knight, Wood Elf 這些種族有這個研發。

關於視野與地圖迷霧 (Fog of War) 有二個相關的研發,前者為 Eagle Eye,後者為 Farseeing。 可以研發 Eagle Eye 的種族包含 Barbarian, Fey, Minotaur, Orc, Ssrathi, The Swarm, Wood Elf, 效果為視野距離 +2, +3 與 +4。可以研發 Farseeing 的種族包含 Fey, Minotaur, Ssrathi, The Swarm, Wood Elf, 用來去除地圖迷霧。

研發 Summon Mana 可以提升 mana regeneration, 包含 Barbarian, Dark Elf, Daemon, Fey, Minotaur, Plaguelord, Ssrathi, The Swarm, Undead 這些種族, 但是 Daemon 只能研發第一級,Fey 只能研發到第二級。 這個研發對於 Barbarian 這個種族有趣的地方在於,只有英雄(以及英雄的隨從們)從 Summon Mana 獲益, 但是如果要讓 Barbarian 英雄可以更快的施展法術幫助團隊,這個研發是必要的。

每個種族的英雄都有其各自的技能,加上英雄職業專長的技能,就組成了一個英雄能夠學習的技能表。

英雄具有下列四種基本屬性:

  • Strength
    • +1 Combat per point of Strength
    • +1 Damage per point of Strength (at 1,3,5,etc…)
    • +5 Hit Points per point of Strength
    • +1 Life Regeneration (per 20 sec’s) for every 3 points of Strength
  • Dexterity
    • +1 Movement Speed per 2 points of Dexterity (at 2,4,6,etc…)
    • - ~0.016 seconds off attack speed per point of Dexterity (minimum 0.4)
    • +1 Resistance per point of Dexterity
    • +1 Armor per 2 points of Dexterity (at 2,4,6,etc…)
    • -1 Second to Conversion Time per point of Dexterity (minimum conversion time is 10 seconds)
  • Intelligence
    • +3 Mana Points per point of Intelligence
    • +1 Mana Regeneration (per 20 sec’s) for every 5 points of Intelligence
    • +1 Initial Troop XP per 2 points of Intelligence (at 2,4,6,etc…)
    • +3% Spellcasting Chance per point of Intelligence
  • Charisma
    • +1 Morale per 2 points of Charisma (at 2,4,6,etc…)
    • +1 Command Radius per 2 points of Charisma (at 1,3,5,etc...)
    • +1 Merchant Skill for every point over 5 (-1 Merchant skill for every point under 5) which gives ~0.86% discount per Merchant skill
    • +1 Army Setup Point for every 4 Points of Charisma

英雄有以下四種類型的英雄(Monk 為 unofficial patch 引入,故不在此列入):

  • 戰士: Assassin, Chieftain, Dragonslayer, Warrior
  • 法師: 單一系列的法術技能加上 Ritual 技能 - Alchemist, Defiler, Druid, Healer, Ice Mage, Illusionist, Necromancer, Priest, Pyromancer, Runemaster, Sage, Shaman, Summoner
    多種法術技能 - Archmage, Elementalist, Lichelord
  • 領導者: Bard, Merchant, Tinker
    Bard 有 Wealth 可以帶來 Gold 收入、Leadership 提升士氣 (Morale) 以及使用 Divination 法術輔助戰鬥;
    Tinker 的 Engineer 技能增加建築物生命值, Smelting 增加 Metal, Quarrying 增加 Stone,以及使用 Alchemy 法術;
    Merchant 擁有 Merchant 和 Trade 技能,Wealth 增加 Gold, Gemcutting 增加 Crystal
  • 混合類型(具有戰鬥或者戰鬥輔助功能,又有法術技能的類型):
    一開始就有 Ferocity 技能 - Daemonslayer, Deathknight, Paladin
    一開始就有 Running 技能 - Ranger, Thief

有些種族或者是英雄的技能是增加資源:

  • Gold: Wealth from Empire (race) or Assassin, Bard, Dragonslayer, Merchant (class)
  • Metal: Smelting from Daemonslayer, Tinker (class)
  • Stone: Quarrying from Barbarian (race) or Runemaster, Tinker (class)
  • Crystal: Gemcutting from Fey (race) or Ice Mage, Merchant (class)

(注意:在一些 unofficial patch 中,Dragonslayer 被移除了 Wealth 技能)

建立英雄時也需要從種族的優缺點出發,使用能夠加強己方的優點或者是彌補自己的缺點,或者是能夠補強經濟方面問題的英雄。

另外,還有終極單位 Titan 的設計,每個種族都有自己獨特的 Titan 單位,每場戰役後期只能夠生產一位。

2024/11/25

魔獸爭霸III

《魔獸爭霸III:混亂之治》(Warcraft III: Reign of Chaos)是一款即時戰略遊戲,屬於暴雪娛樂出品的《魔獸爭霸》系列第三代作品, 於 2002 年發行。2003 年 5 月暴雪公司又發行了《魔獸爭霸III:寒冰霸權》(Warcraft III: The Frozen Throne),它是本作的資料片。 在 2020 年發行的《魔獸爭霸III:淬鍊重生》(Warcraft III: Reforged)為 2002 年的《魔獸爭霸III》之重製版, 包括《混亂之治》與《寒冰霸權》的全部劇情。

玩家可以選擇在《魔獸爭霸III》中操控四個種族,分別是 Human,Orc, Night Elf 與 Undead。 Naga 在資料片製作時曾經設想作為第五個可操控的種族,但在遊戲測試時刪去。而官方解釋是:加上 Naga 之後很難保證遊戲的平衡性, 因為 Naga 的部隊可直接跨過水域。而今它則出現在戰役模式和中立生物當中。

遊戲也加入了一種可透過獲取經驗值升級並增強能力的戰鬥單位,是為英雄。其可分為本族英雄和中立英雄。 每當己方殺滅一個敵方單位或中立生物時,英雄便可獲取相當的經驗值而累積一定程度時其等級就會上升。等級每當上升時, 英雄便可通過添加技能點學習或加強一項技能,不同英雄可學習之技能亦有所異。除此以外,英雄們亦可以攜帶於商店購得或戰勝中立生物後獲取之物品, 而此等物品則可提高英雄或整體的作戰能力。遊戲過程中,一方最多可以有三個英雄出現,但需要將自己的主城升級,可將己方建築物解鎖進而可建築出來。 而倘若有英雄於戰鬥中陣亡,則可在祭壇中加以復活重生回到戰場上。

如上所述,中立生物可視為遊戲中創新之處。即便多人遊戲中,亦存有完全由電腦控制的中立生物,以守衛地圖中關鍵的位置及中立的建築物。 它也成為選手間爭奪的資源,擊殺中立生物後便可獲得相當的經驗值、金錢及物品。使這個類似於角色扮演遊戲的玩家更具「攻擊性」而不會過於防衛, 從而提高遊戲的娛樂性及可觀性。

而另一影響遊戲策略的操施就是維護費徵取,此操施源於一種概念——擁有越多戰鬥單位就須要付出越多的資源去滿足部隊的需要, 如士兵需要補給、武器需要打造、盔甲需要鍛煉等。該遊戲則以上稅實行此概念。當玩家部隊的數目到達一定程度時, 就須於每採集十塊黃金上繳其中三塊。當部隊數目抵達更高程度時,每十塊就須上繳六塊。

在發展的科技樹上可以分為三級(以 Orc 為例,就是 Great Hall 升到 Stronghold 升到 Fortress)。 《魔獸爭霸III》的資源為 GoldLumber,需要透過工人採集。 Human 透過 Peasant, Orc 透過 Peon, Night Elf 透過 Wisp, Undead 則較為特別,Acolyte 採集 Gold 而 Ghoul 採集 Lumber。 也因為如此,通常 Human 第一個建築是生產英雄的 Arcane Sanctum, Orc 第一個建築是 Altar of Storms, Night Elf 第一個建築是 Altar of Elders, 而 Undead 通常第一個建築是生產 Ghoul 的 Crypt,再來才是英雄的 Altar of Darkness。

Human 特別的地方在於可以多個工人一起加速建造建築,同時工人可以化身為民兵進行防守; Orc 則是工人可以躲在 Orc Burrow 中以及可以研發 Spiked Barricades 加強防守; Night Elf 則是有些建築是可以移動的,並且有 Moon Well 可以回復生命與魔力: 而 Undead 的建築則是除了 Haunted Goldmine 與 Necropolis,需要建立在腐土的上面, 以及 Acolyte 在建造建築時不用等建築完成就可以繼續做下一件事。

《魔獸爭霸III:寒冰霸權》各種族都增加了商店這個建築,提供了各個時期可能需要的物品。 Human 為 Arcane Vault,Orc 為 Voodoo Lounge, Night Elf 為 Ancient of Wonders, Undead 為 Tomb of Relics。

下面是《魔獸爭霸III》的英雄列表。

  • Human Alliance
    • Paladin
    • Archmage
    • Mountain King
    • Blood Mage
  • Orcish Horde
    • Blademaster
    • Far Seer
    • Tauren Chieftain
    • Shadow Hunter
  • Undead Scourge
    • Death Knight
    • Lich
    • Dread Lord
    • Crypt Lord
  • Night Elf Sentinels
    • Keeper of the Grove
    • Priestess of the Moon
    • Demon Hunter
    • Warden
  • Neutral
    • Naga Sea Witch
    • Dark Ranger
    • Pandaren Brewmaster
    • Beastmaster
    • Pit Lord
    • Tinker
    • Firelord
    • Alchemist

《魔獸爭霸III:混亂之治》與《魔獸爭霸III:寒冰霸權》自 1.21b 開始提供官方免光碟, 而 1.27b 則是遊戲最後一版不用線上更新的版本。

《魔獸爭霸III》在 1.27b 之後架構改變,不再提供線下更新的下載。同時也帶來了不少遊戲中科技樹的變化, 舉例來說,在 1.30.0 版 Orc 方面最大的變化是將 Spirit Walker 的生產改到 Tauren Totem, 也因此 Tauren Totem 的科技樹改變,改為第二級就可以建造。1.31.1 則是《魔獸爭霸III:寒冰霸權》的最後一版更新版, 之後的版本為《魔獸爭霸III:淬鍊重生》的更新。

另外,如果使用 Wine 玩《魔獸爭霸III》,1.27b 版的開頭動畫以及一些遊戲中的動畫是無法正確播放的, 而且找不到方式修正。還有就是如果使用 Wine,可以嘗試使用 OpenGL 模式 (加上 -opengl)。

2024/11/22

PugiXML

PugiXML 是一個 C++ XML parser 函式庫,支援 DOM-like interface 與 XPATH 1.0 標準。 PugiXML 在是否容易使用、執行速度以及支援功能中取得良好的平衡,其中一個特點就是容易與其它程式整合, 將 pugixml.cpp, pugixml.hpp 與 pugiconfig.hpp 複製到原始碼目錄下就可以開始使用了。

下面是 tree.xml

<?xml version="1.0"?>
<mesh name="mesh_root">
    <!-- here is a mesh node -->
    some text
    <![CDATA[someothertext]]>
    some more text
    <node attr1="value1" attr2="value2" />
    <node attr1="value2">
        <innernode/>
    </node>
</mesh>
<?include somedata?>

下面是載入 XML 檔案的程式:

#include "pugixml.hpp"
#include <iostream>

int main() {
    pugi::xml_document doc;

    pugi::xml_parse_result result = doc.load_file("tree.xml");

    std::cout << "Load result: " << result.description()
              << ", mesh name: " << doc.child("mesh").attribute("name").value()
              << std::endl;
}

下面的程式使用 libcurl 自網站下載 ATOM XML 的資料, 下載以後使用 PugiXML 分析並且將 title 與 link 的資料儲存為 html 格式。

#include "pugixml.hpp"
#include <cstdio>
#include <cstdlib>
#include <curl/curl.h>
#include <fstream>
#include <iostream>

int get_rss(const char *url, const char *outfile) {
    FILE *feedfile = fopen(outfile, "w");

    if (!feedfile)
        return -1;

    CURL *curl = curl_easy_init();
    if (!curl)
        return -1;

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, feedfile);

    CURLcode res = curl_easy_perform(curl);
    if (res)
        return -1;
    curl_easy_cleanup(curl);
    fclose(feedfile);
    return 0;
}

int main(int argc, char *argv[]) {
    char *url = NULL;
    char *filename = NULL;
    char *outfile = NULL;
    if (argc == 4) {
        url = argv[1];
        filename = argv[2];
        outfile = argv[3];
    } else {
        printf("Not valid arguments.\n");
    }

    get_rss(url, filename);

    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_file(filename);

    pugi::xpath_node_set title = doc.select_nodes("/feed/entry/title");
    pugi::xpath_node_set link =
        doc.select_nodes("/feed/entry/link[@rel='alternate']");

    std::ofstream ofile(outfile);

    pugi::xpath_node_set::const_iterator it1 = title.begin();
    pugi::xpath_node_set::const_iterator it2 = link.begin();
    while (it1 != title.end() && it2 != link.end()) {
        pugi::xpath_node node1 = *it1;
        pugi::xpath_node node2 = *it2;
        ofile << "<a href=\"" << node2.node().attribute("href").value() << "\">"
              << node1.node().text().get() << "</a><br>" << std::endl;

        it1++;
        it2++;
    }
    ofile.close();
}

參考連結

2024/11/21

GNU Libmicrohttpd

GNU Libmicrohttpd 是一個函式庫,授權為 GNU LGPL v2.1 (使用者也可以選擇 LGPL v2.1 之後的版本), 最主要的功能是內嵌 HTTP server 到應用程式內,有多種 threading mode 可以選擇, 支援 HTTP/1.1 與 IPv6,並且透過 GnuTLS 支援 SSL/TLS 協定。 因此,當應用程式需要內嵌 web server 作為簡單的 web 介面時,可以考慮使用 GNU Libmicrohttpd。

在 openSUSE Tumbleweed 安裝相關的開發檔案:

sudo zypper in libmicrohttpd-devel

下面是首頁上的範例:

#include <microhttpd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PAGE                                                                   \
    "<html><head><title>libmicrohttpd demo</title>"                            \
    "</head><body>libmicrohttpd demo</body></html>"

static enum MHD_Result ahc_echo(void *cls, struct MHD_Connection *connection,
                                const char *url, const char *method,
                                const char *version, const char *upload_data,
                                size_t *upload_data_size, void **ptr) {
    static int dummy;
    const char *page = cls;
    struct MHD_Response *response;
    int ret;

    if (0 != strcmp(method, "GET"))
        return MHD_NO; /* unexpected method */
    if (&dummy != *ptr) {
        /* The first time only the headers are valid,
           do not respond in the first round... */
        *ptr = &dummy;
        return MHD_YES;
    }

    if (0 != *upload_data_size)
        return MHD_NO; /* upload data in a GET!? */
        
    *ptr = NULL;       /* clear context pointer */
    response = MHD_create_response_from_buffer(strlen(page), (void *)page,
                                               MHD_RESPMEM_PERSISTENT);
    ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
    MHD_destroy_response(response);

    return ret;
}

int main(int argc, char **argv) {
    struct MHD_Daemon *d;

    if (argc != 2) {
        printf("%s PORT\n", argv[0]);
        return 1;
    }

    d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, atoi(argv[1]), NULL,
                         NULL, &ahc_echo, PAGE, MHD_OPTION_END);
    if (d == NULL)
        return 1;

    (void)getc(stdin);
    MHD_stop_daemon(d);
    return 0;
}

下面是加入 SSL/TLS 以及靜態檔案的支援:

#include <microhttpd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>

#define BUF_SIZE 1024
#define MAX_URL_LEN 255

#define EMPTY_PAGE                                                             \
    "<html><head><title>File not found</title></head><body>File not "          \
    "found</body></html>"

/* test server key */
static const char key_pem[] =
  "-----BEGIN PRIVATE KEY-----\n\
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCff7amw9zNSE+h\n\
rOMhBrzbbsJluUP3gmd8nOKY5MUimoPkxmAXfp2L0il+MPZT/ZEmo11q0k6J2jfG\n\
UBQ+oZW9ahNZ9gCDjbYlBblo/mqTai+LdeLO3qk53d0zrZKXvCO6sA3uKpG2WR+g\n\
+sNKxfYpIHCpanqBU6O+degIV/+WKy3nQ2Fwp7K5HUNj1u0pg0QQ18yf68LTnKFU\n\
HFjZmmaaopWki5wKSBieHivzQy6w+04HSTogHHRK/y/UcoJNSG7xnHmoPPo1vLT8\n\
CMRIYnSSgU3wJ43XBJ80WxrC2dcoZjV2XZz+XdQwCD4ZrC1ihykcAmiQA+sauNm7\n\
dztOMkGzAgMBAAECggEAIbKDzlvXDG/YkxnJqrKXt+yAmak4mNQuNP+YSCEdHSBz\n\
+SOILa6MbnvqVETX5grOXdFp7SWdfjZiTj2g6VKOJkSA7iKxHRoVf2DkOTB3J8np\n\
XZd8YaRdMGKVV1O2guQ20Dxd1RGdU18k9YfFNsj4Jtw5sTFTzHr1P0n9ybV9xCXp\n\
znSxVfRg8U6TcMHoRDJR9EMKQMO4W3OQEmreEPoGt2/+kMuiHjclxLtbwDxKXTLP\n\
pD0gdg3ibvlufk/ccKl/yAglDmd0dfW22oS7NgvRKUve7tzDxY1Q6O5v8BCnLFSW\n\
D+z4hS1PzooYRXRkM0xYudvPkryPyu+1kEpw3fNsoQKBgQDRfXJo82XQvlX8WPdZ\n\
Ts3PfBKKMVu3Wf8J3SYpuvYT816qR3ot6e4Ivv5ZCQkdDwzzBKe2jAv6JddMJIhx\n\
pkGHc0KKOodd9HoBewOd8Td++hapJAGaGblhL5beIidLKjXDjLqtgoHRGlv5Cojo\n\
zHa7Viel1eOPPcBumhp83oJ+mQKBgQDC6PmdETZdrW3QPm7ZXxRzF1vvpC55wmPg\n\
pRfTRM059jzRzAk0QiBgVp3yk2a6Ob3mB2MLfQVDgzGf37h2oO07s5nspSFZTFnM\n\
KgSjFy0xVOAVDLe+0VpbmLp1YUTYvdCNowaoTE7++5rpePUDu3BjAifx07/yaSB+\n\
W+YPOfOuKwKBgQCGK6g5G5qcJSuBIaHZ6yTZvIdLRu2M8vDral5k3793a6m3uWvB\n\
OFAh/eF9ONJDcD5E7zhTLEMHhXDs7YEN+QODMwjs6yuDu27gv97DK5j1lEsrLUpx\n\
XgRjAE3KG2m7NF+WzO1K74khWZaKXHrvTvTEaxudlO3X8h7rN3u7ee9uEQKBgQC2\n\
wI1zeTUZhsiFTlTPWfgppchdHPs6zUqq0wFQ5Zzr8Pa72+zxY+NJkU2NqinTCNsG\n\
ePykQ/gQgk2gUrt595AYv2De40IuoYk9BlTMuql0LNniwsbykwd/BOgnsSlFdEy8\n\
0RQn70zOhgmNSg2qDzDklJvxghLi7zE5aV9//V1/ewKBgFRHHZN1a8q/v8AAOeoB\n\
ROuXfgDDpxNNUKbzLL5MO5odgZGi61PBZlxffrSOqyZoJkzawXycNtoBP47tcVzT\n\
QPq5ZOB3kjHTcN7dRLmPWjji9h4O3eHCX67XaPVMSWiMuNtOZIg2an06+jxGFhLE\n\
qdJNJ1DkyUc9dN2cliX4R+rG\n\
-----END PRIVATE KEY-----";

/* test server CA signed certificates */
static const char cert_pem[] =
  "-----BEGIN CERTIFICATE-----\n\
MIIFSzCCAzOgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBgTELMAkGA1UEBhMCUlUx\n\
DzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MRswGQYDVQQKDBJ0ZXN0\n\
LWxpYm1pY3JvaHR0cGQxITAfBgkqhkiG9w0BCQEWEm5vYm9keUBleGFtcGxlLm9y\n\
ZzEQMA4GA1UEAwwHdGVzdC1DQTAgFw0yMjA0MjAxODQzMDJaGA8yMTIyMDMyNjE4\n\
NDMwMlowZTELMAkGA1UEBhMCUlUxDzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwG\n\
TW9zY293MRswGQYDVQQKDBJ0ZXN0LWxpYm1pY3JvaHR0cGQxFzAVBgNVBAMMDnRl\n\
c3QtbWhkc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn3+2\n\
psPczUhPoazjIQa8227CZblD94JnfJzimOTFIpqD5MZgF36di9IpfjD2U/2RJqNd\n\
atJOido3xlAUPqGVvWoTWfYAg422JQW5aP5qk2ovi3Xizt6pOd3dM62Sl7wjurAN\n\
7iqRtlkfoPrDSsX2KSBwqWp6gVOjvnXoCFf/list50NhcKeyuR1DY9btKYNEENfM\n\
n+vC05yhVBxY2ZpmmqKVpIucCkgYnh4r80MusPtOB0k6IBx0Sv8v1HKCTUhu8Zx5\n\
qDz6Nby0/AjESGJ0koFN8CeN1wSfNFsawtnXKGY1dl2c/l3UMAg+GawtYocpHAJo\n\
kAPrGrjZu3c7TjJBswIDAQABo4HmMIHjMAsGA1UdDwQEAwIFoDAMBgNVHRMBAf8E\n\
AjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMDEGA1UdEQQqMCiCDnRlc3QtbWhk\n\
c2VydmVyhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMB0GA1UdDgQWBBQ57Z06WJae\n\
8fJIHId4QGx/HsRgDDAoBglghkgBhvhCAQ0EGxYZVGVzdCBsaWJtaWNyb2h0dHBk\n\
IHNlcnZlcjARBglghkgBhvhCAQEEBAMCBkAwHwYDVR0jBBgwFoAUWHVDwKVqMcOF\n\
Nd0arI3/QB3W6SwwDQYJKoZIhvcNAQELBQADggIBAI7Lggm/XzpugV93H5+KV48x\n\
X+Ct8unNmPCSzCaI5hAHGeBBJpvD0KME5oiJ5p2wfCtK5Dt9zzf0S0xYdRKqU8+N\n\
aKIvPoU1hFixXLwTte1qOp6TviGvA9Xn2Fc4n36dLt6e9aiqDnqPbJgBwcVO82ll\n\
HJxVr3WbrAcQTB3irFUMqgAke/Cva9Bw79VZgX4ghb5EnejDzuyup4pHGzV10Myv\n\
hdg+VWZbAxpCe0S4eKmstZC7mWsFCLeoRTf/9Pk1kQ6+azbTuV/9QOBNfFi8QNyb\n\
18jUjmm8sc2HKo8miCGqb2sFqaGD918hfkWmR+fFkzQ3DZQrT+eYbKq2un3k0pMy\n\
UySy8SRn1eadfab+GwBVb68I9TrPRMrJsIzysNXMX4iKYl2fFE/RSNnaHtPw0C8y\n\
B7memyxPRl+H2xg6UjpoKYh3+8e44/XKm0rNIzXjrwA8f8gnw2TbqmMDkj1YqGnC\n\
SCj5A27zUzaf2pT/YsnQXIWOJjVvbEI+YKj34wKWyTrXA093y8YI8T3mal7Kr9YM\n\
WiIyPts0/aVeziM0Gunglz+8Rj1VesL52FTurobqusPgM/AME82+qb/qnxuPaCKj\n\
OT1qAbIblaRuWqCsid8BzP7ZQiAnAWgMRSUg1gzDwSwRhrYQRRWAyn/Qipzec+27\n\
/w0gW9EVWzFhsFeGEssi\n\
-----END CERTIFICATE-----";

static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max) {
    FILE *file = (FILE *)cls;
    size_t bytes_read;

    /* 'fseek' may not support files larger 2GiB, depending on platform.
     * For production code, make sure that 'pos' has valid values, supported by
     * 'fseek', or use 'fseeko' or similar function. */
    if (0 != fseek(file, (long)pos, SEEK_SET))
        return MHD_CONTENT_READER_END_WITH_ERROR;
    bytes_read = fread(buf, 1, max, file);
    if (0 == bytes_read)
        return (0 != ferror(file)) ? MHD_CONTENT_READER_END_WITH_ERROR
                                   : MHD_CONTENT_READER_END_OF_STREAM;
    return (ssize_t)bytes_read;
}

static void file_free_callback(void *cls) {
    FILE *file = cls;
    fclose(file);
}

/* HTTP access handler call back */
static enum MHD_Result http_ahc(void *cls, struct MHD_Connection *connection,
                                const char *url, const char *method,
                                const char *version, const char *upload_data,
                                size_t *upload_data_size, void **req_cls) {
    static int aptr;
    struct MHD_Response *response;
    enum MHD_Result ret;
    FILE *file;
    int fd;
    struct stat buf;
    (void)cls;              /* Unused. Silent compiler warning. */
    (void)version;          /* Unused. Silent compiler warning. */
    (void)upload_data;      /* Unused. Silent compiler warning. */
    (void)upload_data_size; /* Unused. Silent compiler warning. */

    if (0 != strcmp(method, MHD_HTTP_METHOD_GET))
        return MHD_NO; /* unexpected method */
    if (&aptr != *req_cls) {
        /* do never respond on first call */
        *req_cls = &aptr;
        return MHD_YES;
    }
    *req_cls = NULL; /* reset when done */

    file = fopen(&url[1], "rb");
    if (NULL != file) {
        fd = fileno(file);
        if (-1 == fd) {
            (void)fclose(file);
            return MHD_NO; /* internal error */
        }
        if ((0 != fstat(fd, &buf)) || (!S_ISREG(buf.st_mode))) {
            /* not a regular file, refuse to serve */
            fclose(file);
            file = NULL;
        }
    }

    if (NULL == file) {
        response = MHD_create_response_from_buffer_static(
            strlen(EMPTY_PAGE), (const void *)EMPTY_PAGE);
        ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
        MHD_destroy_response(response);
    } else {
        response = MHD_create_response_from_callback(
            (size_t)buf.st_size, 32 * 1024, /* 32k page size */
            &file_reader, file, &file_free_callback);
        if (NULL == response) {
            fclose(file);
            return MHD_NO;
        }
        ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
        MHD_destroy_response(response);
    }
    return ret;
}

int main(int argc, char *const *argv) {
    struct MHD_Daemon *TLS_daemon;
    int port;

    if (argc != 2) {
        printf("%s PORT\n", argv[0]);
        return 1;
    }

    port = atoi(argv[1]);
    if ((1 > port) || (port > 65535)) {
        fprintf(stderr, "Port must be a number between 1 and 65535.\n");
        return 1;
    }

    TLS_daemon = MHD_start_daemon(
        MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD |
            MHD_USE_ERROR_LOG | MHD_USE_TLS,
        (uint16_t)port, NULL, NULL, &http_ahc, NULL,
        MHD_OPTION_CONNECTION_TIMEOUT, 256, MHD_OPTION_HTTPS_MEM_KEY, key_pem,
        MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END);
    if (NULL == TLS_daemon) {
        fprintf(stderr, "Error: failed to start TLS_daemon.\n");
        return 1;
    }
    printf("MHD daemon listening on port %u\n", (unsigned int)port);

    (void)getc(stdin);
    MHD_stop_daemon(TLS_daemon);
    return 0;
}

接下來使用自簽憑證設定 HTTPS 並且採用 GnuTLS 載入檔案的方式。
首先建立 ssl.conf 設定檔:

[req]
prompt = no
default_md = sha256
default_bits = 2048
distinguished_name = dn
x509_extensions = v3_req

[dn]
C = TW
ST = Taiwan
L = Taipei
O = Orange Inc.
OU = IT Department
emailAddress = admin@example.com
CN = localhost

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.localhost
DNS.2 = localhost
IP.1 = 127.0.0.1

透過 OpenSSL 指令建立開發測試用途的自簽憑證:

openssl req -x509 -new -nodes -sha256 -utf8 -days 3650 \
-newkey rsa:2048 -keyout httpd.key -out httpd.crt -config ssl.conf

下面是一個使用的例子:

#include <microhttpd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>

#define BUF_SIZE 1024
#define MAX_URL_LEN 255

#define EMPTY_PAGE                                                             \
    "<html><head><title>File not found</title></head><body>File not "          \
    "found</body></html>"

#include <gnutls/gnutls.h>
#include <gnutls/abstract.h>

/**
 * A hostname, server key and certificate.
 */
struct Hosts {
    struct Hosts *next;
    const char *hostname;
    gnutls_pcert_st pcrt;
    gnutls_privkey_t key;
};

#define PAGE                                                                   \
    "<html><head><title>libmicrohttpd https demo</title>"                      \
    "</head><body>libmicrohttpd https demo</body></html>"

static struct Hosts *hosts;

/* Load the certificate and the private key.
 * (This code is largely taken from GnuTLS).
 */
static void load_keys(const char *hostname, const char *CERT_FILE,
                      const char *KEY_FILE) {
    int ret;
    gnutls_datum_t data;
    struct Hosts *host;

    host = malloc(sizeof(struct Hosts));
    if (NULL == host)
        abort();
    host->hostname = hostname;
    host->next = hosts;
    hosts = host;

    ret = gnutls_load_file(CERT_FILE, &data);
    if (ret < 0) {
        fprintf(stderr, "*** Error loading certificate file %s.\n", CERT_FILE);
        exit(1);
    }
    ret = gnutls_pcert_import_x509_raw(&host->pcrt, &data, GNUTLS_X509_FMT_PEM,
                                       0);
    if (ret < 0) {
        fprintf(stderr, "*** Error loading certificate file: %s\n",
                gnutls_strerror(ret));
        exit(1);
    }
    gnutls_free(data.data);

    ret = gnutls_load_file(KEY_FILE, &data);
    if (ret < 0) {
        fprintf(stderr, "*** Error loading key file %s.\n", KEY_FILE);
        exit(1);
    }

    gnutls_privkey_init(&host->key);
    ret = gnutls_privkey_import_x509_raw(host->key, &data, GNUTLS_X509_FMT_PEM,
                                         NULL, 0);
    if (ret < 0) {
        fprintf(stderr, "*** Error loading key file: %s\n",
                gnutls_strerror(ret));
        exit(1);
    }
    gnutls_free(data.data);
}

static int cert_callback(gnutls_session_t session,
                         const gnutls_datum_t *req_ca_dn, int nreqs,
                         const gnutls_pk_algorithm_t *pk_algos,
                         int pk_algos_length, gnutls_pcert_st **pcert,
                         unsigned int *pcert_length, gnutls_privkey_t *pkey) {
    char name[256];
    size_t name_len;
    struct Hosts *host;
    unsigned int type;
    (void)req_ca_dn;
    (void)nreqs;
    (void)pk_algos;
    (void)pk_algos_length; /* Unused. Silent compiler warning. */

    name_len = sizeof(name);
    if (GNUTLS_E_SUCCESS !=
        gnutls_server_name_get(session, name, &name_len, &type, 0 /* index */))
        return -1;
    for (host = hosts; NULL != host; host = host->next)
        if (0 == strncmp(name, host->hostname, name_len))
            break;
    if (NULL == host) {
        fprintf(stderr, "Need certificate for %.*s\n", (int)name_len, name);
        return -1;
    }
#if 1
    fprintf(stderr, "Returning certificate for %.*s\n", (int)name_len, name);
#endif
    *pkey = host->key;
    *pcert_length = 1;
    *pcert = &host->pcrt;
    return 0;
}

static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max) {
    FILE *file = (FILE *)cls;
    size_t bytes_read;

    /* 'fseek' may not support files larger 2GiB, depending on platform.
     * For production code, make sure that 'pos' has valid values, supported by
     * 'fseek', or use 'fseeko' or similar function. */
    if (0 != fseek(file, (long)pos, SEEK_SET))
        return MHD_CONTENT_READER_END_WITH_ERROR;
    bytes_read = fread(buf, 1, max, file);
    if (0 == bytes_read)
        return (0 != ferror(file)) ? MHD_CONTENT_READER_END_WITH_ERROR
                                   : MHD_CONTENT_READER_END_OF_STREAM;
    return (ssize_t)bytes_read;
}

static void file_free_callback(void *cls) {
    FILE *file = cls;
    fclose(file);
}

/* HTTP access handler call back */
static enum MHD_Result http_ahc(void *cls, struct MHD_Connection *connection,
                                const char *url, const char *method,
                                const char *version, const char *upload_data,
                                size_t *upload_data_size, void **req_cls) {
    static int aptr;
    struct MHD_Response *response;
    enum MHD_Result ret;
    FILE *file;
    int fd;
    struct stat buf;
    (void)cls;              /* Unused. Silent compiler warning. */
    (void)version;          /* Unused. Silent compiler warning. */
    (void)upload_data;      /* Unused. Silent compiler warning. */
    (void)upload_data_size; /* Unused. Silent compiler warning. */

    if (0 != strcmp(method, MHD_HTTP_METHOD_GET))
        return MHD_NO; /* unexpected method */
    if (&aptr != *req_cls) {
        /* do never respond on first call */
        *req_cls = &aptr;
        return MHD_YES;
    }
    *req_cls = NULL; /* reset when done */

    file = fopen(&url[1], "rb");
    if (NULL != file) {
        fd = fileno(file);
        if (-1 == fd) {
            (void)fclose(file);
            return MHD_NO; /* internal error */
        }
        if ((0 != fstat(fd, &buf)) || (!S_ISREG(buf.st_mode))) {
            /* not a regular file, refuse to serve */
            fclose(file);
            file = NULL;
        }
    }

    if (NULL == file) {
        response = MHD_create_response_from_buffer_static(
            strlen(EMPTY_PAGE), (const void *)EMPTY_PAGE);
        ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
        MHD_destroy_response(response);
    } else {
        response = MHD_create_response_from_callback(
            (size_t)buf.st_size, 32 * 1024, /* 32k page size */
            &file_reader, file, &file_free_callback);
        if (NULL == response) {
            fclose(file);
            return MHD_NO;
        }
        ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
        MHD_destroy_response(response);
    }
    return ret;
}

int main(int argc, char *const *argv) {
    struct MHD_Daemon *TLS_daemon;
    int port;

    if (argc != 2) {
        printf("%s PORT\n", argv[0]);
        return 1;
    }

    port = atoi(argv[1]);
    if ((1 > port) || (port > 65535)) {
        fprintf(stderr, "Port must be a number between 1 and 65535.\n");
        return 1;
    }

    load_keys("localhost", "./httpd.crt", "./httpd.key");

    TLS_daemon = MHD_start_daemon(
        MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD |
            MHD_USE_ERROR_LOG | MHD_USE_TLS,
        (uint16_t)port, NULL, NULL, &http_ahc, NULL,
        MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int)120,
        MHD_OPTION_HTTPS_CERT_CALLBACK, &cert_callback, 
        MHD_OPTION_END);
    if (NULL == TLS_daemon) {
        fprintf(stderr, "Error: failed to start TLS_daemon.\n");
        return 1;
    }
    printf("MHD daemon listening on port %u\n", (unsigned int)port);

    (void)getc(stdin);
    MHD_stop_daemon(TLS_daemon);
    return 0;
}

參考連結

2024/10/31

Beyond 粵語歌曲歌單

Beyond 是香港搖滾樂隊。在主唱黃家駒在 1993 年在日本東京富士電視台錄制遊戲節目《想做甚麼,就做甚麼》上因為節目設計問題而意外去世後, Beyond 其它成員(主音吉他: 黃貫中、貝斯: 黃家強、鼓: 葉世榮)與滾石簽五年約,繼續以 Beyond 的名義發展。

下面是我讀一些新聞以後的想法。在一些訪談中,有提到黃家駒在意外幾個月前聊天時其實就有提過他擔心他會跌倒發生意外的事情。如果觀察整個 Beyond 的發展歷史,那麼或者黃家駒在樂隊成為香港的頂尖樂隊之後就開始有了這種預感, 因為可以觀察到,雖然黃家駒是主唱,但是在專輯裡其它三人也有一些個人創作並且在一些歌曲擔任主唱的時候, 就像是為了預防他如果意外離開,其它三人如果想繼續(即使是個人單飛發展),就可以繼續自己的音樂路。

而在黃家駒意外死亡後,這個時候 Beyond 其實有三種選擇:

  1. 從外界選擇一個新主唱。這個想法不可行的原因是 Beyond 是個極為優秀的創作樂團,所以如果要接下這個位置, 除了唱功要好,至少還需要優秀的作曲與編曲能力,這讓人選近乎為零。
  2. 不用設置主唱,而是三人各自以及合作創作,該歌曲的主創作人就是該歌的主唱。
  3. 三個人裡選擇一個新的主唱,而從使用樂器以及才華來說,就算不如黃家駒, 音樂才華也是十分優秀的黃貫中足以帶領 Beyond 繼續前進,同時樂隊也重新有了創作中心。

事後來看,這就是黃家強身為黃家駒的弟弟與黃貫中的不可協調之處。 一開始的時候是選項二,但是在滾石五年約快結束的時候黃貫中與黃家強在葉世榮不知道的情況有過談判, 葉世榮是選項二和選項三都可以,但是黃家強只接受選項二(因為是黃家駒的弟弟,所以他心裡只接受主唱是他哥哥), 黃貫中卻從幾個專輯的製作中意識到因為三個人有不同的音樂風格,如果要繼續走下去,他認為 Beyond 需要一個新主唱作為創作中心, 而他希望那就是他,但是黃家強直接而且不留餘地的否決,所以 Beyond 暫時解散及三人各自發展。

而後,在 2003 年為了紀念樂隊成立 20 周年,所以又短暫合體,並且把黃家駒一首遺作重新編曲出版,成為紀念周年作《抗戰二十年》。 但是問題一樣存在,而黃家強一樣堅持自己的想法,結果就是 Beyond 正式解散。這也是為什麼黃家強說 Beyond 緣盡了, 黃家強和黃貫中的主張在他們的立場而言都是正確的,但因為黃家強太愛他的哥哥,所以完全沒有調和的可能性。

我以聽 Beyond 國語歌曲為主,不過歌單中還是有放一些粵語歌曲(不固定,所以這只是我現在的歌單)。

  • 再見理想

    原為講述舊一代玩樂隊和在夜總會伴奏的樂手的際遇,其中由黃家駒獨唱的版本收錄在 1986 年自資發行的同名專輯《再見理想》中。 由樂隊四名成員共同參與演唱的版本收錄在 Beyond 1988年發行的粵語專輯《秘密警察》中。 歌名可以有二個意思,黃家駒獨唱的版本像是再見了理想,而四名成員合唱的版本則是再見到了理想。

  • 昔日舞曲

    有一天黃家駒拿著吉他走到街上,經過天橋時,橋下有個乞丐拉住了黃家駒的吉他,黃家駒對他說自己也沒有錢給他了。 可是那個乞丐並不是想要錢,黃家駒不懂他的意思。於是乞丐叫黃家駒坐下,向黃家駒訴說了自己昔日的理想,過去從事的事業、奮鬥的歷程以及歷經的輝煌等。 乞丐這番話使得黃家駒感慨頗深,並激勵了年輕的黃家駒在今後的音樂生涯中不斷奮鬥不斷超越自己。於是黃家駒寫了《昔日舞曲》這首歌, 以此紀念那個乞丐與他的談話,表達對音樂理想的不懈追求。這首歌收錄在 EP《永遠等待》中。

  • 亞拉伯跳舞女郎

    Beyond 第一張商業專輯《亞拉伯跳舞女郎》的同名主打歌。 《亞拉伯跳舞女郎》是一張充滿中東風情的概念專輯,專輯中充滿幻象與歷奇的場景。

  • 東方寶藏

    由《Long Way Without Friends》重新填詞並且加上中東音樂風格的版本, 收錄在《亞拉伯跳舞女郎》中。

  • 舊日的足跡

    《舊日的足跡》創作於 1985 年,歌曲靈感來自於黃家駒的一位好友 Mike Lau。 Mike Lau 故鄉在北京,為了學電影而遠赴美國, 十年後終於回到故鄉,感觸頗深。他來到香港後與黃家駒暢談自己的感想,黃家駒便將他這份思念故鄉的情懷寫進《舊日的足跡》一曲之中。 《舊日的足跡》最早收錄於 1986 年自資發行的《再見理想》中,而後在《現代舞台》中也有將前奏改為鋼琴的版本。我喜歡的是改為鋼琴的版本。

  • 冷雨夜

    《冷雨夜》由黃家駒作曲。黃家強聽到該曲的小樣之後,非常喜歡這首歌,並挑選了它收錄進 Beyond 樂團的專輯裡。 在 1991 年的演唱會裡,黃家強在《冷雨夜》表演的貝斯獨奏是為人稱道的經典。 國語版為《緩慢》。

  • 大地

    《大地》(1988年粵語、1990年國語)由黃家駒作曲,由黃貫中主唱(粵語及國語)。 《大地》歌詞隱喻兩岸中國人長年分隔的骨肉分離的滄桑。

  • 喜歡妳

    《喜歡妳》是黃家駒寫給和自己已經分手的女友的一首歌。最初做音樂時,由於某些原因黃家駒不得不放棄深愛著的女友, 把時間和精力放到音樂之中,這令他十分愧疚。所以他便寫了《喜歡妳》這首歌,表達對失去愛情的苦楚。

  • 真的愛妳

    《真的愛妳》收錄於《Beyond IV》大碟,為該專輯的主打歌。歌曲以讚頌母愛為主題,表達了對母愛的讚揚。

  • 歲月無聲

    《歲月無聲》收錄於 1989 年的專輯《真的見證》。此曲原本由麥潔文主唱,最初以情歌風格編曲, 其後由 Beyond 重新以搖滾風格演繹。因為被認為與六四有關,所以成為中國禁曲 (一說是因為版權的關係,所以無法在中國音樂網站搜尋到此曲)。

  • 灰色軌跡

    這首歌是 1990 年劉德華、吳倩蓮主演的電影《天若有情》的插曲。

  • 光輝歲月

    《光輝歲月》的粵語版是一首讚美南非的非洲人國民大會主席納爾遜·曼德拉的歌曲,以歌頌他在南非種族隔離時期為黑人所付出的努力, 當時曼德拉在監禁 28 年後剛被釋放,光輝歲月表達他的一生。在國語版裡面,這首《光輝歲月》是為激勵年輕人努力拼搏而作, 而當中的種族議題被淡化。

  • Amani

    《Amani》是樂團為呼籲資助非洲難民兒童,呼喚和平而創作的歌曲。

  • 不再猶豫

    《Beyond日記之莫欺少年窮》的主題曲,為 Beyond 的合唱歌曲,同時也是其著名的勵志歌曲。 國語版為《候診室》。

  • 誰伴我闖蕩

    《Beyond日記之莫欺少年窮》的插曲,國語版為《十字路口》。

  • 完全的擁有

    這是鼓手葉世榮在 Beyond 的第一首主唱歌曲,也是黃家駒去世前的惟一一首。

  • 長城

    《長城》由黃家駒作曲及擔當主音、劉卓輝作詞、Beyond 和梁邦彥共同編曲、喜多郎創作前奏;日語版《THE WALL》由真名杏樹填詞; 國語版歌詞由詹德茂改編。粵語版本收錄於Beyond第8張專輯《繼續革命》,並為該大碟之主打歌;日語版本收錄於《超越》,國語版本收錄於《信念》。 黃家駒在一段由香港無綫電視為此曲製作的音樂錄像表示,寫此歌是要「描寫中國人一貫的民族意識」。在歌詞裡,長城反映一個封閉的國度,是強權暴政的產物,是犧牲了無數血肉之軀築成的,然而後人大多只會以它為榮,無視值得反思之處。歌詞是借物描寫這種民族思想和境況,並借古諷今,並非只是寫長城和遠古的中國。 因為被認為與六四有關,以及在香港 2014 「和平佔中」、「雨傘運動」成為抗議者的演唱歌曲,或者被用來影射目前的中國政治, 所以曾經(或者在某一些特別日子)是中國禁曲。

  • 農民

    《農民》原曲為《文武英傑宣言》,而後重新填詞為《農民》,有廣東話和國語部份,內容大抵是描述一個中國農民的生活,如何在艱困的生活中逆境自強。 廣東話和國語的版本卻有著極大不同。廣東話版本是由劉卓輝填詞,是對山區農民生活的影射;而國語版則由姚若龍填詞,內容更為廣泛, 是描述北方人重視固有生活的個性。

  • 不可一世

    Beyond 在香港成名後前經理陳健添就更加變本加厲的密密麻麻安排商業娛樂性重的工作,陳健添還因經理人佣金和分紅和 Beyond 起糾紛, Beyond 早已厭倦陳健添這種為利是圖處處算計的人壓榨逼迫,以及他安排下過的違背意願的奉迎生活, 他們寫的《不可一世》是諷刺逼迫控制他們越緊的經理人陳健添,而不是陳健添口中所說的諷刺電視台高層。 重新填詞的國語版《今天就做》則是表達了一種生活態度。

  • 早班火車

    《早班火車》是一首表達暗戀心情的情歌,黃家駒、黃家強、黃貫中作曲,林振強作詞,黃家駒主唱。

  • 海闊天空

    《海闊天空》被視為黃家駒最具代表性的遺作,同時也是粵語流行音樂的巅峰之作,收錄在專輯《樂與怒》與國語精選專輯《海闊天空》中。 這首歌是記錄 Beyond 十年心路歷程的歌曲,歌詞承載了黃家駒與樂隊赴日本發展的艱辛與對理想的堅持, 也表達了黃家駒內心深處對香港樂壇的掙扎和失望。曲帶給人們的是一種積極向上的生活態度,堅持自己的理想,永遠不放棄的信念。 當年黃家駒在編寫《海闊天空》一曲時,曾將歌詞其中一句定為「也會怕有一天會跌倒 Oh Yeah」,但黃家強認為意思不對,遂修改為「……Oh No」, 沒料到黃家駒在完成此曲後不足2個月真的意外身亡。

  • 狂人山莊

    收錄在專輯《樂與怒》的硬搖滾作品。在專輯《樂與怒》中 Beyond 嘗試了更多的音樂風格, 但是卻仍然能夠被大多數人欣賞,顯示了 Beyond 成熟且優秀的音樂創作能力, 也因此黃家駒在 1993 年日本節目上意外去世才讓人惋惜。

  • 全是愛

    收錄在《樂與怒》與精選專輯《海闊天空》的作品,我會放這首是因為我喜歡這首歌的前奏。

  • 和平與愛

    Beyond 一首關注第三世界的音樂作品,收錄在《樂與怒》與精選專輯《海闊天空》的作品。

  • 情人

    《情人》是 Beyond 為各自的愛人創作的歌曲,不過該曲作詞人劉卓輝後來稱,這首原本叫《大陸情人》的歌曲, 其實是藉分隔兩地的感情來隱喻內地與香港的關係。

  • 總有愛

    《總有愛》是黃家強在 Beyond 經歷黃家駒去世的打擊後創作的歌曲, 他創作這首歌是為了感謝在 Beyond 最困難的時期依然無悔奉獻、關心支持他們的歌迷朋友。 國語版為《一輩子陪我走》。

  • 教壞細路

    《教壞細路》中的「細路」的意思是小孩子。《教壞細路》直白的揭露了彼時香港媒體的過度商業和虛假, 也因此歌曲一發行 Beyond 就遭到了香港 TVB 的封鎖。

  • 無助

    《無助》由葉世榮/李焯雄作詞,葉世榮作曲並演唱,收錄在 Beyond 1997 年 4 月由滾石唱片發行的專輯《請將手放開》中。 這是由葉世榮主唱的一首歌曲。


  • 《霧》由黃偉文作詞,黃貫中作曲並演唱,Beyond、黃仲賢、劉志遠共同編曲,收錄在 Beyond 1997 年 12 月由滾石唱片發行的專輯《驚喜》中。 《霧》以流行搖滾的曲調呈現,吉他伴奏有重型的夢幻流行,編曲用格調化的手法。 《霧》的歌詞寫的是愛情,在迷霧中讀不懂、看不清,最後只能感嘆歲月已過。

  • 不見不散

    《不見不散》這張 1998 年發行的專輯流露出三人創作野心,除了 Beyond 3 位成員外,還有邀請樂隊早期成員劉志遠參與, 此專輯出現三人自己的音樂個性。《不見不散》也是同名專輯中的一首歌曲,由黃貫中作詞作曲。

  • 抗戰二十年

    2003 年是 Beyond 成立 20 週年的日子,家強在家駒生前留下的 demo中,選了一首重新製作作為主題曲, 特別之處是歌曲直接用了 demo 中的一段作前奏,由家駒自彈自哼出旋律,到中間其他隊友加入,鑄成四子不可思議的合作。 《抗戰二十年》這首歌與《海闊天空》、《光輝歲月》均被視為 2014 年香港 6.22 民間全民投票、七一大遊行、 學界大罷課與讓愛與和平佔領中環/雨傘革命爭取自由民主的主題歌曲,同時也被一些人認為有暗示六四的歌詞, 所以《抗戰二十年》也是一首中國禁曲。

  • 長空

    《無間道2》的主題曲,也是 Beyond 正式解散前的最後一首歌,該曲獲得第 23 屆香港電影金像獎最佳原創電影歌曲獎。

2024/08/17

MonetDB

MonetDB is an open-source column-oriented relational database management system (RDBMS) originally developed at the Centrum Wiskunde & Informatica (CWI) in the Netherlands. It is designed to provide high performance on complex queries against large databases, such as combining tables with hundreds of columns and millions of rows.

MonetDB architecture is represented in three layers, each with its own set of optimizers. The front end is the top layer, providing query interface for SQL. Queries are parsed into domain-specific representations, like relational algebra for SQL, and optimized. The generated logical execution plans are then translated into MonetDB Assembly Language (MAL) instructions, which are passed to the next layer. The middle or back-end layer provides a number of cost-based optimizers for the MAL. The bottom layer is the database kernel, which provides access to the data stored in Binary Association Tables (BATs). Each BAT is a table consisting of an Object-identifier and value columns, representing a single column in the database.

MonetDB internal data representation also relies on the memory addressing ranges of contemporary CPUs using demand paging of memory mapped files, and thus departing from traditional DBMS designs involving complex management of large data stores in limited memory.


使用 RPM 安裝以後,使用下列的方式開啟資料庫服務:

sudo systemctl start monetdbd.service

使用下列的方式查詢目前的狀態:

sudo systemctl status monetdbd.service

使用下列的方式停止服務:

sudo systemctl stop monetdbd.service

下面建立一個 demo 資料庫。

sudo monetdb create demo

還需要 release 才能夠使用:

sudo monetdb release demo

然後就可以使用 mclient 連線進行測試:

mclient -u monetdb -d demo

一般而言可以將 user/password 記錄在 .monetdb 中,這樣就不需要輸入帳號密碼,只需要提供資料庫名稱。 下面是內容設定的例子:

user=monetdb
password=monetdb

如果想要刪除資料庫,可以使用 stop 與 destroy:

sudo monetdb stop demo
sudo monetdb destroy demo

使用下列的指令建立一個使用者 danilo:

CREATE USER "danilo" WITH PASSWORD 'danilo' NAME 'Danilo' SCHEMA "sys";
CREATE SCHEMA "danilo" AUTHORIZATION "danilo";
ALTER USER "danilo" SET SCHEMA "danilo";

使用 mclient 連線驗證:

mclient -u danilo demo

MonetDB/e Embedded

MonetDB/e is the embedded version of MonetDB, embed the power of an analytical SQL database engine in your Python or C/C++ applications.

相關連結