2025/08/31

魔獸爭霸3

《魔獸爭霸III:混亂之治》(Warcraft III: Reign of Chaos)是暴雪娛樂在 2002 年出品的即時戰略遊戲。 2003 年 5 月暴雪公司又發行了《魔獸爭霸III:寒冰霸權》(Warcraft III: The Frozen Throne),它是本作的資料片。 《魔獸爭霸III:淬鍊重生》(Warcraft III: Reforged)在 2020 年發行,為 2002 年的《魔獸爭霸III》之重製版(即remastered), 包括《混亂之治》與《寒冰霸權》的全部劇情。 《魔獸爭霸III》流行的其中一個原因是其地圖編輯器十分強大,因此有不少優秀的自製地圖, 例如:DOTA、信長之野望、三國無雙、軍團戰爭、七個人、各類TD守塔遊戲。這些玩家自製地圖深刻影響了後續遊戲業發展, 很多遊戲的雛型都是從這些玩家地圖發展而來,如 MOBA 類游戲英雄聯盟等。 但是因為暴雪宣布對《淬鍊重生》中玩家用地圖編輯器定製地圖的所有權要求, 不少優秀的自製地圖創作者因此不在《淬鍊重生》繼續創作。

可以參考的資料:

《魔獸爭霸III:混亂之治》與《魔獸爭霸III:寒冰霸權》安裝時需要 CD-Key, 例如 8RTJDU-IH67-BQEL2A-BPSS-NX3197(原作)與 NKHZCB-GEPY-2MM98T-WFF9-X9WPNT(資料片)。 在版本 1.21b 時移除光碟檢查,而 1.27b 則是其最後一版可以離線安裝的版本。 自 1.28.0 開始《魔獸爭霸III》採用新架構並且開始沒有提供離線更新安裝,在 1.29.0 則開始更多的架構更改與細節更新, 1.30.0 則是進行很多細節上的平衡性修改(例如將 Spirit Walker 從 Spirit Lodge 移往 Tauren Totem 生產), 可以說是為了重製版《魔獸爭霸III:淬鍊重生》(Warcraft III: Reforged)而開始進行強制轉換前的準備。 因為英雄以及中立生物的關係,所以《魔獸爭霸III》的平衡性更難調整,不過觀察過更新的內容以後,可以說在 1.27b 就已經達成大致上的平衡, 但是因為 1.30.0 大改版的關係,所以需要玩家的勝負資料在後續版本微調各個種族的平衡性。

使用 Wine 在 Linux 執行 1.27b 會有遊戲中的動畫會黑屏無法正確執行的問題,目前看來是遊戲的問題,沒有解決方案。 在 1.29 之前,可以使用 -opengl 這個命令列選項選擇使用 OpenGL 而非 D3D 作為繪製畫面的 API。

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

《魔獸爭霸III》使用的資源為黃金 (Gold) 與 木材 (Lumber)。 對比《星海爭霸》,《魔獸爭霸III》略為簡化了資源管理的部份,黃金只需要最多 5 個工人採集,這降低了資源管理的難度。

《魔獸爭霸III:混亂之治》的人口最大值為 90,而《魔獸爭霸III:寒冰霸權》則增加到 100。

《魔獸爭霸III》使玩家集中注意力於「控制戰鬥單位」而非「生產戰鬥單位」。該遊戲加入一種全新戰鬥單位,是為英雄, 乃一種可透過獲取經驗值升級並增強能力的超級戰鬥單位。其可分為本族英雄和中立英雄。每當己方殺滅一個敵方單位或中立生物時, 英雄便可獲取相當的經驗值而累積一定程度時其等級就會上升。等級每當上升時,英雄便可通過添加技能點學習或加強一項技能,不同英雄可學習之技能亦有所異。

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

而另一影響遊戲策略的操施就是維護費徵取 (Upkeep),此操施源於一種概念——擁有越多戰鬥單位就須要付出越多的資源去滿足部隊的需要, 如士兵需要補給、武器需要打造、盔甲需要鍛煉等。該遊戲則以上稅實行此概念。當玩家部隊的數目到達一定程度時, 就須於每採集十塊黃金上繳其中三塊。當部隊數目抵達更高程度時,每十塊就須上繳六塊。 也因此《魔獸爭霸III》讓玩家沒有一直生產兵種的壓力(因為較低的人口數以及維護費徵取的設計)。 對比《星海爭霸》,雖然因為英雄單位與維護費徵取的關係,《魔獸爭霸III》偏重於玩家微操的部份,但是因為《星海爭霸》本來就是快節奏的遊戲, 《星海爭霸:怒火燎原》的新單位還加快了其遊戲的節奏,因此《魔獸爭霸III》的節奏更適合一般玩家,而非只適合職業選手。


《魔獸爭霸III》的攻擊類型為下列幾種:

  • Normal - Mainly used by melee or short ranged units. Effective against most ground ranged units.
  • Piercing - Primarily used by ranged attackers, ground, air, or structure. Effective against air units and spellcasters.
  • Magic - Primarily used by spellcasters, but also by certain heavy air units. Squashes most ground melee units. Introduced in patch 1.06. Cannot attack magic immune units, like spell breakers and destroyers.
  • Siege - Used by siege units, to destroy fortifications and spellcasters.
  • Hero - Used by Heroes. Full damage to all units except those with Fortified armor.
  • Chaos - Used by powerful summoned units and creeps above level 6. 100% damage to all armor types. Used by the Demon Hunter in demon form.
  • Spell - Used by abilities. Deals reduced damage to heroes. Also poison abilities use this attack type. Note that spell immunity does not affect spell damage.

《魔獸爭霸III》的裝甲類型為下列幾種:

  • Heavy - Primarily used by melee units, long-ranged siege weaponry, and summoned units.
  • Medium - Primarily used by ground ranged units.
  • Light - Used by most air units, and Scout Towers.
  • Unarmored - Mostly Used by spellcasters, and certain air units.
  • Fortified - Used by most buildings.
  • Hero - Used by Heroes.
  • Divine - Used by powerful characters in the campaign.

《魔獸爭霸III》的建築是由工人(Human Peasants, Orc Peons, Undead Acolytes 與 Night Elf Wisps))所建造的。 資料片各種族都增加了商店 (Shop) 的設計,分別為 Human 的 Arcane Vault,Orc 的 Voodoo Lounge,Undead 的 Tomb of Relics, Night Elf 的 Ancient of Wonders。 Unit Inventory 則是資料片新增加四個種族都有的研發選項,研發後一般單位可以攜帶物品。

《魔獸爭霸III》有自動施法 (Autocast) 的設計,自動施法技能可以設定為自動施放。右鍵點選該技能即可開啟或關閉自動施放功能。

Human 的建築只要地形允許就可以建造,工人 Peasant 能夠在 Town Hall 使用 Call to Arms 變身為 Militia 進行防禦。 多個工人可以一起建造建築讓建造建築的速度變快。Farm 提供食物(6 food),從而增加可訓練單位的最大數量。 Altar of Kings 為 Human 生產英雄的建築。 Human 的木材收集建築為 Lumber Mill,攻擊防守升級的建築為 Blacksmith。 Human 需要建立 Scout Tower,再來才是升級為 Guard Tower,Arcane Tower 或者是 Cannon Tower。 Barracks 是 Human 第一級主堡的生產建築。 Footman 是 Human 的初階步兵,可以研發 Defend 降低 50% 的遠程攻擊,但是移動速度也降低了 30%。 Rifleman 是 Human 的初階遠程攻擊兵種,研發 Long Rifles 可以增加其攻擊範圍。 Priest 與 Sorceress 為原作的法師,生產自 Arcane Sanctum, Priest 擁有 Heal 的能力,升級後則具有 Dispel MagicInner Fire 技能。 Sorceress 的 Slow 技能用來降低對手的攻擊速度與移動速度,升級後則具有 InvisibilityPolymorph 技能 (在 1.36.2 版之後 Polymorph 才能夠對英雄使用)。 Spell Breaker 則是資料片新增加用來反魔的兵種,具有 Spell Immunity 的能力,第一個能力為 Spell Steal, 升級後則具有 Control MagicFeedback 技能。 Mortar Team 是升到二級主堡以後,在 Workshop 生產的攻城兵種,可以研發 Flare 用來偵查隱形的單位(可以照亮某個區域 15 秒)。 Flying Machine 是在 Workshop 生產的飛行兵種,用來對抗其它空軍的單位,具有 True Sight 能力用來偵測隱形, 並且升級到第三級主堡以後可以研發 Flak Cannons 以及可以攻擊地面單位的 Flying Machine Bombs。 Dragonhawk Rider 是資料片新增加的飛行兵種,生產自 Gryphon Aviary, 具有 Aerial Shackles 能力,用來對抗像是 Frost Wyrm 或者是 Chimaera 之類的空軍, 並且可以研發 Cloud 技能用來對抗防禦塔(注意:使用 Aerial Shackles 或 Cloud 技能時 Dragonhawk Rider 不能移動)。 Knight 是升到三級主堡以後,在 Barracks 生產的高階近戰兵種,研發 Animal War Training 後可以增加生命值。 Siege Engine 是升到三級主堡以後,在 Workshop 生產的高階兵種,特別之處在於其護甲為與建築物相同的 Fortified 類別。 Gryphon Rider 是 Human 的終極兵種,可以研發 Storm Hammers 技能。

Orc 的工人 Peons 可以躲在 Burrow 中進行防禦。Orc Burrow 提供食物(10 food),從而增加可訓練單位的最大數量。 Altar of Storms 為 Orc 生產英雄的建築。 Orc 的木材收集建築與攻擊防守升級的建築為 War Mill。 Orc 的防禦塔為 Watch Tower。 Barracks 是 Orc 第一級主堡的生產建築。 一些單位(Grunt 與 Raider)在升級 Pillage 以後可以在攻擊敵人的建築時掠奪敵人的資源。 Grunt 是 Orc 的初階步兵,可以研發 Brute Strength 提高生命值與額外的 3 點攻擊傷害。 Troll Headhunter 是 Orc 的初階遠程攻擊兵種。 Demolisher 是 Orc 在升到二級主堡以後,在 Barracks 生產的攻城兵種。 Raider 是 Orc 在升到二級主堡以後,在 Beastiary 生產的騎兵,攻擊類型為 Siege, 能夠研發 Ensnare 技能手動將空軍網下來攻擊,同時 Ensnare 也可以用來中斷需要連續施法的技能, 因此 Raider 是 Orc 重要的兵種。 Kodo Beast 也是生產自 Beastiary,具有 Devour 能力(Devour 可以用來吞噬一個陸軍單位,缺點是自己的視野也會因此被對手知道), 並且可以研發 War Drums Aura。 Wind Rider 是生產自 Beastiary 的空軍,攻擊力不錯,但是生命值與護甲的屬性值則較為遜色。 因為 Orc 反魔與反空的能力為四個種族中最弱的,資料片新增加了 Troll Batrider 用來幫忙反空, 其能力 Unstable Concoction 可以用來自爆 600 點傷害到目標飛行單位,並且可以研發 Liquid Fire 技能。 Shaman 與 Witch Doctor 為原作的法師, Shaman 擁有 Purge 的能力,升級後則具有 Lightning ShieldBloodlust 技能。 Witch Doctor 的 Sentry Ward 技能可以召喚一個隱形的 ward 用來提供某個區域的視野, 升級後則具有 Stasis Trap WardHealing Ward 技能。 Spirit Walker 則是資料片新增加用來幫忙反魔的兵種,具有二種型態(Ethereal Form 無法被物理攻擊,但是也無法攻擊對手), 只有 Resistant Skin 而非 Spell Immunity 能力(Orc 也是惟一沒有 Spell Immunity 能力單位的種族), 第一個能力為 Spirit Link,研發後則具有 Disenchant 與可以復活一個 Tauren 的 Ancestral Spirit 技能。 Tauren 是 Orc 的終極兵種,可以研發 Pulverize 技能,也是惟一終極兵種為陸軍的種族。

Undead 的建築必須要建造在 Blight 上(除了主堡 Necropolis 以及 Haunted Goldmine)。 一般(非英雄)的 Undead 單位只會在 Blight 的區域恢復生命值。 Undead 英雄在 Blight 的區域恢復生命值的速度會被提升。 工人 Acolyte 在建造建築時只要在一開始召喚就可以,之後就可以去執行其它任務。 Acolyte 在 Haunted Goldmine 上採集黃金,而不用將黃金帶回主堡。 Ziggurat 提供食物(10 food),從而增加可訓練單位的最大數量,並且可以升級為 Nerubian Tower 或者是 Spirit Tower。 Altar of Darkness 為 Undead 生產英雄的建築。 Undead 的木材收集建築與攻擊防守升級的建築為 Graveyard。 Crypt 是 Undead 第一級主堡的生產建築。 Ghoul 是 Undead 的初階步兵,研發 Cannibalize 後可以藉由消耗附近的屍體回復生命值, 也是用來收集木材的單位。也因為 Undead 採集黃金與木材的單位是分開的, 因此第一個建築和其它種族不同,通常會建議先建造 Crypt 而不是 Altar of Darkness。 Crypt Fiend 是 Undead 的初階遠程攻擊兵種,使用 Web 技能將空軍網下後攻擊, 並且可以研發 Burrow,Burrow 可以讓 Crypt Fiend 躲藏在地下並且恢復生命值(當然,在地下躲藏的時候無法攻擊)。 Gargoyle 是升到二級主堡以後的飛行兵種,可對空對地,可以學習 Stone Form 技能。 Meat Wagon 是升到二級主堡以後的攻城兵種,生產自 Slaughterhouse,擁有 Get Corpse 與 Drop All Corpses 的能力。 Necromancer 與 Banshee 為原作的法師, Necromancer 擁有 Raise Dead 的能力,升級後則具有 Unholy FrenzyCripple 技能。 Banshee 擁有 Curse 的能力,升級後則具有 Anti-magic ShellPossession 技能。 Obsidian Statue 可以用來恢復附近友方單位的生命值和法力值(Essence of BlightSpirit Touch 技能)。 Obsidian Statue 可以變形為 Destroyer,Destroyer 是資料片新增加用來反魔的兵種,具有 Spell Immunity 的能力, Devour Magic 是 Destroyer 的第一個技能。 Shade 生產自 Sacrificial Pit,需要犧牲一個 Acolyte 生產,是一個隱形的偵察單位。 Abomination 是升到三級主堡以後,在 Slaughterhouse 生產的高階近戰兵種, 在 Crypt 研發 Cannibalize 後 Abomination 也可以使用此技能。 Frost Wyrm 是 Undead 的終極兵種,可以研發 Freezing Breath 技能。

Night Elf 一些建築(被稱為 "Ancients")可以 uproot 然後移動,並且攻擊敵人的陸地單位。 在建造 ncients 時必須要犧牲工人 Wisp 才行。 Wisp 在 Entangled Gold Mine 上採集黃金,纏繞在樹木上收集木材,而不用將資源帶回主堡。 Moon Well 提供食物(10 food),從而增加可訓練單位的最大數量,擁有補充法力和生命值的能力。 Altar of Elders 為 Night Elf 生產英雄的建築。 Night Elf 攻擊防守升級的建築為 Hunter's Hall。 Night Elf 的防禦塔為 Ancient Protector。 Ancient of War 是 Night Elf 第一級主堡的生產建築。 在升級 Ultravision 之後,Night Elf 在在夜晚時有更好的視野。 Archer 是 Night Elf 的初階弓箭手,也是第一個兵種是遠程攻擊單位的種族。 Huntress 是 Night Elf 的初階近戰兵種,在初期很好用(但是中期以後就沒有太大的優勢), Sentinel 技能可以將 owl 放到樹上用來提供視野用來發現隱形單位與觀察對方的動向(一個 Huntress 只有一次的使用機會)。 Glaive Thrower 是 Night Elf 在一級主堡就可以生產的攻城兵種。 Hippogryph 生產自 Ancient of Wind,是用對空的兵種,Pick up Archer 能力則可以與 Archer 結合成為 Hippogryph Rider。 Druid of the Talon 與 Druid of the Claw 為原作的法師,同時前者兼任近戰單位與後者可以兼任空軍單位。 Druid of the Talon 生產自 Ancient of Lore,擁有 Roar 的能力,升級後則具有 Rejuvenation 技能, 並且具有 Bear Form(變身為 Bear 的能力)。 Druid of the Claw 生產自 Ancient of Wind,擁有 Faerie Fire 的能力,升級後則具有 Cyclone 技能, 並且具有 Crow Form(變身為 Crow 的能力)。 Dryad 生產自 Ancient of Lore,是原作的反魔單位,具有 Spell Immunity 的能力,第一個技能為 Slow Poison, 升級後則具有 Abolish Magic 的能力。 Faerie Dragon 生產自 Ancient of Wind,是資料片新增加用來反魔的兵種,具有 Spell Immunity 的能力,第一個技能為 Phase Shift, 升級後則具有 Mana Flare 的能力。 Mountain Giant 是資料片新增加的高階近戰兵種,具有 Taunt 能力,並且可以研發 War Club 技能(可將攻擊類型變為 Siege)。 Chimaera 是 Night Elf 的終極兵種,可以研發 Corrosive Breath 技能,缺點為無法對空,只能用來對付陸軍與建築。


英雄具有下列三種屬性(其中一種為某個英雄的主要屬性,當升級時會有額外的點數增加到屬性中)。

  • Strength: Each point of strength increases the maximum hit points by 25 and the hit point regeneration by 0.05 hit points per second. It also increases base attack damage by 1, if strength is the primary attribute of the hero.
  • Agility: Each point of agility increases armor by 0.3 and attack speed by 2%. It also increases base attack damage by 1, if agility is the primary attribute of the hero.
  • Intelligence: Each point of intelligence increases maximum mana by 15 and mana regeneration by 0.05 mana per second. It also increases base attack damage by 1, if intelligence is the primary attribute of the hero.

原作各種族各有 3 名英雄,資料片各種族又新增加了 1 名英雄,並且在資料片新增加了中立英雄的設計。 有個有趣的點是,在不計入中立英雄的情況下,Orc 是惟一一個三個屬性英雄都有的種族。 每個英雄所佔的人口數為 5,等級最高為 10 級,每場遊戲每一個玩家最多只有 3 名英雄可以出場。 因為一場戰役一個玩家最多只有 3 名英雄可以出場,所以會有單英雄策略、雙英雄策略,以及三英雄策略的差別。 以 Human 來說,如果是雙英雄策略,可以使用 Archmage 與 Mountain King 的組合; 如果是 Orc 可以使用 Blademaster 與 Shadow Hunter 的組合; 而以 Undead 來說,可以使用 Death Knight 與 Lich 的組合; Night Elf 則可以使用 Demon Hunter 與 Keeper of the Grove 的組合。

Faction Heroes
Human Archmage (Intelligence), Mountain King (Strength), Paladin (Strength), Blood Mage (Intelligence)
Orc Blademaster (Agility), Far Seer (Intelligence), Tauren Chieftain (Strength), Shadow Hunter (Agility)
Undead Death Knight (Strength), Dreadlord (Strength), Lich (Intelligence), Crypt Lord (Strength)
Night Elf Demon Hunter (Agility), Keeper of the Grove (Intelligence), Priestess of the Moon (Agility), Warden (Agility)
Neutral Alchemist (Strength), Beastmaster (Strength), Dark Ranger (Agility), Firelord (Agility), Naga Sea Witch (Intelligence), Pandaren Brewmaster (Strength), Pit Lord (Strength), Tinker (Intelligence)

中立英雄可以自 Tavern 僱用(復活時則是在各種族的 Altar)。 也因此只有在《魔獸爭霸III:寒冰霸權》的地圖有 Tavern 這個建築,因為原作並沒有這個設計。

《魔獸爭霸III》中技能有主動與被動的分別。 舉例來說,Mountain King 的技能 Bash 有機會透過攻擊造成 25 點額外傷害並使對手昏迷 2 秒。 Blademaster 的技能 Critical Strike 是一種被動能力,可以給予更高的機率有更多的攻擊傷害。 Demon Hunter 的技能 Evasion 可以給予一定的機率閃避對方的攻擊。 Crypt Lord 的技能 Spiked Carapace 可以增強其防禦力並對敵人的近戰攻擊單位造成傷害。 Pandaren Brewmaster 的技能 Drunken Brawler 有一定機率避免攻擊,並且有 10% 機率造成額外傷害。 Pit Lord 的技能 Cleaving Attack 可以對多名敵人造成傷害。 Tinker 的技能 Engineering Upgrade 可以讓 Tinker 的其他能力都會提高,同時還會造成額外傷害並增加 Tinker 的移動速度。

靈氣 (Aura) 是被動能力的其中一種設計,是一種被動的能力,可以持續影響在範圍內的部隊。其中包含
Human - Paladin 的 Devotion Aura,Archmage 的 Brilliance Aura
Orc - Tauren Chieftain 的 Endurance Aura,Kodo Beast 的 War Drums Aura
Undead - Death Knight 的 Unholy Aura,Dread Lord 的 Vampiric Aura
Night Elf - Keeper of the Grove 的 Thorns Aura,Priestess of the Moon 的 Trueshot Aura
只有 Orc 的 Kodo Beast 並不是英雄,而是作戰單位。

每個英雄都有 3 個技能,以及到第 6 級可以學習終極招式。 以 Far Seer 來說,有 Chain Lightning, Far SightFeral Spirit 3 個技能,而 3 個技能都可以學習到第 3 級, Earthquake 則是其終極招式。而有些招式需要在原地維持不動一段時間施法(最著名的是 Priestess of the Moon 的終極招式 Starfall, 以及 Keeper of the Grove 的終極招式 Tranquility),可以使用一些方式中斷其施法。 下面是一些中斷的方式,例如 Mountain King 的技能 Storm Bolt, Tauren Chieftain 的技能 War Stomp,Shadow Hunter 的技能 Hex,Orc Raider 的技能 Ensnare, Keeper of the Grove 的技能 Entangling Roots,Druid of the Talon 的技能 Cyclone, Dreadlord 的技能 Sleep,Crypt Lord 的技能 Impale, Dark Ranger 的技能 Silence,Tinker 的技能 Cluster Rockets,Firelord 的技能 Soul Burn

有些技能(法術)可以用來移除部隊身上的增益法術,或者用來傷害召喚單位。 例如 Humans 的 Priest 其法術 Dispel Magic 可以移除目標區域部隊身上的所有增益法術,以及造成召喚單位 200 點傷害; Spell Breaker 的技能 Spell Steal 可以將敵方的正面增益法術偷取到友方的部隊上,以及將己方的負面增益法術轉移到敵方部隊。 Orcs 的 Shaman 的技能 Purge 可以移除目標身上的所有增益法術,造成目標移動速度降低,並且造成一個召喚單位 400 點傷害; Spirit Walker 的技能 Disenchant 可以移除目標區域部隊身上的所有增益法術,以及造成召喚單位 250 點傷害。 Night Elves 的 Dryad 的技能 Abolish Magic 可以移除友方部隊身上的負面增益法術,以及敵方部隊的正面增益法術,以及造成召喚單位 250 點傷害; Wisp 的技能 Detonate 以犧牲一個 Wisp 為代價,消除所有的增益法術並且在其附近的部隊吸取 50 點 Mana (1.32.9 改為 40 點),以及造成召喚單位 225 點傷害。 Undead 的 Banshee 的技能 Anti-magic Shell 可以創造一道屏障,阻止 300 點法術或魔法傷害影響目標單位。 Destroyer 的技能 Devour Magic 消耗區域內所有單位的所有正向和負向增益效果,每個被吞噬的單位都會使毀滅者恢復 50 點生命值和 75 點法力值, 可以對召喚單位造成 160 點傷害。 中立英雄 Pandaren Brewmaster 的終極招式 Storm, Earth, And Fire,其分身之一的 Storm,其中一個技能 Dispel Magic 可以 移除目標區域部隊身上的所有增益法術,以及造成召喚單位 200 點傷害。

2025/08/07

理財投資資訊

總論

定存

定存的第一個特性就是通常本金不會有損失(注意如果需要換匯,換匯以後本金仍然可能會有損失), 再來就是隨時可以解約,只是利息打折,而不需要任何解約賠償。 因此如果有一段時間後才需要使用的現金部位,那麼就可以考慮使用定存。 定存有其獨特的功能和特徵,其他的理財工具並無法完全取代。 不過定存會有無法擊敗通膨的問題,因此除非採用極為保守的理財策略,建議不要全部都使用定存。

債券

債券是一種債務工具,發行債券的目的是在預先指定的期間內透過向外借貸來籌集資金。發債機構一般會承諾在指定日期償還本金及利息。 市場或會將債券稱為“票據”,雖然名稱不同,但所指的是同一類債務工具。

造成債券價格的波動因素,就稱為風險。市場利率會造成債券價格波動,這稱為利率風險。發行機構的信用發生危機,也會造成價格波動,稱為信用風險。 如果是持有不同貨幣計價的債券而帶來的價格變動,則是匯率風險。

債券可根據其付息方式來區分:
  • 固定利率債券
  • 浮動利率債券
  • 次級債券
  • 可換股債券
  • 抗通脹證券
  • 零息債券

債券價格與利息之間存在典型的反向關係。即利率升高時,債券價格通常會下跌,反之亦然。 利率可說是債券市場最重要的觀察指標,一般的認知是「利率漲、債券跌;利率跌、債券漲」。 值得注意的是,並非所有類型的債券價格都與市場利率(如美國聯邦資金利率或公債殖利率)走反方向。公司債與高收益債比較不受利率攀升的影響, 因為利率走揚通常是經濟較為活絡的時期,企業反而因為經營環境改善,更能順利償還利息與本金,為投資人創造額外報酬。

債券與其他投資資產最大的不同在於,債券能夠提供高度穩定的收益,而對於使用同貨幣的人來說,唯一影響債券的只有利率的改變。 提升利率會造成債券有更高的殖利率以及較低的價格,也因此會造成資產虧損。而利率的改變會反應多少幅度在債券的價格, 則跟債券的存續期間(Duration)長短有關。

存續期間是比較兩個固定收益投資最重要的關鍵,而公式則是當利率提昇一個百分點,那麼債券的價格將下跌的百分點會與存續期間一致, 例如七年期債券會下跌 7%。而這個公式原則上是長期債券和短期債券都適用,但有一個假設是當升息的時候, 長期債券與短期債券所構成的殖利率曲線會平行遷移,也就是不管長債或短債,對利率改變有相同的殖利率變化。 不過實際上則並非如此,因為短期債券的殖利率的確深受利率升降的影響,而長期債券的殖利率則是反應市場對通膨預期。

當我們在評估債券市場潛在的風險時,思考債券為什麼可以降低股市高波動性所帶來的風險是很重要的。簡單來說, 債券投資人對升息產生恐懼是合理的,但是要瞭解的是債券的熊市與股市(或其他風險資產)的熊市是完全不同的。事實上, 股市下跌超過20%通常被定義為熊市,但對債券投資人來說,債券市場的熊市指的則是負報酬的情況。

而似乎有不少投資者認為,利率上升時,債券ETF的表現會遜於個別債券。當中的思維是只要持有個別債券至到期日,收益就不受利率升跌的影響。 而一般債券 ETF 不會到期,因此投資者無法避免利率上升帶來的損失。 一些投資者偏好個別債券多於互惠基金,是因為他們相信債券讓他們免受利率上升影響:即使利率上升導致債券價格下降, 他們依然可以選擇持有債券至到期日,收回預期的本金和利息。債券基金或ETF沒有預先定明的收益或本金,因此被視為對利率較敏感的產品。 許多投資者忽視的是債券收益固定,但債券基金或 ETF 的收益通常會在利率上升時增加。而這些增加的收入,往往能隨著時間補償利率上升初期的價格虧損。 也就是說,對於長期投資的投資人而言,債券 ETF 更能讓投資者分散債券的信貸風險,減少債券違約可能帶來的損失。 債券市場的交易成本高,規模大的債券 ETF 有助於降低交易時的費用,進而減少開支。

股、債還有一個很大的差異,那就是債券在價格下跌的時候也意味著更高的殖利率,但股票則不一定有這樣的關係存在,這是因為股票的價格不只受殖利率影響, 也受公司盈餘所影響,也就是股價有兩個影響因素。

投機等級債券為非投資等級,通常被歸類為垃圾債券 (Junk Bond),為了吸引投資者,通常有較高的殖利率。 垃圾債券的特性介乎股票與國債之間,無法為傳統的股債混合投資組合帶來分散投資的效益。而由於流動性欠佳, 在一些情況下垃圾債券更可能會有大幅下跌的情況。 垃圾債券除了跟股票、債券一樣都會受經濟增長、通脹等因素影響外,還多了流動性的風險。

經驗豐富的主動式基金經理有能力從低流動性的資產當中找出價格被低估的資產,從而獲得較高而且穩定的超額回報。 因此,如果投資者希望持有高收益債券資產,按照晨星的建議是選擇主動式管理的高收益債劵型基金,重點是要選對投資基金。 但是一般而言,使用者難以挑選出獲得較高而且穩定的超額回報的主動式基金,所以結論是對於一般較為保守的投資人而言不要投資高收益債劵型基金, 大部份投資者還是較適合投資於高評級的股票與債券。

股票

股票是一種有價證券,股份有限公司將其所有權藉由這種有價證券進行分配。 因為股份有限公司需要籌措長期資金,因此將股票發給投資者作為公司資本的部分所有權憑證, 成為股東以此獲得股利(股票股利)或/且股息(現金股利),並分享公司成長或交易市場波動帶來的利潤; 但也要共同承擔公司運作錯誤所帶來的風險。

GDP(Gross Domestic Product)就是國內生產毛額,指的是某一個經濟體(國家)在一特定時間內的經濟活動所創造出來的價值總和。

巴菲特提出了衡量目前市場情況的 GDP 理論。 根據 GDP 理論,大盤與 GDP 呈現相關的走向,由所有上市公司的市值,佔 GDP 的比重就可以知道目前市場的狀況。

巴菲特指標 = 股市總市值/GDP國民生產毛額
巴菲特指出,儘管這個比值並非萬能,卻可能是在特定時點,「衡量市場價位高低的最佳指標」。此一比值,若大幅降低, 代表企業產生的經濟價值,嚴重被低估,買進股票,會有不錯表現。反之,若如同 1999 年、2000 年的狀況, 急劇竄高,代表已經「名不副實」,是危險狀況(但此時的市場氣氛,往往也最樂觀)。

但是注意的是,巴菲特指標超過前高也不代表會立刻崩盤,股市的崩盤或者是修正有多種原因, 因此不能說超過前高就可能會發生崩盤。

房地產與 REITs

如果投資人對投資組合只有股票和債券兩種資產感到不足,可以考慮商品(Commodity)以及代表不動產的 REITs 作為資產配置的重要資產類別, 尤其這兩種較新的資產與股、債相關性均不高,因此也有助於整體投資組合的風險分散。

一般的投資人如果是要投資房地產,比較好的方法是使用 REITs。REITs 是一種不動產證券化商品,是受託機構以公開募集或私募方式, 交付受益證券,募集一筆資金,再投資不動產、不動產相關權利、不動產相關有價證券等。而證券化的不動產主要為辦公大樓、購物中心、倉庫等商業不動產為主。 運作方式是將不動產的所有權證券化,募集完成後將於在公開市場上購買,沒有最低額度限制, 投資人可以透過投資 REIT 來參與不動產市場。因為房地產的報酬與其它資產的相關性低,在投資組合裡加入 REITs,理論上可以降低整體的風險。

對 REITs 而言,基本的觀察項目為:

  1. 租金來源:承租率
  2. 標的穩定/成長性
  3. 標的風險分散性

不過台灣的 REITs 因為台灣本身的法規限制(只能採用信託制),所以產品缺乏多元性與成長性, 只有某些有避稅需求的人因為分離課稅的制度而可能投資,投資價值較低。

人一生的理財通常會有自住需求的問題。那麼何時是買房的時機?那就是,你有自住需求,已經準備好頭期款, 並且可以在不影響目前生活的情況下付得出貸款,那就是可以買房子的時候。對大多數人來說,買房子,特別是第一次買的房子, 那是要自用,而非投資的標的。 所以以自用的觀點出發,好好的篩選一間讓自己住的舒適,住得便利的房子,那就是很好的購屋計畫。 不是買了之後增值才是買了好屋。也不要再想買了之後房價的漲跌,因為它是買來用的。

期貨、選擇權和權證

期貨原本的用途是用來避險,但是發展到今日,已經成為比較投機的金融工具,這些金融產品都是零和遊戲,不建議散戶和一般投資人進行操作。 不論買賣期貨背後是出於甚麼原因,緊記期貨是槓桿式投資工具。槓桿效應既能使回報以倍數增大,但同樣亦能使損失以倍數遞增。 當然,如果是以 1 倍槓桿的方式用來避險,那麼期貨對投資人而言是一項有效的工具。

外匯

外幣交易的目的主要有二個,第一個是捕捉外幣的升值潛力及分散資產組合的風險,第二個是傳統對沖外匯眨值的工具。 對於台灣的投資者來說,主要有用的外國貨幣為美元(買賣的匯差理論上在各家銀行都是最小),再來是目前還未完全可以自由兌換的人民幣, 以及傳統上視為高息貨幣、波動度較大的原物料貨幣澳幣。

而外幣投資並不能以利息作為主要的考量點,而是要以是否有升值潛力作為最重要的考量,再來是持有該貨幣可以對沖本國貨幣貶值的風險。 因此,像是南非幣等本國財政出現赤字且波動過大的貨幣並不適合作為投資之用(也不適合作為投機的標的)。

美元指數(US Dollar Index,USDX)是通過平均美元與六種國際主要外匯的匯率得出的。美元指數顯示的是美元的綜合值,為衡量美元強弱的指標。


槓桿式外匯是一種利用「槓桿效應」而進行的投資。基本上,你以按金形式(俗稱「孖展」)買入一種外幣,並預期該外幣會相對於另一種貨幣轉強或轉弱。 最終盈虧將視乎你就指定的外幣合約開倉及平倉時的價格差別而定。

槓桿式外匯是以合約的方式進行交易。外幣的合約價值由你和你的中介人議定。 目前,最普遍買賣的外幣合約為歐元、英鎊、日圓、瑞士法郎及澳幣。 利潤及虧損是根據指定貨幣相對美元(或另一種貨幣)於開倉後的走勢而定。 在未平倉前,任何帳戶內的利潤或虧損均屬浮動性質,祇有當平倉時,利潤或虧損才會兌現。

槓桿式外匯投資並不適合散戶和一般投資人進行操作。

使用指數基金或者是 ETF

不論使用何者指標,都有泡沫破滅以後,人們才知道這是泡沫的問題。 因此如果是一般投資人要投資股票或者是建立股票與債券的長期投資組合, 建議選擇指數基金或者是追蹤指數的 ETF 並且長期投資。

如果你對一些個股真的非常熟悉,確定可以發揮自己在這個個股上的優勢,可以使用一定的資金比例投資在個股上, 不用硬性強迫自己一定要全部的資金都投資指數基金或者是追蹤指數的 ETF。或者是你有一些投資策略想要使用(例如長期持有並且分散在各種股票的投資組合), 只要你自己知道自己做什麼,就可以使用自己的投資策略。

注意:因為台灣公債長期利率偏低(甚至比定存還低,那我放定存就好)而且沒有相關的台灣公債 ETF, 所以因為台灣環境的關係,我會往美國公債或者是高等級的公司債 ETF 去尋找投資標的。 對於中國而言,我會建議中國政府應該引導基金公司遂步降低其費用(當然,作為交換,就是操作的時候選擇降低費用的 ETF,結果就是擴大其規模)。 再來就是,中國需要費用夠低的股債组合(股票以滬深三百指數 ETF 為主,債券以中國短期公債 ETF 為主, 當然債券最好也有中國中期公債或者是中國長期公債的選項),並且讓中國公民了解而且願意使用這方面的工具。

注意:按照中華民國(台灣)目前的稅制,海外營利所得依成分股來源地區區分為「大陸地區」與「大陸地區以外的海外地區」。 對於設籍中華民國並居住於台灣地區的個人,根據《台灣地區與大陸地區人民關係條例》的特別規定,大陸地區的所得需納入綜合所得稅申報與繳納, 營利所得也不例外,同時不是稽徵機關提供查詢的所得資料範圍,因此需要自行申報。 因此,如果是投資中國股票的 ETF,需要注意其分配收益的分類(還有要注意雖然是投資中國的 ETF,不代表所有收益都是從大陸地區配出, 要看 ETF 所投資個股的公司登記地)。至於海外地區收入,達 100 萬需要納入基本所得額並且申報,如果達 750 萬,課徵海外所得稅 20%。 就我個人而言,投資「大陸地區」的收益不論是股票或者是債券,在稅收方面十分麻煩,目前如果我確定我投資的標的有此收益項目我會直接放棄。 同時我會建議中華民國政府納入提供查詢的所得資料範圍並且不需要自行申報, 或者將「大陸地區」視為外國,跟海外地區一樣的管理方式,而不是像現在這樣掩耳盜鈴的方式。

注意:如果是設籍中華民國並居住於台灣地區的個人投資台灣上市上櫃股票, 以及投資產品中收益來源為「大陸地區」,若單次股利給付達 2 萬元(含)以上,需扣繳 2.11% 的二代健保補充保費, 且以單次給付上限 1,000 萬元為限。

台灣缺少全市場類型的 ETF,下面是追蹤上市大型股的 ETF:

  • 元大台灣50 (0050):投資台灣五十指數,其成分股涵蓋台灣證券市場中市值前五十大之上市公司。 競爭產品為富邦台50 (006208)

參考資料

2025/07/05

Beyond 中國音樂計畫

我沒有仔細查過目前中國的政策,有可能和實際狀況有出入,所以只是寫著玩的。不過也不可能有人會真的照做吧?所以就只是寫下想法。

這個計畫包含下列三個部份:

  1. 中國允許定調以後的六四學運資料出現在自身網路上
  2. 如果禁歌中有 Beyond 的部份,那麼就解禁(Beyond 全部的歌曲都可以聽到,並且成為接下來中國言論管制的底線)
  3. 強調 Beyond 的精神,也就是目前中國需要的部份:超越自我

第一點和 Beyond 有關的部份就是 Beyond 一些歌曲被認為與六四有關,所以第一步是解決六四運動的定位問題。 而我的答案也很簡單,避而不談是錯誤的,中國共產黨要做的是做出官方的定調,網路上能查到的資料就是中國政府 的定調版本。我的意思是,中國官方可以定調為一開始是中國學生為了追求民主而出現的學運,但是被境外敵對份子 滲透(其實就是美國)而加以利用,導致學運出現直接對抗政府並且無法停止的情況,以致於中國政府必須以強制的手 段中止學運。

第二點很簡單,Beyond 的全部歌曲都可以聽到。如果真的有疑慮,採用目前的做法,也就是沒問題的歌曲一般 人都可以聽到,如果真的有爭議的歌曲,在音樂平台上則採取只有登䤸後的 VIP 會員可以聽到的方法。

第三點就是目前中國需要的,也就是 Beyond 的建團精神。在1998年出版的樂隊自傳《擁抱Beyond歲月》中, 鼓手葉世榮解釋,由於樂隊喜愛自己創作,有別於當時其他樂隊多數翻唱外國樂隊的作品,故「Beyond」有超越一般 樂隊所涉足的音樂領域的意思,但葉世榮重申,Beyond 不是要超越他人,而是要超越自己。而藉由這個計畫,也鼓勵 中國音樂創作者在找出自己在音樂創作上的強項或者是舒適區以後,能夠嘗試更多不同的音樂流派以及曲調。

然後有可能會出現一些小混亂的情況,這時候不要急著又要禁掉 Beyond 的歌曲(我知道有些人就是蠢,所以還是先說 比較好),中國政府應該學著有方法和管道能夠正確的引導與論,如果這都無法做到,那麼很多事都只會事倍功半。

最後,我認為中國目前從上到下急迫需要的是思考周密成熟的官員,觀察以前中國的政策(包含文化大革命和生育管制的一胎化政策), 都會有為了解決一個問題,結果產生新的問題的狀況。在施政這麼多年以後,我想中國政府也應該有一批有能力的官員了, 所以重點就是需要思慮周密而且又能夠施行政策,在全盤思考目前的中國的問題以後改善目前的情況。

2025/03/25

C++ Thread

Pthreads

POSIX Threads 是 POSIX 的執行緒標準,定義了建立和操控執行緒的一套API。

Process 和 Threads 之間的不同點:

  • Process:
    A process is a program placed in memory or running with all the run-time environment (or all the resources) associated with it.
  • Thread:
    A thread is a portion or part of the process and the smallest sequential unit of instructions processed independently by the scheduler of the operating system.
    It is simply an execution or processing unit composed of a set of instructions contained in the process.

Process 之間的資源是隔離的,而同一個 Process 內的 Thread 之間的記憶體資源是共用的,所以使用 Thread 需要小心的處理全域變數, 需要使用互斥鎖(Mutex)等完成執行緒之間的同步管理。 除了共同的記憶體,執行緒區域儲存區(Thread Local Storage,TLS) 可以讓執行緒有私人的資料儲存區,讓執行緒可以儲存各自執行緒的資料。

Pthreads API 全都以 "pthread_" 開頭,並可以分為四類:

  • 執行緒管理,例如建立執行緒,等待(join)執行緒,查詢執行緒狀態等。
  • 互斥鎖(Mutex):建立、摧毀、鎖定、解鎖、設定屬性等操作
  • 條件變數(Condition Variable):建立、摧毀、等待、通知、設定與查詢屬性等操作
  • 使用了互斥鎖的執行緒間的同步管理

下面是使用的例子:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static void wait(void) {
    time_t start_time = time(NULL);

    while (time(NULL) == start_time) {
        /* do nothing except chew CPU slices for up to one second */
    }
}

static void *thread_func(void *vptr_args) {
    int i;

    for (i = 0; i < 20; i++) {
        fputs("  b\n", stderr);
        wait();
    }

    return NULL;
}

int main(void) {
    int i;
    pthread_t thread;

    if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
        return EXIT_FAILURE;
    }

    for (i = 0; i < 20; i++) {
        puts("a");
        wait();
    }

    if (pthread_join(thread, NULL) != 0) {
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

建立執行緒的函式如下:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

執行緒屬性 pthread_attr_t 可以設定 __detachstate,表示新執行緒是否與行程中其他執行緒脫離同步。 如果設定為 PTHREAD_CREATE_DETACHED,則新執行緒不能用 pthread_join() 來同步,且在退出時自行釋放所占用的資源。 預設為 PTHREAD_CREATE_JOINABLE 狀態。也可以先建立執行緒並執行以後用 pthread_detach() 來設定。 一旦設定為 PTHREAD_CREATE_DETACHED 狀態,不論是建立時設定還是執行時設定,都不能再恢復到 PTHREAD_CREATE_JOINABLE 狀態。

C++ Thread

自 C++11 開始,C++ 標準函式庫提供了 Thread library。

下面就是一個使用的例子。

#include <iostream>
#include <thread>

void myfunc() { std::cout << "At myfunc..." << std::endl; }

int main() {
    std::thread t1(myfunc);

    std::this_thread::sleep_for(std::chrono::seconds(1));

    t1.join();
    return 0;
}

參考連結

2025/03/09

C++ 學習筆記

C++ 設計原則

Bjarne Stroustrup 博士在 20 世紀 80 年代在貝爾實驗室工作期間發明並實現了 C++。 一開始的想法可以追溯到 1979 年,起初這種語言被稱作「C with Classes」,作為 C 語言的增強版出現。 C++ 在 C 的基礎上增加功能,並且儘量與 C 的相容。 C++ 比起其它語言有巨大優勢的地方,就是可以直接使用 C 的函式。

C++ 編譯器自由軟體的主要實作為 GNU Compiler Collection (GCC) 與 Clang

C++ 是一個通用的語言,抽象資料型別為 C++ 的核心概念, 含有一些系統程式領域的特性,並且期望能夠達到下列的目標:

  • is a better C
  • supports data abstraction
  • supports object-oriented programming
  • supports generic programming
在《C++語言的設計和演化》(1994)中,Bjarne Stroustrup 描述了他在設計C++時,所使用的一些原則。
  • C++ 設計成靜態類型、和 C同樣高效率且可移植的多用途程式設計語言。
  • C++ 設計成直接的和廣泛的支援多種程式設計風格。
  • C++ 設計成給程式設計者更多的選擇,即使可能導致程式設計者選擇錯誤。
  • C++ 設計成盡可能與 C 相容,籍此提供一個從 C 到 C++ 的平滑過渡。
  • C++ 避免平臺限定或沒有普遍用途的特性。
  • C++ 不使用會帶來額外開銷的特性。
  • C++ 設計成無需複雜的程式設計環境。

但是,C++ 標準並沒有規範 Object Model 的實作方式,同時 C++ 也缺乏 ABI 的標準, 因此在 Windows Platform 上各家編譯器所產出的 DLL 很難互通,這是 C++ 在 binary level 上的缺點。


下面是一個 C 的 Hello World 程式:

#include <stdio.h>

int main() {
   /* my first program in C */
   printf("Hello, World! \n");

   return 0;
}

In a C program, the semicolon is a statement terminator. That is, each individual statement must be ended with a semicolon. It indicates the end of one logical entity.

C++標準表頭檔沒有副檔名,因為副檔名的命名規則隨各編譯器而有所不同。 下面是 C++ 版的 Hello World:

#include <iostream>

int main() {
    std::cout << "Hello! World!\n";

    return 0;
}

下面是一個範例,使用者在命令列輸入一個字串,然後程式計算字串 MD5 的值並且輸出:

//
// g++ test.cpp -std=c++17 -lcrypto
//
#include <cstring>
#include <string>
#include <iostream>
#include <openssl/md5.h>

std::string MD5(const std::string &src)
{
    MD5_CTX ctx;

    std::string md5_string;
    unsigned char md[16] = {0};
    char tmp[3] = {0};

    MD5_Init(&ctx);
    MD5_Update(&ctx, src.c_str(), src.size());
    MD5_Final(md, &ctx);

    for (int i = 0; i < 16; ++i)
    {
        memset(tmp, 0x00, sizeof(tmp));
        snprintf(tmp, sizeof(tmp), "%02X", md[i]);
        md5_string += tmp;
    }

    return md5_string;
}

int main(int argc, char *argv[])
{
    if (argc == 1)
    {
        std::cout << "Please give a string." << std::endl;
    }
    else
    {
        std::string mystring = argv[1];
        std::cout << "String: " << mystring << std::endl;
        std::cout << "Result: " << MD5(mystring) << std::endl;
    }
    return 0;
}

下面是一個範例,使用者在命令列輸入一個字串,然後程式計算字串 SHA256 的值並且輸出:

//
// g++ test.cpp -std=c++17 -lcrypto
//
#include <cstring>
#include <string>
#include <iostream>
#include <openssl/sha.h>

std::string SHA256(const std::string &src)
{
    SHA256_CTX ctx;

    std::string sha256_string;
    unsigned char md[32] = {0};
    char tmp[3] = {0};

    SHA256_Init(&ctx);
    SHA256_Update(&ctx, src.c_str(), src.size());
    SHA256_Final(md, &ctx);

    for (int i = 0; i < 32; ++i)
    {
        memset(tmp, 0x00, sizeof(tmp));
        snprintf(tmp, sizeof(tmp), "%02X", md[i]);
        sha256_string += tmp;
    }

    return sha256_string;
}

int main(int argc, char *argv[])
{
    if (argc == 1)
    {
        std::cout << "Please give a string." << std::endl;
    }
    else
    {
        std::string mystring = argv[1];
        std::cout << "String: " << mystring << std::endl;
        std::cout << "Result: " << SHA256(mystring) << std::endl;
    }
    return 0;
}

Date types

C++ 中基本的資料型態主要區分為「整數」(Integer)、「浮點數」(Float)、「字元」(Character),而這幾種還可以細分:

  • 整數:用 來表示整數值,可以區分為 short、int 與 long,可容納的大小各不相同,short的長度為半個 word,int 表示一個 word, 而 long 可能是一個或兩個 word(要看採用的 data model),在 32 位元機器上 int 與 long 的長度通常是相同的, 型態的長度越長,表示可表示的整數值範圍越大。 如果是 64 位元的機器 (64-bit computing), 大多數的 UNIX 系統在 64 位元採用 LP64 data model,這時候 long 就會是 8 bytes。 而 Windows 64 位元採用 LLP64 這個 data model,這時候 long 的大小仍然還是 4 bytes,也就是差異出現在 long 這個型別上。
  • 浮點數:用來表示小數值,可以區分為 float、double 與 long double,float 的長度為一個 word,double 的長度為二個 word, long double 長度為 3 或 4 個word。
  • 字元:用來儲存字元,長度為 1 個位元組,其字元編碼主要依 ASCII 表而來,由於字元在記憶體中所佔有的空間較小, 所以它也可以用來儲存較小範圍的整數。

以上的資料型態在記憶體中所佔有的大小依平台系統而有所差異,word 的大小取決於機器,在 32 位元機器上通常一個 word 是 4 個位元組, 如果想要知道這些資料型態在所使用的平台上所佔有的記憶體空間有多少,最好的作法是使用 sizeof() 運算子,取得確實的記憶體大小。

在 C11 標準中,建議包括 stdint.h 程式庫(亦包含在 C++ 的標準函式庫), 使用 int8_tint16_tint32_tint64_tuint8_tuint16_tuint32_tuint64_t 等作為整數型態的宣告,以避免平台相依性的問題。

有時候我們需要表示非十進位的數字(例如八進位或者十六進位)。 在 C 其八進位通常以「0」開頭(注意是數字 0),例如 0640;而十六進位通常以「0x」或「0X」開頭,例如 0xEF 或 0XEF; 而二進位通常以「0b」開頭,例如 0b1。

要注意的是,如果是需要精確求值的場合,那麼需要考慮使用 big number library 來實作,而不是使用浮點數。 有些程式語言(例如 Tcl、Common Lisp 等)直接支援大整數運算,無需顯式地使用 API。 使用浮點數有兩個最根本的問題:輸入與儲存的值不一定精確計算的結果會有誤差

另外,電腦的浮點數常用二進位或十六進位運算與儲存,所以在程式中的十進位數需要轉換為二進位或十六進位, 但是一個簡單的十進位數卻可能轉換成無限位的二進位或十六進位數,而儲存的位置是有限的, 算出來的結果就不夠精確,結果也可能受到四捨五入誤差的影響,如果再用來計算其它值,誤差就會愈滾愈大。


There are two kinds of expressions in C −

  • lvalue − Expressions that refer to a memory location are called "lvalue" expressions. An lvalue may appear as either the left-hand or right-hand side of an assignment.
  • rvalue − The term rvalue refers to a data value that is stored at some address in memory. An rvalue is an expression that cannot have a value assigned to it which means an rvalue may appear on the right-hand side but not on the left-hand side of an assignment.

Constants refer to fixed values that the program may not alter during its execution. These fixed values are also called literals.

Constants can be of any of the basic data types like an integer constant, a floating constant, a character constant, or a string literal.

There are two simple ways in C to define constants −

  • Using #define preprocessor.
  • Using const keyword.

Given below is the form to use #define preprocessor to define a constant −

#define identifier value

The following example explains it in detail −

#include <stdio.h>

#define LENGTH 10
#define WIDTH  5
#define NEWLINE '\n'

int main() {
   int area;

   area = LENGTH * WIDTH;
   printf("value of area : %d", area);
   printf("%c", NEWLINE);

   return 0;
}

You can use const prefix to declare constants with a specific type as follows −

const type variable = value;

The following example explains it in detail −

#include <stdio.h>

int main() {
   const int  LENGTH = 10;
   const int  WIDTH = 5;
   const char NEWLINE = '\n';
   int area;

   area = LENGTH * WIDTH;
   printf("value of area : %d", area);
   printf("%c", NEWLINE);

   return 0;
}

Macros in C and C++ are tokens that are processed by the preprocessor before compilation. Each instance of a macro token is replaced with its defined value or expression before the file is compiled. Macros are commonly used in C-style programming to define compile-time constant values. However, macros are error-prone and difficult to debug. In modern C++, you should prefer constexpr variables for compile-time constants:

#define SIZE 10 // C-style
constexpr int size = 10; // modern C++

constexpr 可以說是 C++11 對 const 修飾字的加強。 常數表達式 (constant expression) 代表的是可以在編譯時期經過固定確定運算得到確切值的表達式。


A storage class defines the scope (visibility) and life-time of variables and/or functions within a C Program. They precede the type that they modify. We have four different storage classes in a C program −

  • auto
  • register
  • static
  • extern

The auto storage class is the default storage class for all local variables.

{
   int mount;
   auto int month;
}

The register storage class is used to define local variables that should be stored in a register instead of RAM.

{
   register int  miles;
}

The static storage class instructs the compiler to keep a local variable in existence during the life-time of the program instead of creating and destroying it each time it comes into and goes out of scope. Therefore, making local variables static allows them to maintain their values between function calls.

The extern storage class is used to give a reference of a global variable that is visible to ALL the program files. When you use 'extern', the variable cannot be initialized however, it points the variable name at a storage location that has been previously defined.


Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.

You can initialize an array in C either one by one or using a single statement as follows −

double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};

If you omit the size of the array, an array just big enough to hold the initialization is created. Therefore, if you write −

double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};

A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before using it to store any variable address.

#include <stdio.h>

int main () {

   int  var = 20;   /* actual variable declaration */
   int  *ip;        /* pointer variable declaration */

   ip = &var;  /* store address of var in pointer variable*/

   printf("Address of var variable: %x\n", &var  );

   /* address stored in pointer variable */
   printf("Address stored in ip variable: %x\n", ip );

   /* access the value using the pointer */
   printf("Value of *ip variable: %d\n", *ip );

   return 0;
}

It is always a good practice to assign a NULL value to a pointer variable in case you do not have an exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned NULL is called a null pointer.

Arrays are not pointers! Arrays look like pointers, and pointers can refer to array objects. For example, people sometimes think that char s[] is identical to char *s. But they aren’t identical. The array declaration char s[12] requests that space for 12 characters be set aside, to be known by the name s. The pointer declaration char *p, on the other hand, requests a place that holds a pointer, to be known by the name p. This pointer can point to almost anywhere: to any char, to any contiguous array of chars, or frankly nowhere.


參考(Reference)是 C++ 新增加的語言特性,為物件的別名(Alias),也就是替代名稱,對參考名稱存取時該有什麼行為, 都參考了來源物件該有的行為,在 C++ 中,「物件」這個名詞,不單只是指類別的實例,而是指記憶體中的一塊資料。

要定義參考,是在型態關鍵字後加上 & 運算子,例如:

int n = 10;
int *p = &n;
int &r = n;

上面的程式中,最後一行定義參考。參考一定要初始化,否則無法通過編譯。 與指標 (pointer) 不同,參考在初始化之後不能參照不同的物件,或設為 null,也因此參考一般而言比指標安全。


C 並沒有為 String 定義一個型別,字串在 C 語言中是一個以 null character '\0' 為結尾的一維陣列。 這讓 C 的字串需要小心的處理。

如果要在 C 進行字串串接,可以使用 asprintf,雖然是 GNU 自行擴充的 function,但是使用上很方便。

#define _GNU_SOURCE
#include <stdio.h>

下面則是使用的例子:

char *s;
asprintf(&s,"hello,%s","-Reader-");
printf("%s\n",s);
if (s) free(s);

C++ 在這一點則有所改變,加入了 std::string 作為字串物件類別。


Arrays allow to define type of variables that can hold several data items of the same kind. Similarly structure is another user defined data type available in C that allows to combine data items of different kinds.

To define a structure, you must use the struct statement. The struct statement defines a new data type, with more than one member. The format of the struct statement is as follows −

struct [structure tag] {

   member definition;
   member definition;
   ...
   member definition;
} [one or more structure variables];

The structure tag is optional and each member definition is a normal variable definition, such as int i; or float f; or any other valid variable definition. At the end of the structure's definition, before the final semicolon, you can specify one or more structure variables but it is optional. Here is the way you would declare the Book structure −

struct Books {
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

An enum is a special type that represents a group of constants (unchangeable values).

下面是一個 enum 的例子:

enum Level {
  LOW,
  MEDIUM,
  HIGH
}; 

下面就是宣告變數並且初始化的例子:

enum Level myVar = MEDIUM;

「Scoped and strongly typed enums」是 C++11 時所引進的一個新的功能,主要是要取代舊的列舉型別(enum)。 基本用法是在 enum 後面,再加上 class 或 struct;而要使用定義的值的時候,一定要加上範圍(scope、在這裡就是指 class 的名稱)。

enum class EColor
{
    RED,
    GREEN,
    BLUE
};

EColor eColor = EColor::RED;

另外,在 C++11 開始,不管是 enum 或 enum class,也都可以指定實際要使用的型別。

enum class EColor : char
{
  RED,
  GREEN,
  BLUE
};

A union is a special data type available in C that allows to store different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time. Unions provide an efficient way of using the same memory location for multiple-purpose.

To define a union, you must use the union statement in the same way as you did while defining a structure. The union statement defines a new data type with more than one member for your program. The format of the union statement is as follows −

union [union tag] {
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables];

The union tag is optional and each member definition is a normal variable definition, such as int i; or float f; or any other valid variable definition. At the end of the union's definition, before the final semicolon, you can specify one or more union variables but it is optional. Here is the way you would define a union type named Data having three members i, f, and str −

union Data {
   int i;
   float f;
   char str[20];
} data;

Now, a variable of Data type can store an integer, a floating-point number, or a string of characters. It means a single variable, i.e., same memory location, can be used to store multiple types of data. You can use any built-in or user defined data types inside a union based on your requirement.

The memory occupied by a union will be large enough to hold the largest member of the union. For example, in the above example, Data type will occupy 20 bytes of memory space because this is the maximum space which can be occupied by a character string.


The declaration of a bit-field has the following form inside a structure −

struct {
   type [member_name] : width ;
};

The variables defined with a predefined width are called bit fields. A bit field can hold more than a single bit; for example, if you need a variable to store a value from 0 to 7, then you can define a bit field with a width of 3 bits as follows −

struct {
   unsigned int age : 3;
} Age;

The C programming language provides a keyword called typedef, which you can use to give a type a new name. Following is an example to define a term BYTE for one-byte numbers −

typedef unsigned char BYTE;

You can use typedef to give a name to your user defined data types as well. For example, you can use typedef with structure to define a new data type and then use that data type to define structure variables directly as follows −

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

typedef struct Books {
   char title[50];
   char author[50];
   char subject[100];
   int book_id;
} Book;

int main( ) {

   Book book;

   strcpy( book.title, "C Programming");
   strcpy( book.author, "Nuha Ali");
   strcpy( book.subject, "C Programming Tutorial");
   book.book_id = 6495407;

   printf( "Book title : %s\n", book.title);
   printf( "Book author : %s\n", book.author);
   printf( "Book subject : %s\n", book.subject);
   printf( "Book book_id : %d\n", book.book_id);

   return 0;
}

The C Preprocessor is not a part of the compiler, but is a separate step in the compilation process. In simple terms, a C Preprocessor is just a text substitution tool and it instructs the compiler to do required pre-processing before the actual compilation. We'll refer to the C Preprocessor as CPP.

All preprocessor commands begin with a hash symbol (#). It must be the first nonblank character, and for readability, a preprocessor directive should begin in the first column.

ANSI C defines a number of macros.

#include <stdio.h>

int main() {

   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );

}

The token-pasting operator (##) within a macro definition combines two arguments. It permits two separate tokens in the macro definition to be joined into a single token. For example −

#include <stdio.h>

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   tokenpaster(34);
   return 0;
}

A header file is a file with extension .h which contains C function declarations and macro definitions to be shared between several source files. There are two types of header files: the files that the programmer writes and the files that comes with your compiler.

You request to use a header file in your program by including it with the C preprocessing directive #include, like you have seen inclusion of stdio.h header file, which comes along with your compiler.

Including a header file is equal to copying the content of the header file but we do not do it because it will be error-prone and it is not a good idea to copy the content of a header file in the source files, especially if we have multiple source files in a program.

A simple practice in C or C++ programs is that we keep all the constants, macros, system wide global variables, and function prototypes in the header files and include that header file wherever it is required.

If a header file happens to be included twice, the compiler will process its contents twice and it will result in an error. The standard way to prevent this is to enclose the entire real contents of the file in a conditional, like this −

#ifndef HEADER_FILE
#define HEADER_FILE

the entire header file file

#endif

Control flow

C 語言用來判斷條件的 statement 有二個,ifswitch。 另外還有條件運算子 ? : 這個運算子。

Exp1 ? Exp2 : Exp3;

C 語言迴圈包含了 while, fordo ... while 等三種迴圈。


Write a program that displays the digits from 1 to n then back down to 1; for instance, if n = 5, the program should display 123454321. You are permitted to use only a single for loop. The range is 0 < n < 10.

首先是使用 switch 來解:

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

int main(int argc, char *argv[]) {
    int n = 0;

    if (argc >= 2) {
        n = atoi(argv[1]);
    } else {
        fprintf(stderr, "Please give a number.\n");
        return 1;
    }

    if (n < 1 || n > 9) {
        fprintf(stderr, "Out of range.\n");
        return 1;
    }

    switch (n) {
    case 1:
        printf("1\n");
        break;
    case 2:
        printf("121\n");
        break;
    case 3:
        printf("12321\n");
        break;
    case 4:
        printf("1234321\n");
        break;
    case 5:
        printf("123454321\n");
        break;
    case 6:
        printf("12345654321\n");
        break;
    case 7:
        printf("1234567654321\n");
        break;
    case 8:
        printf("123456787654321\n");
        break;
    case 9:
        printf("12345678987654321\n");
        break;
    default:
        printf("Please input 0 < n < 10\n");
        break;
    }

    return 0;
}

接下來,改為使用 while 的版本:

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

int main(int argc, char *argv[]) {
    int n = 0;

    if (argc >= 2) {
        n = atoi(argv[1]);
    } else {
        fprintf(stderr, "Please give a number.\n");
        return 1;
    }

    if (n < 1 || n > 9) {
        fprintf(stderr, "Out of range.\n");
        return 1;
    }

    int positive = 1;
    int count = 0;
    while (1) {
        if (positive == 1) {
            count++;
            printf("%d", count);
            if (count == n) {
                positive = 0;
                continue;
            }
        } else {
            count--;
            if (count > 0) {
                printf("%d", count);
            } else {
                break;
            }
        }
    }
    printf("\n");

    return 0;
}

C++ 的控制結構大致上與 C 相同,在 C++11 增加了以範圍為基礎的 for 陳述式。

#include <iostream>

int main() {

    for (int i : {1, 2, 3}) {
        std::cout << i << std::endl;
    }

    return 0;
}

Function

函式 (Function) 的組成主要包括四個部份:返回值、函式名稱、參數列與函式主體。前三者稱為函式宣告或函式原型(Function prototype), 在 C++ 中規定,如果函式是在 main 之後實作,必須在 main 之前進行宣告,否則會出現編譯錯誤。

如果函式不傳回任何值,則宣告為 void,若不傳入任何引數,參數列保持空白即可,雖然也可以使用 void 來加以註明, 要注意的是 void 註明參數列不使用為是 C 的風格,而在 C++ 中,參數列空白就表示這個函式不接受任何引數。

在含入標頭檔時,若標頭檔與含入標頭檔的文件在同一目錄,就使用雙引號 " " 來包括標頭檔名稱,如果是標準或專案專屬的標頭檔,例如 C++ 的標準表頭檔,那麼使用角括號 < > 來括住,編譯器在尋找時就會從設定的目錄尋找。

下面是 C 語言對函式的參數沒有固定數目時的方法。

#include <stdio.h>
#include <stdarg.h>

double average(int num,...) {

   va_list valist;
   double sum = 0.0;
   int i;

   /* initialize valist for num number of arguments */
   va_start(valist, num);

   /* access all the arguments assigned to valist */
   for (i = 0; i < num; i++) {
      sum += va_arg(valist, int);
   }

   /* clean memory reserved for valist */
   va_end(valist);

   return sum/num;
}

int main() {
   printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
   printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

C 語言在 <stdlib.h> 定義了關於記憶體管理的函式,例如 malloc, realloc 與 free。

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

int main() {

   char name[100];
   char *description = NULL;

   strcpy(name, "Zara Ali");

   /* allocate memory dynamically */
   description = (char *) malloc( 200 * sizeof(char) + 1);

   if( description == NULL ) {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   } else {
      strcpy( description, "Zara ali a DPS student in class 10th");
   }

   printf("Name = %s\n", name );
   printf("Description: %s\n", description );

   /* Free memory */
   if(description) free(description);
}

下面是人類猜數字的小遊戲:

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

int getA(char *ans, char *guess) {
  int len1 = 0;
  int len2 = 0;
  int count = 0;

  len1 = strlen(ans);
  len2 = strlen(guess);

  if (len1 != len2) {
    return 0;
  }

  for (int i = 0; i < len1; i++) {
    if (ans[i] == guess[i]) {
      count++;
    }
  }

  return count;
}

int getB(char *ans, char *guess) {
  int len1 = 0;
  int len2 = 0;
  int count = 0;

  len1 = strlen(ans);
  len2 = strlen(guess);

  if (len1 != len2) {
    return 0;
  }

  for (int i = 0; i < len1; i++) {
    for (int j = 0; j < len2; j++) {
      if (i != j) {
        if (ans[i] == guess[j]) {
          count++;
        }
      }
    }
  }

  return count;
}

int main() {
  int answer = 1;
  char ans[5];
  char guess[5];
  int avalue = 0;
  int bvalue = 0;

  srand(time(0));

  while (1) {
    answer = (int)(rand() % 9999);
    sprintf(ans, "%04d", answer);

    if (ans[0] != ans[1] && ans[0] != ans[2] && ans[0] != ans[3] &&
        ans[1] != ans[2] && ans[1] != ans[3] && ans[2] != ans[3]) {
      break;
    }
  }

  while (1) {
    printf("Please input your guess: ");
    scanf("%s", guess);
    avalue = getA(ans, guess);
    bvalue = getB(ans, guess);
    printf("Result: A = %d, B = %d\n", avalue, bvalue);

    if (avalue == 4 && bvalue == 0) {
      printf("Game is completed.\n");
      break;
    }

    printf("\n");
  }
}

下面是電腦猜數字的小遊戲:

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

int getA(char *ans, char *guess) {
  int len1 = 0;
  int len2 = 0;
  int count = 0;

  len1 = strlen(ans);
  len2 = strlen(guess);

  if (len1 != len2) {
    return 0;
  }

  for (int i = 0; i < len1; i++) {
    if (ans[i] == guess[i]) {
      count++;
    }
  }

  return count;
}

int getB(char *ans, char *guess) {
  int len1 = 0;
  int len2 = 0;
  int count = 0;

  len1 = strlen(ans);
  len2 = strlen(guess);

  if (len1 != len2) {
    return 0;
  }

  for (int i = 0; i < len1; i++) {
    for (int j = 0; j < len2; j++) {
      if (i != j) {
        if (ans[i] == guess[j]) {
          count++;
        }
      }
    }
  }

  return count;
}

int main() {
  int count = 0;
  int index = 0;
  char **total;
  char **total_new;
  char **newtotal;
  char ans[5];
  int avalue = 0;
  int bvalue = 0;

  total = (char **)malloc(sizeof(char *) * 5040);
  if (!total) {
    printf("Malloc failed.\n");
    return 0;
  }

  for (int i = 0; i <= 9; i++) {
    for (int j = 0; j <= 9; j++) {
      for (int k = 0; k <= 9; k++) {
        for (int m = 0; m <= 9; m++) {
          if (i != j && i != k && i != m && j != k && j != m && k != m) {
            char buffer[5] = {0};
            sprintf(buffer, "%d%d%d%d", i, j, k, m);
            total[count] = (char *)malloc(sizeof(char) * 5);
            strcpy(total[count], buffer);
            count++;
          }
        }
      }
    }
  }

  while (1) {
    if (count == 0) {
      printf("Something is wrong.\n");
      break;
    }

    strcpy(ans, total[0]);
    printf("My answer is %s.\n", ans);
    printf("The a value is: ");
    scanf("%d", &avalue);
    printf("The b value is: ");
    scanf("%d", &bvalue);

    if (avalue == 4 && bvalue == 0) {
      printf("Game is completed.\n");
      break;
    }

    index = 0;
    newtotal = (char **)malloc(sizeof(char *) * count);
    for (int i = 0; i < count; i++) {
      int aguess = 0;
      int bguess = 0;
      aguess = getA(total[i], ans);
      bguess = getB(total[i], ans);

      if (aguess == avalue && bguess == bvalue) {
        newtotal[index] = (char *)malloc(sizeof(char) * 5);
        strcpy(newtotal[index], total[i]);
        index++;
      }
    }

    total_new = (char **)realloc(total, sizeof(char *) * index);
    if (!total_new) {
        printf("Realloc failed.\n");
        break;
    }
    total = total_new;

    for (int i = 0; i < index; i++) {
      strcpy(total[i], newtotal[i]);
    }

    for (int i = 0; i < index; i++) {
      if (newtotal[i]) {
        free(newtotal[i]);
      }
    }
    if (newtotal) {
      free(newtotal);
    }

    count = index;
    printf("\n");
  }

  for (int i = 0; i < count; i++) {
    if (total[i])
      free(total[i]);
  }

  if (total) {
    free(total);
  }
}

realloc 的行為要特別注意,如果失敗會傳回 NULL,但是原本配置的記憶體並不會釋放!所以需要特別處理。

C++ Class

變數(Variable)提供一個有名稱的記憶體儲存空間,一個變數關係至一個資料型態,一個變數本身的值與一個變數的位址值。 變數資料型態決定了變數所分配到的記憶體大小;變數本身的值是指儲存於記憶體中的某個數值,而您可以透過變數名稱取得這個數值, 這個數值又稱為 rvalue或 read value;而變數的位址值則是指變數所分配到的記憶體之位置,變數本身又稱為lvalue或 location value。

由於 C++ 的演化來自 C,在 C++ 中的術語物件和 C 語言一樣是意味著記憶體區域,而不是類別實體。在 class 中,有兩大成員,一是資料(data member),一是行為(member function)。

C++ 使用 new 和 delete 來建立和刪除物件,
string *stringPtr1 = new string;
delete stringPtr1;
下面是另外一個形式:
string *stringPtr1 = new string[100];
delete [] stringPtr1;
C++ 的 new 運算子和 C 的 malloc 函式都是為了要配置記憶體,但是 new 不但配置物件所需的記憶體空間,同時會引發建構式的執行。

雖然 new 運算子看起來是單一運算,但是包含了二個動作:
  1. 透過適當的 new 運算子函式實體,配置所需的記憶體(new 運算子配置所需的記憶體實作上幾乎都是以標準的 C malloc() 來完成,正如 delete 運算子是以 C free() 來完成)
  2. 將所配置的物件設立初值

Brace initialization

It is not always necessary to define a constructor for a class, especially ones that are relatively simple. Users can initialize objects of a class or struct by using uniform initialization, as shown in the following example:

// no_constructor.cpp
// Compile with: cl /EHsc no_constructor.cpp
#include <time.h>

// No constructor
struct TempData
{
    int StationId;
    time_t timeSet;
    double current;
    double maxTemp;
    double minTemp;
};

// Has a constructor
struct TempData2
{
    TempData2(double minimum, double maximum, double cur, int id, time_t t) :
       stationId{id}, timeSet{t}, current{cur}, maxTemp{maximum}, minTemp{minimum} {}
    int stationId;
    time_t timeSet;
    double current;
    double maxTemp;
    double minTemp;
};

int main()
{
    time_t time_to_set;

    // Member initialization (in order of declaration):
    TempData td{ 45978, time(&time_to_set), 28.9, 37.0, 16.7 };

    // Default initialization = {0,0,0,0,0}
    TempData td_default{};

    // Uninitialized = if used, emits warning C4700 uninitialized local variable
    TempData td_noInit;

    // Member declaration (in order of ctor parameters)
    TempData2 td2{ 16.7, 37.0, 28.9, 45978, time(&time_to_set) };

    return 0;
}

Note that when a class or struct has no constructor, you provide the list elements in the order that the members are declared in the class. If the class has a constructor, provide the elements in the order of the parameters. If a type has a default constructor, either implicitly or explicitly declared, you can use default brace initialization (with empty braces).

For example, the following class may be initialized by using both default and non-default brace initialization:

#include <string>
using namespace std;

class class_a {
public:
    class_a() {}
    class_a(string str) : m_string{ str } {}
    class_a(string str, double dbl) : m_string{ str }, m_double{ dbl } {}
double m_double;
string m_string;
};

int main()
{
    class_a c1{};
    class_a c1_1;

    class_a c2{ "ww" };
    class_a c2_1("xx");

    // order of parameters is the same as the constructor
    class_a c3{ "yy", 4.4 };
    class_a c3_1("zz", 5.5);
}

If a class has non-default constructors, the order in which class members appear in the brace initializer is the order in which the corresponding parameters appear in the constructor, not the order in which the members are declared (as with class_a in the previous example).

靜態變數與函式

static 成員變數不屬於物件的一部份,而是類別的一部份,所以可以在沒有建立任何物件的情況下就處理 static 成員變數。而且即使 static 成員變數的權限為 private,設定 static 成員變數初值時,不受任何存取權限的束縛。

static 成員函式和 static 成員變數一樣,可以在沒有建立任何物件的情況下就被呼叫執行。 而之所以可以在未建立任何物件的情況下就被呼叫執行, 是因為編譯器不會為它暗自加上一個 this 指標, 也因為缺少 this 指標,static 成員函式無法處理類別之中的 non-static 成員變數。

C++ Object Model

Stroustrup 所設計的 Model:

  • Nonstatic data members 被配置在每一個 class object 之內
  • static data members 被配置在個別的 class object 之外
  • function members 被配置在個別的 class object 之外
  • 每一個 class 產生出指向 virtual functions 的指標,放在表格中(virtual table)。 每一個 class object 都被安插一個指標,指向相關的virtual table。
  • 為了支援 RTTI,會在 virtual table 的第一個 slot 插入型別資訊

多型的實現方式很複雜,大致上是編譯器或 VM 在資料結構內加入一個資料指標,此指標通常稱爲 vptr,是 Virtual Table Pointer 的意思。vptr 指向一個 Virtual Table,此 Virtual Table 是一個陣列 (array),由許多函數指標所組成,每個函數指標各自指向一個函數的地址。不管是 C++ 編譯器、或是 Java VM、或是 .NET CLR,內部都是以此方式來實現多型。

C++ Object Model 提供了有效率的執行時期支援,再加上與 C 之間的相容性,造成了 C++ 的流行。但是因為 Object Layout (物件大小、每一個非虛擬的 member)在編譯時間就已經固定下來,在 binary level 上阻礙了使用的彈性。

C++:封裝(Encapsulation)

資訊隱藏的意義在於將物件的實際內容除非有必要,否則最好將實際內容隱藏在介面裡。

C++ 的存取等級分為 public, protected, private 三種,把資料宣告為 private,只能透過特定的介面來操作,這就是物件導向的封裝(encapsulation)特性。

C++:繼承 (Inherit)

繼承:讓使用者藉由在已經有的類別上,加入新成員(資料或者是函式來定義新的類別,而不必重新設計。

C++ 的繼承分為三種情況:

  • Public
  • Protected
  • Private

成員函式有一個隱藏參數,名為 this 指標(代表著物件自己),因此可以知道所應喚起的函式。

C++ 多型支援:虛擬函式

對物件導向的程式語言來說,在繼承關係發生的同時,子類別可能會去覆寫父類別的函式。因此在所謂「多型」的機制下, 就無法在編譯時期決定要呼叫的究竟是那個函式,也就是到了執行時期才決定要呼叫的究竟是那一個函式(所引申的意義,就是多型的前提是繼承, 只有繼承才有多型行為的產生)。

物件導向的三個特色:封裝、繼承、多型,其中最重要的多型,C++ 是靠繼承和動態繫結(Dynamic binding)達成, 「虛擬函式」可以實現「執行時期」的多型支援,是一個「動態繫結」, 也就是指必須在執行時期才會得知所要調用的物件或其上的公開介面,以相同的指令卻喚起了不同的函式,也就是「一種介面,多種用途」。

如果 C++ 沒有虛擬函式,如果以一個「基礎類別之指標」指向一個「衍生類別之物件」, 那麼使用此指標就只能夠呼叫基礎類別(而不是衍生類別)所定義的函式。C++ 透過指標或參考來支援多型,以 Virtual function 來達到多型的實現, Virtual function 在基底類別中使用關鍵字 virtual 宣告,並在衍生類別中重新定義虛擬函式。 多型與動態繫結只有在使用指標或參考時才得以發揮它們的特性。

虛擬函式可以實現執行時期的「多型」,一個含有虛擬函式的類別被稱為「多型的類別」(Polymorphic class), 當一個基底類別型態的指標指向一個含有虛擬函式的衍生類別,您就可以使用這個指標來存取衍生類別中的虛擬函式。

class Window // Base class for C++ virtual function example
{
  public:
  virtual void Create() // virtual function for C++ virtual function example
  {
    cout <<"Base class Window"<<endl;
  }
};

class CommandButton : public Window
{
  public:
  void Create()
  {
    cout<<"Derived class Command Button - Overridden C++ virtual function"<<endl;
  }
};

void main()
{
  Window  *x, *y;

  x = new Window();
  x->Create();

  y = new CommandButton();
  y->Create();
}

如果沒有宣告為 virtual 的話,CommandButton 所呼叫的 Create() 仍然為 base class 所定義的 Create(),但是宣告為 virtual function 之後,將會視所使用的指標型別而決定要喚起的函式,因此將可以增加使用上的彈性。

純虛擬函式 (Pure Virtual Function)

C++ 提供「純虛擬函式」(Pure virtualfunction),它的存在只是為了在衍生類別中被重新定義,指明某個函式只是提供一個介面, 要求繼承的子類別必須重新定義該函式。

class Work {
  public:
    // pure virtual function
    virtual void doJob() = 0;
};

一個類別中如果含有純虛擬函式,則該類別為一「抽象類別」(Abstract class), 該類別只能被繼承,而不能用來直接生成實例,如果直接產生實例會發生編譯錯誤。

final specifier and override specifier

C++11 標準提供了對虛擬函式更好的表達方式。

final specifier specifies that a virtual function cannot be overridden in a derived class or that a class cannot be inherited from. 如果設定為 final,就表示這就是最後一個覆寫的 virtual function。

struct Base
{
    virtual void foo();
};

struct A : Base
{
    void foo() final; // A::foo is overridden and it is the final override
    void bar() final; // Error: non-virtual function cannot be overridden or be final
};

struct B final : A // struct B is final
{
    void foo() override; // Error: foo cannot be overridden as it's final in A
};

struct C : B // Error: B is final
{
};

override specifier specifies that a virtual function overrides another virtual function. 也就是用來指定是否可以覆寫 virtual function。

struct A
{
    virtual void foo();
    void bar();
};

struct B : A
{
    void foo() const override; // Error: B::foo does not override A::foo
                               // (signature mismatch)
    void foo() override; // OK: B::foo overrides A::foo
    void bar() override; // Error: A::bar is not virtual
};

對於 C++ 而言,因為其設計哲學是「任何特性在不使用的時候,絕對不增加程式的負擔」,所以在不使用虛擬特性的時候,就不會增加呼叫時的負擔。與 Java 這些內建使用動態繫結的語言不同,C++ 比較偏向使用靜態繫結,只有在使用 Virtual 關鍵字時才具有動態繫結的能力,因此與其說 C++ 是一個物件導向語言,不如說是支援物件導向的 Template based 語言。

Templates

Templates are parametrized by one or more template parameters, of three kinds: type template parameters, non-type template parameters, and template template parameters.

C++ 所提供的 template 機制,就是將目標物的資料型別參數化

下面是一個 template 的例子:

template <class T>
inline const T& max(const T& a, const T& b)
{
  return a < b ? b : a;
}

一旦程式以指定引數的方式,確定了型別之後,編譯器便自動針對這個(或這些)型別產生出一份實體。 針對目標物之不同,C++ 支援 function templates 和 class templates 兩大類型, 而後者的 members 又可以是 templates(所謂 member templates),帶來極大的彈性與組合空間。

「由編譯器產生出一份實體」的動作,我們稱之為具現化(instantiation)。由於  Template 具現化的行為是在編譯時期完成,所以愈複雜的 templates,就會需要愈多的編譯時間。然而 template 卻不會影響到執行時間,因此對於程式的執行效率仍然得以保障。

C++ 泛型編程的中心思考是 Template,運算子多載也為 C++ 泛型編程帶來了幫助, 讓我們得以用看起來行為像函式的 Function Object (函式物件, or Functor)寫出更有彈性的程式。 Standard Template Library 是 C++ 泛型編程開花結果之後所帶來的成品,讓我們得以享用這些高編程品質的函式庫。

Templates 是 C++ 支援泛型的重要關鍵。

template<typename To, typename From> To convert(From f);

void g(double d)
{
    int i = convert<int>(d); // calls convert<int,double>(double)
    char c = convert<char>(d); // calls convert<char,double>(double)
    int(*ptr)(float) = convert; // instantiates convert<int, float>(float)
}

關鍵字:typename

C++ 引進了 typename 關鍵字,用來指定 template 內的標識符號為一種型別。 C++ 的規則是,除非用 typename 修飾,template 內的標識符號都會被視為一個實值 (value) 而不是型別。

Parameter pack (since C++11)

A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments.

A template with at least one parameter pack is called a variadic template.

template<class ... Types> struct Tuple {};
Tuple<> t0;           // Types contains no arguments
Tuple<int> t1;        // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error;       // error: 0 is not a type

A variadic function template can be called with any number of function arguments (the template arguments are deduced through template argument deduction):

template<class ... Types> void f(Types ... args);
f();       // OK: args contains no arguments
f(1);      // OK: args contains one argument: int
f(2, 1.0); // OK: args contains two arguments: int and double

A pattern followed by an ellipsis, in which the name of at least one parameter pack appears at least once, is expanded into zero or more comma-separated instantiations of the pattern, where the name of the parameter pack is replaced by each of the elements from the pack, in order.

template<class ...Us> void f(Us... pargs) {}
template<class ...Ts> void g(Ts... args) {
    f(&args...); // “&args...” is a pack expansion
                 // “&args” is its pattern
}
g(1, 0.2, "a"); // Ts... args expand to int E1, double E2, const char* E3
                // &args... expands to &E1, &E2, &E3
                // Us... pargs expand to int* E1, double* E2, const char** E3

Type casting

Type casting is a way to convert a variable from one data type to another data type. For example, if you want to store a 'long' value into a simple integer then you can type cast 'long' to 'int'. You can convert the values from one type to another explicitly using the cast operator as follows −

(type_name) expression

Consider the following example where the cast operator causes the division of one integer variable by another to be performed as a floating-point operation −

#include <stdio.h>

main() {

   int sum = 17, count = 5;
   double mean;

   mean = (double) sum / count;
   printf("Value of mean : %f\n", mean );
}

Type conversions can be implicit which is performed by the compiler automatically, or it can be specified explicitly through the use of the cast operator. It is considered good programming practice to use the cast operator whenever type conversions are necessary.

因為更重視型別安全的關係,除了上面 C 語言風格的型別轉換, C++ 加入了 static_castdynamic_castconst_castreinterpret_cast 四種 cast。

static_cast 執行於編譯時期,功能與 C-Style cast 相似,但更安全,可以避免不合理的型別轉換。

float f = 3.5;
int n1 = static_cast<int>(f);

為了支援執行時期的型態轉換動作,C++ 提供了dynamic_cast 用來將一個基底類別的指標轉型至衍生類別指標, 稱之為「安全向下轉型」(Safe downcasting),它在執行時期進行型態轉換動作,首先會確定轉換目標與來源是否屬同一個類別階層, 接著才真正進行轉換的動作,檢驗動作在執行時期完成,如果是一個指標,則轉換成功時傳回位址,失敗的話會傳回 0, 如果是參考的話,轉換失敗會丟出 bad_cast例外。

#include <iostream> 
#include <typeinfo> 
using namespace std; 

class Base { 
public: 
    virtual void foo() = 0;
}; 

class Derived1 : public Base { 
public: 
    void foo() { 
        cout << "Derived1" << endl; 
    } 
 
    void showOne() {
        cout << "Yes! It's Derived1." << endl;
    }
}; 

class Derived2 : public Base { 
public: 
    void foo() { 
        cout << "Derived2" << endl; 
    } 
 
    void showTwo() {
        cout << "Yes! It's Derived2." << endl;
    }
}; 

void showWho(Base &base) {
    try {
        Derived1 derived1 = dynamic_cast<Derived1&>(base);
        derived1.showOne();
    }
    catch(bad_cast) {
        cout << "bad_cast 轉型失敗" << endl;
    }
}

int main() { 
    Derived1 derived1;
    Derived2 derived2; 

    showWho(derived1);
    showWho(derived2);
 
    return 0;
}

const_cast 的用途是移除 const 的屬性。除非真的有需要,否則不應該使用。

const int a = 10;
const int *ptr = &a;
int *cc = const_cast<int *>(ptr);
*cc = 99;

reinterpret_cast 用途是強制轉換型別,不論資料大小是否相同。

int number = 10;
// Store the address of number in numberPointer
int* numberPointer = &number;

// Reinterpreting the pointer as a char pointer
char* charPointer
    = reinterpret_cast<char*>(numberPointer);

Exception

如果要在 C++ 中實作例外狀況 (exception) 處理,使用 trythrowcatch 運算式。 開發者需要使用 try 包住可能會發生例外的程式碼區段(也就是使用 throw 丟出例外狀況的程式碼), 在 catch 處理這個 try 區域所發生的例外,並且 catch 裡面的 exception 變數應該要用 reference 的方式。 另外,如果在 catch 拿到例外狀況無法即時處理而需要丟給更上層的 try ... catch 處理,可以使用 throw 重新丟出一個例外狀況。

下面是一個例外狀況處理的例子。

#include <iostream>
#include <vector>
#include <exception>

int main()
{
    std::vector<int> v = {1,2,3};
    try {
        std::cout << v.at(0) << std::endl;
        std::cout << v.at(1) << std::endl;
        std::cout << v.at(2) << std::endl;
        std::cout << v.at(3) << std::endl;
    } catch (std::exception &e) {
        std::cout << "exception: " << e.what() << std::endl;
    }

    return 0;
}

C++ 並不支援 finally,因為 C++ 可以使用 RAII(Resource Acquisition Is Initialization), 也就是物件銷毀的時候也關閉或移除其使用的資源。

Namespace

C++ 可以使用 namespace 來定義名稱空間(或者開啟既存的名稱空間),例如,可以在 account.h 中定義 bank 名稱空間:

#include <string>

namespace bank {
    using namespace std; 

    class Account { 
    private:
        string id;  
        string name; 
        double balance;

    public: 
        Account(string id, string name, double balance);
        void deposit(double amount);
        void withdraw(double amount);
        string to_string() const;
    };
}

在使用上,可以在 account.cpp 可以開啟 bank 名稱空間,並在其中實作類別定義:

#include "account.h"

namespace bank {
    using namespace std;

    Account::Account(string id, string name, double balance) {
        this->id = id;
        this->name = name;
        this->balance = balance;
    }

    string Account::to_string() const {
        return string("Account(") + 
            this->id + ", " +
            this->name + ", " +
            std::to_string(this->balance) + ")";
    }
    
    // ...
}

或者是在實作時指定 bank 範疇:

bank::Account::Account(string id, string name, double balance) {
    this->id = id;
    this->name = name;
    this->balance = balance;
}

string bank::Account::to_string() const {
    return string("Account(") + 
           this->id + ", " +
           this->name + ", " +
           std::to_string(this->balance) + ")";
}

名稱空間會是類別名稱的一部份,因此在使用時,必須包含 bank 前置; 或者是使用 using 來指明使用哪個名稱空間,例如:

using namespace std;
using namespace bank;

using 也可用來導入某個名稱,例如僅導入 std::string、std:cout:

#include <iostream>
#include <string>
using std::string;

int main() {
    string str = "Example";
    using std::cout;
    cout << str;
}

C++ 其實並不建議使用 using,因為這樣如果程式碼如果大到一定規模,可能會出現命名衝突的問題。

C++ 11 Lambda Expression

Lambda expression 在 C++ 中可以視為是一種匿名函數的表示方式,它可以讓程式設計師將函數的內容直接以 inline 的方式寫在一般的程式碼之中, 使用時機跟 functor 與 function pointer 類似,一般的狀況都是使用 lambda expression 定義一個匿名的函數, 然後再將此函數當作另外一個函數的傳入參數來使用。

基本的用法如下:
[=] (int x) mutable throw() -> int
{
  // 函數內容
  int n = x + y;
  return n;
}
[=]:lambda-introducer,也稱為 capture clause。
所有的 lambda expression 都是以它來作為開頭,不可以省略,它除了用來作為 lambda expression 開頭的關鍵字之外,也有抓取(capture)變數的功能,指定該如何將目前 scope 範圍之變數抓取至 lambda expression 中使用,而抓取變數的方式則分為傳值(by value)與傳參考(by reference)兩種,跟一般函數參數的傳入方式類似,不過其語法有些不同,以下我們以範例解釋:
  • []:只有兩個中括號,完全不抓取外部的變數。
  • [=]:所有的變數都以傳值(by value)的方式抓取。
  • [&]:所有的變數都以傳參考(by reference)的方式抓取。
  • [x, &y]x 變數使用傳值、y 變數使用傳參考。
  • [=, &y]:除了 y 變數使用傳參考之外,其餘的變數皆使用傳值的方式。
  • [&, x]:除了 x 變數使用傳值之外,其餘的變數皆使用傳參考的方式。

這裡要注意一點,預設的抓取選項(capture-default,亦即 = 或是 &)要放在所有的項目之前,也就是放在第一個位置。

(int x):lambda declarator,也稱為參數清單(parameter list)。
定義此匿名函數的傳入參數列表,基本的用法跟一般函數的傳入參數列表一樣,不過多了一些限制條件:
  • 不可指定參數的預設值。
  • 不可使用可變長度的參數列表。
  • 參數列表不可以包含沒有命名的參數。

參數清單在 lambda expression 中並不是一個必要的項目,如果不需要傳入任何參數的話,可以連同小括號都一起省略。

mutable:mutable specification。
加入此關鍵字可以讓 lambda expression 直接修改以傳值方式抓取進來的外部變數,若不需要此功能,則可以將其省略。
throw():例外狀況規格(exception specification)。
指定該函數會丟出的例外,其使用的方法跟一般函數的例外指定方式相同。如果該函數沒有使用到例外的功能,則可以直接省略掉。
-> int:傳回值型別(return type)。
指定 lambda expression 傳回值的型別,這個範例是指定傳回值型別為整數(int),其他的型別則以此類推。如果 lambda expression 所定義的函數很單純,只有包含一個傳回陳述式(statement)或是根本沒有傳回值的話,這部分就可以直接省略,讓編譯器自行判斷傳回值的型別。
mutable:compound-statement,亦稱為 Lambda 主體(lambda body)。
這個就是匿名函數的內容,就跟一般的函數內容一樣。

下面是一個最簡單的 Hello World 範例。

#include <iostream>

using namespace std;
int main() {
  auto lambda = []() { cout << "Hello, Lambda" << endl; };
  lambda();
}

再來是 Trailing Zero-Bits 的解法:

/*
 * Trailing Zero-Bits
 * Given a positive integer, count the number of trailing zero-bits in its binary
 * representation. For instance, 18 = 10010, so it has 1 trailing zero-bit,
 * and 48 = 110000, so it has 4 trailing zero-bits.
 */
#include <iostream>

int main(void)
{
    int number = 0;

    auto lambda = [](int num) -> int {
        int count = 0;
        while((num & 1) == 0) {
            count++;
            num = num >> 1;
        }

        return count;
    };

    std::cout << "Please input a number: ";
    std::cin >> number;
    if (std::cin.fail()) {
        std::cout << "It is not a number." << std::endl;
        return 1;
    }

    if (number <= 0) {
        std::cout << "Number requires > 0." << std::endl;
    } else {
        std::cout << lambda(number) << std::endl;
    }
    return 0;
}

也可以在參數列加上 void,明確標示沒有傳入參數,並將傳回值的類型設為 void,明確標示這個函數沒有傳回值:

auto lambda = [](void) -> void { cout << "Hello, Lambda" << endl; };
下面的例子是直接呼叫 lambda expression 所定義的匿名函數,將兩個參數傳入其中進行運算,最後再將運算結果傳回來:
#include <iostream>

int main() {
  using namespace std;
  int n = [] (int x, int y) { return x + y; }(5, 4);
  cout << n << endl;
}

C++ 標準程式庫中有許多的函數在使用時會需要其他的函數作為傳入參數,最常見的就是一些對於陣列的處理函數, 這個例子是 std::count_if 最簡單的使用方式:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

bool condition(int value) {
  return (value > 5);
}

int main() {
  vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };

  auto count = count_if(numbers.begin(), numbers.end(), condition);
  cout << "Count: " << count << endl;
}

這裡我們定義一個 condition 函數,作為 std::count_if 在判斷元素時的依據,std::count_if 會將每個元素一一傳入 condition 函數中檢查, 最後傳回所有符合條件的元素個數。

由於 std::count_if 所使用到的判斷函數都需要另外定義,這樣會讓程式碼顯得很冗長, 我們可以使用 lambda expression 改寫一下,讓整個程式碼更簡潔:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
int main() {
  vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };

  auto count = count_if(numbers.begin(), numbers.end(),
    [](int x) { return (x > 5); });
  cout << "Count: " << count << endl;
}

我們將原本 condition 函數所在的位置,直接使用一個 lambda expression 替換,至於傳入的參數與傳回值的類型則維持不變(傳入 int,傳回 bool)。

C++ 11 Automatic Type Deduction and decltype

In C++03, you must specify the type of an object when you declare it. Yet in many cases, an object’s declaration includes an initializer. C++11 takes advantage of this, letting you declare objects without specifying their types:
auto x=0; //x has type int because 0 is int
auto c='a'; //char
auto d=0.5; //double
auto national_debt=14400000000000LL;//long long
Automatic type deduction is chiefly useful when the type of the object is verbose or when it’s automatically generated (in templates). Consider:
void func(const vector<int> &vi)
{
    vector<int>::const_iterator ci=vi.begin();
}
而在 C++11,現在可以這樣使用:
auto ci = vi.begin();
C++11 offers a similar mechanism for capturing the type of an object or an expression. The new operator decltype takes an expression and “returns” its type:
const vector<int> vi;
typedef decltype (vi.begin()) CIT;
CIT another_const_iterator;

C++11 也支援了 Range-based for loop,並且支援 auto 的使用,下面是一個九九乘法表的範例:

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> x = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<int> y = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    for (auto& nx: x) {
        for (auto& ny: y) {
            int z = nx * ny;
            std::cout << nx << " x " << ny << " = " << z << std::endl;
        }
    }
}

在 C++14,則可以結合 Lambda Expression 與 auto 的使用,下面是一個範例:

#include <iostream>
#include <vector>
#include <string>
#include <numeric>

int main()
{
  std::vector<int> ivec = { 1, 2, 3, 4};
  std::vector<std::string> svec = { "red",
                                    "green",
                                    "blue" };
  auto adder  = [](auto op1, auto op2){ return op1 + op2; };
  std::cout << "int result : "
            << std::accumulate(ivec.begin(),
                               ivec.end(),
                               0,
                               adder )
            << "\n";
  std::cout << "string result : "
            << std::accumulate(svec.begin(),
                               svec.end(),
                               std::string(""),
                               adder )
            << "\n";
  return 0;
}
下面就是執行的結果:
int result : 10
string result : redgreenblue

IO Stream

C++ comes with libraries that provide us with many ways for performing input and output. In C++ input and output are performed in the form of a sequence of bytes or more commonly known as streams.

  • Input Stream: If the direction of flow of bytes is from the device(for example, Keyboard) to the main memory then this process is called input.
  • Output Stream: If the direction of flow of bytes is opposite, i.e. from main memory to device( display screen ) then this process is called output.

The stream-based input/output library is organized around abstract input/output devices. These abstract devices allow the same code to handle input/output to files, memory streams, or custom adaptor devices that perform arbitrary operations (e.g. compression) on the fly.

Most of the classes are templated, so they can be adapted to any basic character type. Separate typedefs are provided for the most common basic character types (char and wchar_t).

C++ 提供了 stream 的方式來看待輸出與輸入。下面的範例是讓使用者輸入 A 與 B 以後,輸出相加的數字:

#include <iostream>

int main()
{
    int a = 0, b = 0;

    std::cout << "Please input the name a: ";
    std::cin >> a;

    std::cout << "Please input the name b: ";
    std::cin >> b;

    std::cout << "The sum is " << a+b << "." << std::endl;
}

下面是從 /etc/os-release 讀取內容,然後取得 Linux Distribution Name 的範例:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#ifdef _WIN32
   #include <io.h>
   #define access    _access_s
#else
   #include <unistd.h>
#endif

#ifdef ENABLE_STD
   #include <filesystem>
#endif

using namespace std;

/*
 * Using access function to check file exist or not
 */
bool FileExists( const string &Filename )
{
    return access( Filename.c_str(), 0 ) == 0;
}

/*
 * Split incoming string and return a vector
 */
vector<string> split(const string& str, const string& delim)
{
    vector<string> tokens;
    size_t prev = 0, pos = 0;
    do
    {
        pos = str.find(delim, prev);
        if (pos == string::npos) pos = str.length();
        string token = str.substr(prev, pos-prev);
        if (!token.empty()) tokens.push_back(token);
        prev = pos + delim.length();
    } while (pos < str.length() && prev < str.length());

    return tokens;
}

/*
 * get Linux distributed name: use /etc/os-release file
 */
string getListributedName()
{
    string name = "";

#ifdef ENABLE_STD
    std::filesystem::path p("/etc/os-release");
    if(std::filesystem::exists(p)) {
#else
    if(FileExists("/etc/os-release")==true) {
#endif
        ifstream releasefile("/etc/os-release");
        string line;

        if (releasefile.is_open()) {
            while ( getline (releasefile, line) )
            {
                auto splitArray = split(line, "=");

                if(splitArray[0].compare("NAME")==0) {
                   name =  splitArray[1];
                   break;
                }
            }

            releasefile.close();
       }
    }

    return name;
}


int main(int argc, char *argv[])
{
    string name = getListributedName();
    std::cout << name << std::endl;
}

C++17 加入了 Filesystem library,提供了對於 files 與 directories 的操作。

編譯:
g++ getDistributionName.cpp -std=c++17 -o getDistributionName

如果要配合 C++ standard library:
g++ getDistributionName.cpp -std=c++17 -o getDistributionName -DENABLE_STD

參考資料

2024/12/20

戰神:狂神天威3

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

(注意: Unofficial patch 1.03.24 與 1.03.25 分別由不同的團隊修改與維護!因此需要將二者的討論分開。)

可以參考的資料:

Overview

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

由於英雄的等級與技能會在戰役後持續保留,因此在等級不同的情況下會有不公平或者是平衡的問題。 遊戲提供了 Freeze your hero's level 的選項,在進行多人連線時通常會講好英雄的等級(例如 50 級的英雄), 在相同等級的情況下競技。

三代故事建立在 Dark Elf 嘗試召喚 Daemon Lord,而因為如此有 Four Horsemen 進入 Etheria 世界。 其中代表瘟疫的 Lord Antharg 創造了 Plaguelord,代表戰爭的 Lord Sartek 創造了 Minotaur, 代表饑荒的 Lord Melkor 創造了 The Swarm,代表死亡的 Lord Bane 創造了 Undead。 其中 Minotaur 為 Neutral alignment,其餘三者為 Evil alignment。 Campaign 劇情故事就是主角發現有第五個 Daemon Lord、也就是代表毀減的 Lord Gorgon 進入這個世界, 主角走遍 Etheria 世界,在知道 Lord Gorgon 無法被毀滅以後,最後封印 Fifth Horseman 的故事。

在 Campaign 中,有七個地方完成任務以後可以僱用一些助力成為英雄隨從 (Retinue) , 包含 Ragnar's Pass 的 Ragnar (the Frost Dragon), Theira 完成 Troll Hunt 任務(並且有機會成為 Knight 的盟友)以後,可以僱用 Prince Henrik (Knight); Daros 完成 Barbarian 的挑戰任務以後可以僱用 Warlord, Twilight Woods 幫助 Fey 以後可以僱用 Unicorn, 在完成護送 High Elf 的 Queen 到 Lurarion 的任務以後可以僱用 Moonguard, 在完成 Hand of Sartek Bonus 以後可以在 Realms of War 僱用 Minotaur King, 以及在 White Mountains 如果是 Dwarf 的友好方或者是完成 Griffon Raid 的任務取得 Griffon Eggs Bonus 以後可以僱用 Griffon (注意: White Mountains 任務會降低 Dwarf 對你的 diplomatic scores,即使是 Dwarf 英雄也會下降)。 而 Siria 的 Temple of Sirian 可以僱用 Archon,以及在 Elenia 可以僱用 Squire

在 Campaign 中有幾個地方是可以使用錢(遊戲中稱為 Crowns)來換取一些英雄的經驗值,包含完成任務以後的 Twilight Woods 與 Lurarion, 以及 Siria。

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

《戰神:狂神天威》系列採用 5 級科技樹,主堡最高為第 5 級。如果地圖沒有特別設定,各種族的主堡都具有轉化 (Convert) 的能力。 和一般遊戲不同,玩家需要使用英雄或者是具有轉化 (Convert) 能力的單位轉化資源為己方的資源,而後才開始有收入。

一般而言,等級愈高的主堡就會提供愈高的 Army Limit, 而 Army Limit 也可以透過建造建築而增加(通常是 +2,但是也有 +1、+3 與 +4 的建築)。 而有些種族則對於 Army Limit 有額外的支援。Empire 可以在 Granary 研發 Supply(共有 4 級,效果是 +5, +10, +15, +20)。 Barbarian 可以在 Chieftain's Hut 研發 Horde(共有 9 級,效果是 +5, +10, +15, +20, +25, +30, +35, +40, +50)。 Dark Dwarf 可以建造 Supply Depot 來 +3 Army Limit。 Orc 可以建造 Hovel 來 +3 Army Limit。

英雄具有轉化 (Convert) 以及建造主要建築的能力。 在一開始的時候玩家需要轉化資源以及建立主堡,因此除非是在劇情中 No buildings 的角色扮演模式, 否則在遊戲戰役一開始選擇需要攜帶的人員時,就需要攜帶一些工人或者是 builders 才行。

而能夠建造所有建築的工人 builder 是否生產自主堡,則是各個種族有其不同的設計。 舉例來說,EmpireKnight 有共同的工人 Peasant,BarbarianMinotaur 有共同的工人 Thrall, Fey 的工人為 Oakman,Orc 的工人為 Kobold,Daemon 的工人為 Quasit, High ElfWood ElfDark Elf 的工人為 Wisp,都是生產自主堡, 差別在於三個 Elf 種族其工人 Wisp 無法進入礦產挖礦加快資源的收入,而其它種族的工人可以。 而 Dwarf 的工人 Smith,Ssrathi 的工人 Chameleon,Dark Dwarf 的工人 Engineer, The Swarm 的工人 Giant Ant,PlaguelordUndead 的工人 Zombie 則並非生產自主堡。

Tower 是每個種族用來鞏固基地或地圖上某個位置的主要防禦工事。英雄無法建造 Tower,因此必須由工人或者是 builders 建造。 Tower 可以在其中駐紮 (garrison) 一些單位。但並非所有單位都能駐紮。 在可以駐紮的單位中,普通步兵可以分別增加塔樓 3 點戰鬥力和 1 點攻擊速度。一個英雄相當於兩個普通單位。 如果你駐紮一個遠程攻擊單位,塔樓的傷害力將增加 10 點,射程將增加 1 點。 你可以根據需要混合使用遠程單位和近戰步兵來獲得所需的屬性。 作為獎勵,駐紮的英雄擁有雙倍 health regeneration,所以這是快速恢復生命值低的英雄的一種方法。

整個遊戲的戰鬥可以區分為近戰 (melee) 和遠程 (ranged) 二種類型。 Combat 是遊戲中兩個或多個單位進行近戰時所使用的主要屬性,也是整個戰鬥系統的第一步。 Combat 用於確定一個單位的攻擊是否能夠命中、輕微命中、致命一擊、造成致命一擊或未命中另一個單位。

在遊戲中的 Speed 可以分為二種,一種是移動速度 (Movement Speed),一種是攻擊速度 (Attack Speed)。 移動速與各個單位的 Speed 屬性數值有關;英雄的攻擊速度與他們的 dexterity 數值有關, 而如果不是英雄,那麼攻擊速度與士氣 (Morale) 有關。

遊戲中物理傷害類型有三種,PiercingCrushingSlashing,而其中 Slashing 是最常見的類別(主要與劍和斧頭有關)。 元素傷害類型有三種,FireColdElectric。 最後,還有不是物理傷害與元素傷害類型的 Magic 類型,是一種獨特的類型。 Armor 可以降低來自物理傷害類型 (Piercing, Slashing and Crushing) 與 Resistance 可以降低來自 元素傷害類型 (Fire, Cold and Electric) 的傷害,Magic Resistance 則是降低 Magic 類型的部份。

在遊戲中有二種疾病 (Illnesses)和四種被稱為精神效果 (psyche effects) 的狀態,這些都使用相同的機制, 因此一個單位在同一時間不能擁有超過一種精神效果或超過一種疾病。但是,一個單位可以同時擁有一種精神效果和一種疾病。 二種疾病分別為 PoisonDisease,如果在這個狀態下會防止 HP regeneration 並且緩慢的扣除生命值。 四種精神效果的狀態分別為 Fear, Terror, ChaosAwe

遊戲中有態度 (Attitude) 的設計,可以決定單位在戰鬥和地圖上的行為和 AI 設定。 這些不同的態度 (Attitude) 允許玩家控制單一單位的行動,例如它們是否自動施法、守衛或追擊敵人。 舉例來說,可以設定一些單位的態度為 Guardian 或者是 Magic Guardian,用來守護其它的單位(例如英雄), 或者將法師設定為 Magic Defender,讓法師在一些情況下會使用法術。

每個種族都有設計其將軍 (general),通常在第五級主堡的時候可以生產(有例外的例子,White Mage 在第四級主堡就可以生產), 為各個種族具有轉化 (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)。

另外,遊戲還有終極單位 Titan 的設計, Titan 是可以與高等級英雄旗鼓相當的作戰單位,每場戰役只能夠生產一位, 在第五級主堡並且達成條件的時候可以生產,每個種族都有自己獨特的 Titan 單位。

Races

可玩的種族有 16 種:

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

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

Empire 是一個全面的種族,具有對騎兵有攻擊加成的初階步兵 Pikeman,普通但是也沒有特別弱勢的弓箭手 Archer, 三種法師 (White Mage, Red Mage, Black Mage),只要有錢就能很快生產的騎兵 Mercenary, 以及新的騎兵兵種 Elephant,並且高階步兵 Halberdier 一樣對騎兵有攻擊加成。 Catapult 與 Battering Ram 則是 Empire 的攻城武器。 Pikeman 與 Halberdier 這二者的差別主要在物理傷害類型不同,Pikeman 使用 Piercing,而 Halberdier 使用 Slashing。 White Mage 是十分有用的輔助單位,除了轉化 (Convert) 能力還具有 Cure 以及 Group Healing 技能。 Empire 的初階飛行單位 Eagle 具有建造建築的能力。 Griffon 是 Empire 的高階飛行單位。 Palace GuardRoyal GuardImperial Guard 是用來加強 Pikeman 與 Halberdier 的研發項目。 MysticismAdvanced Mysticism 是法師相關的研發,在 Library 開發,都可以 Mana 最大值增加 15。 Empire 有個要注意的點,如果要生產騎兵單位 Mercenary, 最好先在三級主堡才能夠建造的 Archway 研發 Fame 降低其生產成本以後再生產。 Empire 在 Quartermaster 的研發 Foreign Mercenary 有趣的點是僱用的傭兵是隨機的,也就是玩家無法知道會出現什麼助力。 因為有 White Mage 可以醫療的關係,所以可以嘗試戰士類的英雄職業,例如 Warrior。 雖然 Empire 的英雄種族天賦有 Wealth,但 Empire 在建造或者是升級 Palace 時,除了最高等級並非以 Gold 而是使用 Metal 為主要使用資源, 因此只有以 Mercenary 作為主力時才需要大量的 Gold,那麼有 Wealth 技能的 Merchant 是最好的選擇; 其次的選擇是 Bard,再來是有 Wealth 技能的英雄。 如果想試著使用法師類的英雄,可以考慮 Sage,因為其 Mage King 技能可以用來加強 White Mage, Red Mage, Black Mage。 也可以考慮使用 Pyromancer,Pyromancy 的法術中使用 Soul Flame 法術增加作戰單位 XP, 以及使用 Cauterize 補血 (但是注意 Empire 沒有 mana regeneration 研發的支援)。

Knight 繼承了二代的騎兵體系(Knight, Knight Champion, Knight Lord), 加上初階步兵 Swordsman,可對空對地的單位 Dancing Sword, 價格偏貴但是有 Cure 技能的飛行單位 Archon 與有 Purify 技能的法師 Inquisitor。 Knight 的 弓箭手 Squire 雖然價格不算貴而且生產的速度不慢,不過相較於其它種族的弓箭手而言是偏弱的, 所以如果要對抗較大量的空軍,一般而言在可以生產 Dancing Sword 以後會考慮使用更多的 Dancing Sword 配合而不是單純使用 Squire。 Knight 的初階飛行單位為 Eagle,具有建造建築的能力。Knight 的高階飛行單位為 Pegasus。 Crusade 是一項有趣的研發(共有五級),研發後作戰單位如果殺掉敵人,可以取得額外的 XP。 因為 Knight 是以 Gold 為中心的經濟,所以英雄技能一樣有 Divination Magic 同時又有 Wealth 技能的 Bard 是不錯的選擇 (Bard 可以使用 Divination Magic 中的 Telepathy 增加新產出的單位 XP, Mind Leech 偷取敵人的 XP 以及使用 Comprehension 降低研發的成本, Call Sage 則是可以召喚 Black, Red 或者 White Mage 其中一種法師), 再來是具有 Wealth 技能的英雄。 如果想要偏向戰士類的,可以考慮 Paladin(因為其 Healing Magic 與 Knight Protector 技能), 以及 Warrior(因為與 Knight 種族技能相合)。 如果是法師,可以考慮 Priest 或者是 Healer, 另外因為種族英雄的法術為 Divination,也可以考慮 Sage(但是注意 Knight 沒有 mana regeneration 研發的支援)。

Dwarf 在初期需要建設其經濟(因為其價格較貴的單位,而升級與單位生產大多數都需要 Gold), 同時其大多數的單位移動速度較慢,因此 Dwarf 在初期是處於劣勢的。還有要注意的是,Dwarf 沒有騎兵單位。 Dwarf 主堡 Citadel 並不生產工人,而是由 Foundry 生產 Smith。Smith 如果進入礦產挖礦,會被計算為放入 2 個工人。 Dwarf 除了 Tower,還有主堡升到第三級以後可以建造對地的炮塔 Mortar。 Dwarf Runner 可以研發 Palace MessengerRoyal Messenger 增加移動速度, 同時有不錯的 missile resistance,不過需要研發 WeaponsmithArmorer 才比較好用。 Dwarf Berserker 有較高的物理傷害抗性,同時是對於騎兵有攻擊加成的兵種。Khazrimi Guard 則是對於元素攻擊有不錯的 resistance。 另外弓箭手 Dwarf Crossbow 的價格偏貴不過還可以使用。 Dwarf 的初階飛行單位 Eagle 具有建造建築的能力。 Griffon 是 Dwarf 的高階飛行單位,雖然沒有什麼特別的能力,不過可以對空對地,加上其不錯的移動速度,是十分好用的輔助兵種。 因為 Dwarf 升級時使用較多的 Gold 與 Stone,所以可以嘗試使用有 Wealth 技能的英雄職業加強經濟方面,例如 Merchant。 要注意的是 Dragonslayer 在 unofficial patch 被移除了 Wealth 技能, 所以在 1.03 是個選擇但是在 unofficial patch 不是。 雖然缺乏 mana regeneration 研發的支援,不過因為 Rune Magic 是 Dwarf 英雄的種族技能, lv5 的技能 Runic Lore 可以加強法師 Runelord,所以可以嘗試 Runemaster 這個職業。 還可以嘗試的法師類英雄是 Healer,雖然無法幫助 Dwarf 的經濟,但是補足沒有醫療的部份。

High Elf, Wood ElfDark Elf 分別是代表 Elf 中 Good alignment, Neutral alignment 與 Evil alignment 的種族,都是擁有優秀弓箭手與法師的種族, 並且需要在主堡研發相關 Rune 的科技才能夠生產相關的兵種。 三個種族的工人 Wisp 無法進入礦產挖礦加快資源的收入, 而是需要在二級主堡研發 Ancient Wisp,而後 4 個 Wisp 合成一個 Ancient Wisp 增加 Crystal 的收入, 也因此 Elf 三個種族都需要在資源管理上耗費心力。三個種族的初階飛行兵種 Phoenix 具有轉化 (Convert) 的能力,善用這一點可以取得一些優勢。

High Elf 是一個強大的種族。 Iceguard 是 High Elf 的初階步兵,除了生命值略低,其它數值相比其它種族的初階步兵算是不錯的作戰單位。 Longbow 是 High Elf 的弓箭手,在研發 Rune of Cielos 之後可以生產,研發項目則在 Shooting Range。 Dragon Knight 是 High Elf 的騎兵,可以對空對地,在升到二級主堡後,研發 Rune of Animos 後可以生產。 Unicorn 在研發 Rune of VivosRune of Animos 之後可以生產,是具有醫療能力的騎兵單位,可以作為輔助單位使用。 Mystic 與 Ice Maiden 為 High Elf 的法師,Mystic 的攻擊距離較短,可以施展 Ring of Ice 和 White Ward; Ice Maiden 的攻擊距離長,可以施展 Hand of Ice 和 Freeze。 三個 Elf 種族中只有 High Elf 有攻城單位,可以用來對抗步兵的 Manticore。 Pegasus 是 High Elf 的高階飛行單位,而且 High Elf 還有生產於 Dragonstone、同樣也是高階飛行單位的 Wyvern。 Moonguard 是 High Elf 的將軍同時也是優秀的遠程攻擊單位,除了轉化 (Convert) 能力還具有 Multi-target 技能。 因為 High Elf 種族英雄技能有 Healing Magic 法術,有 Elcor's Balm 與提升 health regeneration rate 的研發 Healing, 以及 Unicorn 提供醫療,所以可以嘗試戰士類的英雄職業,例如 Warrior。 如果想嘗試法師類的英雄,因為種族英雄的法術為 Healing Magic,可以考慮 Priest 或者是 Healer (注意三個 Elf 種族英雄技能都有增加 Mana 的 Lore 技能,而只有 Dark Elf 有 Summon Mana 研發)。

Wood Elf 是一個初期弱勢同時需要良好建設經濟的種族,英雄隨從中帶一個 Ancient Wisp 是一個不錯的主意。 Forestguard 是 Wood Elf 的初階步兵,相比於其它種族的初階步兵而言比較弱小,沒有特別優秀的地方。 Gladewarden 是 Wood Elf 的弓箭手,在研發 Rune of Cielos 之後可以生產,研發項目則在 Rangers' Guild。 Woodrider 是 Wood Elf 的初階騎兵,在升到二級主堡後,研發 Rune of Animos 後可以生產。 Elven Hunter 是 Wood Elf 的高階騎兵,Rune of CielosRune of Animos 二者都有研發就可以生產, FletcherBowyerFlaming Arrows 對於 Elven Hunter 也有效用。 Druid 是 Wood Elf 的法師,在升到三級主堡後,研發研發 Rune of Manos 後可以生產,具有施展 Call Lightning 法術的能力。 Treant 是 Wood Elf 的高階步兵,在升到四級主堡後,Rune of CielosRune of Arbos 二者都有研發就可以生產, 可以建造主要建築,是高效率的 builder,同時有 Entangle 能力可以降低敵人的速度。 Ancient Treant 是高階的步兵,有 Entangle 能力可以降低敵人的速度,死亡時可以分裂為 2 個 Treants,但是沒有建造主要建築的能力。 Dryad 是 Wood Elf 的將軍,相比於其它種族的將軍而言比較弱,優點是轉化 (Convert) 的速度比其它將軍快 25%。 Griffon 是 Wood Elf 的高階飛行單位,因為 Wood Elf 的種族英雄技能中有 Sky Rune,所以 Griffon 這個飛行兵種也有所獲益。 Rune of Arbos 在研發後可以讓 Gladewarden +2 missile range 並且給予額外的 +5 damage, 同時給予 Elven Hunter +2 combat。 Wood Elf 在第四級主堡的時候可以建造 Magic Well 增加 Gold 收入。 White Tree 則是用來生產 Sprite 與 Pixie,以及 Treant 相關的研發。 對於 Wood Elf 來說,還有個劣勢是 Tower 以其價格來說偏貴但是卻沒有其它種族的 Tower 強。 Forest Tower 則是可以用來對空的偵察塔。 以英雄選擇來說,因為 Wood Elf 有 Elcor's Balm 與提升 health regeneration rate 的研發 Healing, 可以嘗試戰士類的英雄職業,例如 Warrior。 也可以考慮同樣有 Nature Magic 技能的 Druid 或者是 Ranger,Druid 的技能 Guardian Oak 可以用來加強 Treant, Ranger 的技能 Griffonmaster 可以用來加強 Griffon。 如果想要使用提供資源的英雄,因為資源方面偏重使用 Crystal,可以嘗試使用有 Gemcutting 技能的 Merchant 或者是 Ice Mage。

Dark Elf 有豐富的兵種。 Dark Infantry 是 Dark Elf 的初階步兵,並沒有研發可以加強這個兵種,但是對於 Dwarf 有攻擊加成。 Dark Archer 是 Dark Elf 的弓箭手,在研發 Rune of Cielos 之後可以生產,研發項目則在 Gallery。 Dark Rider 是 Dark Elf 的騎兵,在升到二級主堡後,研發 Rune of Animos 後可以生產,對於英雄有攻擊加成。 Skeleton 擁有不錯的 missile resistance,Spider 與 Queen Spider 都有 Poison 能力, 以及 Assassin 則是有 Assassination 與 Poison 能力。 Sorceror 具有強大的攻擊法術(Pillar of Fire, Darkstorm),還可以召喚 Zombie 並且讓他們進入資源挖礦,是很優秀的法師單位。 Spider Priestess 也是 Dark Elf 的法師單位,攻擊距離比 Sorceror 短,不過有可以召喚一群 Queen Spider 的能力。 Sorcery 是在 Void 的研發項目,共有 2 級,每級可以 Sorceror 的 Mana 最大值增加 15。 Darkbolt 則是用來增加 Sorceror 與 Spider Priestess 的攻擊,研發後可以 +15 ranged damage。 Harpy 是 Dark Elf 的高階飛行單位(包含 Dark Elf, Daemon, Orc, The Swarm, Undead 五個種族都是 Harpy), 有 Poison 能力並且可以施展 Drain Mana 技能,但是只能對地。 Harpy Hag 是 Harpy 的研發技能,可以給予 +3 combat,包含 Dark Elf, Daemon, Orc 都有這個研發項目。 Dark Elf 種族英雄技能在 lv10 為 Death Rune 與 lv30 為 Assassin,所以適合 Dark Elf 的英雄為 Assassin。 因為 Dark Elf 研發中有 Summon Mana,加上其種族英雄技能有 Summoning Magic,也可以考慮選擇 Summoner。 如果想嘗試不同的英雄,可以考慮有多種法術的 Archmage(需要高等級才能發揮潛力的英雄,很難用好的進階英雄)。

Fey 是二代新增的種族,缺少攻城武器單位,在一開始的時候因為單位較為弱小, 是需要資源升級單位並且度過初期弱勢的種族(同時需要累積更多戰鬥單位,是適合大量生產的種族), 建築的體積小,Unicorn 作為騎兵單位具有醫療能力,可以對空對地的 Leprechaun 還可以增加 Gold 的收入。 Orb of Wonder 雖然只有一種研發項目 Lore (levels 1 - 9),不過對於 Fey 而言是重要的建築,最好建造多個並且能夠研發升級就研發。 Rainbow 這個二級主堡才能建造的建築可以用來生產 Leprechaun 並且研發 Income (levels 1 - 4), 如果以大量的 Leprechaun 作為主力,那麼 Rainbow 也是一個重要的建築。 Lightning Hawk 是 Fey 的初階飛行單位,雖然只能對地,但是攻擊類型為 Electric。 Pegasus 是 Fey 的高階飛行單位。 The Alicorn 這項研發可以帶給 Unicorn +10 melee damage。 Fey 的 Crystal Tower 有個特別的地方是如果殺死敵人的單位會得到 85 Crystal。 一般而言,英雄應該選擇 Merchant 來取得生產折扣以及更多的資源,因為高等級的 Merchant 有 Gemcutting 技能; 還可以的選擇是也有 Gemcutting 技能的 Ice Mage。 Fey 的種族英雄技能中有 Illusion Magic,所以可以考慮 Illusionist。 因為 Unicorn 具有醫療能力,所以可以嘗試戰士類的英雄職業,例如 Warrior。 在 unofficial patch 中 Fey 的種族英雄技能有被修改,增加了 Gemcutting 刪除了 Energy, 這個改法對於工人 Wisp 無法進入礦產挖礦加快資源的收入的三個 Elf 種族來說是破壞平衡的改法。

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

Barbarian 缺少攻城武器以及法師。 優點是經濟均衡,單位生產資源主要是使用 Metal (Barbarian, Rider) 和 Stone (War Dog), 生產速度不慢。在 Fortress 的研發項目 Hunting 最好儘快研發,對於 Barbarian 這個兵種有很大的幫助。 Warlord 是 Barbarian 這個種族在三代新增的高階騎兵,花費並不貴,相比其它的 Barbarian 單位有較高的 Armor,是很有用的單位。 Reaver 是 Barbarian 的將軍,只能用來對地,不過移動速度快,對於大型的敵人有攻擊加成。 Barbarian 的 Summon Mana 是在 Altar of Tempest 研發, 而 Altar of Tempest 還可以生產 Lightning Hawk,雖然只能對地,卻是 Barbarian 的單位中少數具有不同攻擊類型的單位。 Eagle 是 Barbarian 的初階飛行單位,只能對空,但是具有建造所有建築的能力。 Pegasus 是 Barbarian 的高階飛行單位,移動速度快,可以對空對地,可以用來輔助對抗其它種族的空軍。 Scout Tower 是 Barbarian 可以用來對空對地的偵察塔。 Chieftain 是為了加強 Barbarian 的優點而出現的英雄(Barbarian King 技能用來加強 Barbarian, Rider 與 Warlord), 在 unofficial patch 將 Barbarian King 改為 Riding,也就是只加強騎兵(與二代的 Barbarian class 相同), 在 Barbarian 缺少醫療手段的情況下,Barbarian 缺少良好的戰士型英雄支援,所以改弱 Chieftain 是錯誤的修改方向。 其它的英雄選擇是啟用法師類的英雄,因為 Barbarian 有 mana regeneration 研發的支援, 所以使用英雄作為法術輸出以及補強弱點的部份是可行的方向,如果考慮 Barbarian 沒有醫療的方式,可以考慮 Healer。 雖然 Barbarian 的種族英雄技能中有 Ice Magic,但是 Ice Magic 大多數為攻擊法術的法術系列, Ice Mage 並不完全適合 Barbarian(可以用但不夠好)。如果想要嘗試輔助類的英雄,可以使用具有 Running 技能的 Thief。 如果想要使用提供資源的英雄,可以考慮 Tinker 或者是因為 Barbarian 的種族技能有 Quarrying,所以使用有 Smelting 技能的 Daemonslayer。

Minotaur 缺少騎兵單位,單位強壯可靠但是造價較為昂貴, 不過 Minotaur 可以生產 Sheep 以及食用無害動物讓 Minotaur 英雄以及單位 (Minotaur, Axe Thrower, Minotaur Shaman, Minotaur King)自我醫療。 Minotaur 是 Minotaur 的初階步兵,研發升級以後在戰役後期仍然是不錯的單位。 Axe Thrower 是 Minotaur 的初階遠程攻擊單位,只是攻擊距離不長,但是攻擊可以穿過多個敵人。 Gnoll 是 Minotaur 的高階步兵,比起其它兵種數值並不是十分出色,不過具有 Assassination 能力。 Minotaur King 是 Minotaur 的將軍,除了轉化 (Convert) 能力還可以造成敵人 Fear,並且還有 Ignores armor 技能。 Basilisk 提供了加快收集 Stone 的方式(每殺死一個敵人就可以拿到 50 Stone),是很有用的單位。 Bat 是 Minotaur 的初階飛行單位,只能用來對空,是適合用來偵查的兵種。 Griffon 是 Minotaur 的高階飛行單位,雖然沒有什麼特別的能力,不過可以對空對地,加上其不錯的移動速度,是十分好用的輔助兵種。 Lookout 是 Minotaur 可以用來對空的偵察塔。 Minotaur 種族英雄的技能中有 Ferocity 並且有自我醫療的方式,十分適合使用戰士類的英雄,所以可以考慮選擇戰士類的英雄,例如 Warrior。 因為 Minotaur 的種族技能中有 Pyromancy 法術,可以考慮 Pyromancer 這個職業。 如果想要嘗試團隊型的法師英雄,那麼可以嘗試 Illusionist(因為 Mutate 法術可以將對手的基本兵種變成無害動物, 再配合 Minotaur 的食用無害動物自我醫療)。 另外可以嘗試的英雄職業為 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 生產速度不慢,非飛行單位都有免疫 Disease 的優勢,但是對於精神效果的對抗性較差。 戰鬥單位組合包含初階步兵 Orc 與高階步兵 Ogre,初階弓箭手 Kobold Sniper 與高階弓箭手 Troll, 騎兵 Wolf Rider,法師 Goblin Shaman 以及攻城武器 Gobshooter。 Goblin 則是其偵查步兵,攻擊與防守能力都不出色,但是擁有一定機率會散播 Disease 的能力。 Goblin Chief 是高階步兵,可以召喚一群 Goblin,如果傾向於採用人海戰術可以採用。 Giant 則是 Orc 的將軍,除了轉化 (Convert) 能力還可以造成敵人 Fear。 Bat 是 Orc 的初階飛行單位,只能用來對空,是適合用來偵查的兵種。 Harpy 是 Orc 的高階飛行單位,有 Poison 能力並且可以施展 Drain Mana 技能,但是只能對地。 在 Battleyard 中的 No Pain! 需要儘快研發,可以提高對 physical missiles 的 resistance。 Orc 在研發 Shaman research 之後可以建造對空的 Totem 補強防空, 但是注意 Orc 所有的建築都有一個嚴重的缺陷,那就是建築無法花錢修理 (Repair) ,只能嘗試使用 Earthpower 法術回復! Orc 在遊戲設計上怪異的點是雖然其種族英雄技能有 Ferocity, 但是如果將英雄支援的單位或者是技術研發分為戰士型(Healing 研發或者是有醫療的方式)、 法師型(Summon Mana 或者是 Meditation 研發), 或者是加強士氣、增加資源(MoraleIncome 或者是 Trade 這些研發或者是類似的項目與支援, 或者有增加資源的建築與單位), Orc 都沒有這方面的設計,又因為 Orc 已經有良好的戰鬥單位組合,所以可以考慮以團隊輔助為主的英雄, 在戰鬥輔助方面可以考慮 Thief,在加強建築以及增加資源方面可以考慮 Tinker。 如果想要改善建築修復的問題,可以考慮 Runemaster。 因為種族英雄的法術為 Chaos Magic, 也可以考慮使用 Deathknight 或者是 Shaman 輔助戰鬥。

Barbarian, Minotaur, Orc 這三個種族都有掠奪敵人資源的方式。 Barbarian 如果摧毀敵人的建築可以取得 100 Gold; Minotaur 如果摧毀敵人的建築可以取得 100 Metal,Basilisk 每殺死一個敵人就可以拿到 50 Stone, Gnoll 如果 Assassination 技能暗殺敵人成功可以拿到 100 Gold(在 1.03 patch 的數值); Orc 如果摧毀敵人的建築可以取得 100 Stone。 另外,三族都有 Training 這項研發,可以在 Barbarian 的 Camp, Minotaur 的 Arena 與 Orc 的 Battleyard 中研發此項目, 研發後新生產的單位都會 +10 XP,不過不會影響之前都已經存在的部隊,所以愈快研發愈好。

Ssrathi 為三代新增的種族。主堡並不生產工人,而是建造 Worker Sect 後才在 Worker Sect 生產 Chameleon。 Chameleon 是高效率的工人,在研發 Construction 技能之後則是效率最高的工人。 要注意的是,Ssrathi 一般單位通常都可以使用 Poison 或者相關的技能,而 Ssrathi 的 Tower 也具有 Poison 攻擊。 Snakeman 是 Ssrathi 的初階步兵。 Ssrathi 並沒有弓箭手或者是遠程攻擊兵種,而是使用法師 Snakepriest 作為替代品, Snakepriest 在早期就可以生產並且投入戰場(並且有 Cauterize 法術可以略為恢復生命值), 最好在 Sacred Pool 研發 Power of Couatl(總共有 3 級)加強 Snakepriest, 可以攻擊距離 +2, +4 以及 +6。Lizard Rider 則是其移動速度快速的騎兵。 Triceratops 與 Tyrannosaurus Rex 是 dinosaurs,是有較高血量的單位。 Dragonfly 是 Ssrathi 的初階飛行單位,具有 Poison 能力,但為只能對空的兵種。 Pterodactyl 是 Ssrathi 的高階飛行單位,擁有良好的攻擊力,但為只能對空的兵種。 Naga 是 Ssrathi 的將軍,為遊戲中可以渡水的單位,除了轉化 (Convert) 能力還可以造成敵人 Fear。 Couatl's Favor 是第三級主堡的研發項目,可以讓 Ssrathi 的部隊 +4 combat。 雖然 Poison Magic 是 Ssrathi 的種族英雄技能,但對於 Ssrathi 而言並沒有技能十分符合的英雄,Defiler 的技能設計偏向 Plaguelord, Lichelord 對於 Ssrathi 而言只是勉強可用而已。因為 Snakepriest 具有 Cauterize 法術的關係,可以考慮選擇戰士類的英雄,例如 Warrior。 一個有趣的英雄選擇是 Dragonslayer,如果在 unofficial patch 會非常適合,因為 Dragon Master 被修改為其技能,與 Ssrathi 種族英雄技能相符。 因為 Ssrathi 有 mana regeneration 研發的支援,如果想要偏向法師類的,可以考慮 Healer 使用英雄加強醫療的部份。 如果想要嘗試輔助類的英雄,可以使用具有 Running 技能的 Thief。

Dark Dwarf 是二代新增的種族,其大多數單位移動速度稍慢。 Dark Dwarf 主堡 Furnace 並不生產工人,而是由 Guild 生產 Engineer。 Engineer 是高效率的工人,經過在 Ancestral Hall 研發升級後可以使用 Earthpower 法術,同時 Engineer 如果進入礦產挖礦,會被計算為放入 2 個工人。 在兵種上 Dark Dwarf 缺少騎兵和法師單位,使用多種可對空對地的 Golem,包含 Stone Golem, Iron Golem 以及 Bronze Golem; 以及擁有不錯的攻城武器,例如只能對地的 Flame Cannon 以及可對空對地的 Hellbore。 Iron Golem 擁有召喚 Firebomb 的能力。 Bronze Golem 是 Dark Dwarf 的將軍,除了轉化 (Convert),還有一項能力是 scavenge building rubble for resources, 施展後可以從敵人被摧毀的建築取得資源。 如果以 Golem 作為主力,單位生產資源主要是使用 Stone (Stone Golem) 和 Metal (Iron Golem),需要注意的是 Golem 的弱點是 Electric 類型的攻擊。 另外,Golem 無法駐紮 (garrison) 到 Tower 中進行防守,這是 Dark Dwarf 的潛在弱點。 Dark Dwarf 的初階飛行單位 Firebat,可以用來對空以及攻擊建築。 Dark Dwarf 的高階飛行單位為 Wyvern,可以研發 Golden Wyvern 提升移動速度,也是其少數移動速度快的兵種。 Dark Dwarf 除了 Tower,還有主堡升到第三級以後可以建造對地的炮塔 Mortar。 另外,因為設定上 Dark Dwarf 是為了躲避大瘟疫而遷徙結果被 Lord Bane 抓到而出現的種族, 所以 Ancestral Hall 可以用來生產 Wraith 和 Shadow,但是無法像 Undead 一樣可以讓 Wraith 升級, 所以一般而言如果要生產,都會研發升級以後生產 Shadow。 在考慮英雄技能以後,Tinker 是個十分適合 Dark Dwarf 的英雄職業。 如果想要試著使用法師類的英雄,可以考慮 Alchemist。因為種族英雄的法術為 Chaos Magic, 也可以考慮使用 Deathknight 或者是 Shaman 輔助戰鬥。

Daemon 是二代新增的種族,是個強大的種族,缺點是在初期的經濟會有一些麻煩, 擁有不少的飛行單位(Imp, Succubus, Daemon),Nightmare 是其騎兵,Salamander 則是其高階步兵,缺少攻城武器不過對於 Daemon 來說並不是大問題。 Daemon 是 Daemon 強大的飛行單位,擁有造成 Chaos 精神效果的能力。 Daemon 的初階飛行單位 Firebat,可以用來對空以及攻擊建築。 Harpy 是 Daemon 的高階飛行單位,有 Poison 能力並且可以施展 Drain Mana 技能,但是只能對地。 Harpy Hag 是 Harpy 的研發技能,可以給予 +3 combat。 其英雄擁有 Ferocity、Regeneration 以及 Pyromancy 法術技能,在英雄的個人技能上頗為優秀。 在建築方面,除了防禦塔 Tower,也有替代的 Lightning Spire。Lightning Spire 特別的地方在於,這是可以升級的。 Summoning Tower 也是可以升級的建築(共有 3 級),在研發 Brood 之後,可以召喚最多 8 個 Quasit, 以及研發 Summoning 用來降低單位生產時間 (level 1) 與單位的生產花費 (level 2), 還有 Gate 可以用來增加新生產的單位 XP。 在設定上 Daemon 是被 Summoning 法術召喚而來的,而 Daemon 也確實是十分適合 Summoning 法術的種族, 加上 Summoner 的 Gate 技能,Summoner 是最適合 Daemon 的英雄。雖然有點惡趣味,但是如果要嘗試使用偏向戰士的英雄職業, 可以考慮 Daemonslayer。

Plaguelord 為三代新增的種族,是個需要良好資源管理的種族(因為主堡升級、技能升級和生產可能會有資源衝突), 大多數的單位具有免疫 Disease 的能力。要注意的是,Plaguelord 沒有騎兵單位。 Plaguelord 的主堡並不生產工人,需要建立 Cess Pool 後由 Cess Pool 生產工人 Zombie, Cess Pool 還可以生產初階步兵 Ghoul 以及有一定機率會散播 Disease 的偵查步兵 Slime, 而 Ghoul 與 Slime 的科技研發則在 Laboratory。Slime 需要足夠多的數量、並且研發 Acid 升級其攻擊力才會比較好用。 Gazer、Spore 與 Eye of Flame 在 Temple of Eyes 生產,是 Plaguelord 的遠程攻擊單位。 Bone Catapult 是 Plaguelord 的攻城單位,不過通常是使用其較長的攻擊距離作為輔助。 Dragonfly 是 Plaguelord 的初階飛行單位,具有 Poison 能力,但為只能對空的兵種。 Wyvern 是 Plaguelord 的高階飛行單位,對於 Plaguelord 而言是較少使用的兵種,除了需要使用 Piercing 攻擊類型的時候。 Plaguelord 有個很微妙的點,就是 Hydra Cave 可以研發科技升級為 Fire Cave 或者是 Ice Cave, 但是升級以後就無法生產 Hydra,只能生產升級以後的 Pyrohydra 或者是Cryohydra! 以英雄選擇來說,Defiler 有二個技能是用來加強 Plaguelord 的兵種(lv5 Slimemaster 與 lv15 All-Seeing Eye), 所以是還可以的選擇,但是 Ranger 的 Taming 技能對於 Plaguelord 而言有更廣泛的加強效果。考慮種族英雄有 Summoning 法術, 也可以考慮 Daemonslayer。

The Swarm 為三代新增的種族,是以大量生產士兵為主的種族。 主堡 Dunekeep 並不生產工人,需要建立 Hive 後由 Hive 生產工人 Giant Ant, 而 Hive 升級之後則可以生產更多種類的單位(注意,是每一個 Hive 都需要升級,這是 The Swarm 的潛在弱點)。 Scarab 是 The Swarm 的遠程攻擊單位,如果要生產 Scarab 那麼 Hive 至少要升到第二級。 Scorpionman 是 The Swarm 的騎兵。 Husk 生產自 Burial Hall,擁有不錯的 missile resistance。 Scorpionpriest 是 The Swarm 的將軍,除了轉化資源,還可以用來輔助對抗空軍。 Wasp 是 The Swarm 的初階飛行單位,個體弱小,並不是十分可靠,不過具有 Poison 與 Assassination 能力。 Harpy 是 Daemon 的高階飛行單位,有 Poison 能力並且可以施展 Drain Mana 技能,但是只能對地。 Watcher 則是 The Swarm 可以對空對地的防禦塔替代品。 Dunekeep 在研發 Famine 技能之後可以偷取資源。在 Egg Chamber 研發 Incubation 則可以加快生產的速度。 以英雄選擇來說,因為 unofficial patch 修改了種族英雄法術技能 (從 Necromancy 改為 Poison Magic),所以如果要符合大多數的版本,那麼是 Warrior; 如果是 1.03,那麼是 Deathknight,因為 Necromancy 是其英雄的法術技能之一。 如果想嘗試法師類的英雄,可以考慮 Lichelord。

Undead 是一個需要良好操作與資源管理的種族。主堡並不生產工人,而是建造 Graveyard 後由 Graveyard 生產 Zombie。 Undead 生產方式在各種種族中是比較特別的,有一些單位並不是直接從相關建築生產, 而是從 Skeleton、Wight 或者是 Wraith 升級而來(Skeleton 可以從 Graveyard 或者是 Gravestone 生產, 再來花費資源成為 Wight 或者是 Wraith)。Wight 是 Undead 的初階步兵,只能夠對地。 Wraith 也是 Undead 的初階步兵,能夠對空對地,但是後續只能夠升級為 Shadow。 Skeleton Cavalry 則是 Undead 的騎兵單位。Skeleton 與 Skeleton Cavalry 有不錯的 missile resistance。 Shadow 是 Undead 的高階步兵,自 Wraith 變化而來。 Liche 是 Undead 的高階遠程攻擊單位,自 Wight 變化而來,同時也是法師,可以施展 Call the Dead。 Slayer Knight 是 Undead 的高階步兵,自 Wight 變化而來,擁有造成 Chaos 精神效果的能力。 Doom Knight 是強大的單位,從 Slayer Knight 變化而來,擁有造成 Chaos 精神效果的能力。 Vampire 是 Undead 的將軍,除了轉化 (Convert) 能力還可以造成敵人 Fear。 Bat 是 Undead 的初階飛行單位,只能用來對空,是適合用來偵查的兵種。 Barrow 是在二級主堡能夠建造的建築,為 Skeleton 能夠變化為 Wight 的必要建築, 並且有 Haunting (+3 speed) 與 Wailing (+3 combat) 升級 Wight 與 Shadow 的能力。 Necromancy 是其英雄的法術技能之一,是十分適合該種族的法術(第一個法術就是 Raise Skeleton, 第二個法術是 Raise Zombie), 而 Necromancer 的技能 Memories 增加 Skeleton 的 XP,Undead Legion 增加 Skeleton Cavalry 的 XP, Necromancer 是極為適合 Undead 使用的英雄。如果想嘗試戰士類的英雄,可以考慮 Deathknight。 因為 Lichelord 的英雄技能有 Necromancy,法師類的英雄還可以嘗試 Lichelord。

Researches

High Elf 和 Wood Elf 有 Healing 科技可以提升 health regeneration rate。 High Elf 在建築 Healer 與 Wood Elf 在建築 Healing Orb 研發 Elcor's Balm 之後, 就可以以花費 400 Crystal 的代價回復附近大範圍部隊 HP 與治療 Poison、Disease。

Fey 和 High Elf 騎兵 Unicorn 擁有 Cure 和 Group Healing 能力, 對於戰士類英雄以及部隊來說,是很有用的單位。 Empire 的 White Mage 除了轉化 (Convert) 能力,也有 Cure 和 Group Healing 能力,是很有用的單位。 Knight 的 Archon 具有 Cure 能力,可以治療 Poison、Disease以及略為恢復生命值。 Ssrathi 的 Snakepriest 具有 Cauterise 能力,可以用來略為恢復生命值。 Minotaur 種族可以透過無害食用動物自我醫療(例如 Sheep)。

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

研發 Meditation 可以提升英雄 casting skill,第一級提升 10%,第二級提升 20%,第三級提升 30%。 包含 Dark Elf, Fey, High Elf, Wood Elf 這些種族,但是 Fey 只能研發到第二級。

一些種族有 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% 的資源。

另外,Dark Elf, Orc 與 Undead 有 Slavehorde 這項研發,召喚費用最多為 10 個 Thrall 250 Gold。 Dark Elf 在研發 Slavehorde 之後可以在 Reformatory 召喚 Thrall。 Orc Prison 除了生產 Troll,在研發 Slavehorde 之後還可以召喚 Thrall。 Undead Undead 在研發 Slavehorde 之後可以在 Cage 召喚 Thrall。

Morale 在遊戲中是一項支援機制,可以用來增加 army limit,略為加強隊伍的攻擊速度,以及延伸 Command Radius 的範圍。 研發 Morale 可以提升部隊的 Morale,效果為 Morale +3, +6 與 +9, 包含 Dwarf, Empire, Minotaur, The Swarm, Wood Elf 這些種族有這個研發。 Ssrathi 也有類似的研發,Warmth 可以提升部隊的 Morale +5。 Knight 的研發 Order of the Lion 可以增加英雄 Morale +2。 另外,有幾個作戰單位在戰場上可以提升已方的 Morale,包含 Knight 的 Knight lord 可以帶來 +2 Morale, 與 Barbarian 的 Warlord 可以帶來 +1 Morale。

英雄有 command radius 的設計(也就是英雄轉化、使用法術的有效範圍),可以按 r 查看目前的範圍。 Undead 的研發 Dark Lord 可以 +8 英雄 command。

大多數的種族都有加強攻擊、防守等方面的研發。 WeaponsmithArmorer 是一些種族都有的科技研發項目,共有二級研發。 前者 +5 melee damage 與 +10 melee damage,包含 Dark Dwarf, Dwarf, Empire, Knight, Undead 這些種族有這個研發。 後者 +5 armor 與 +10 armor,包含 Dark Dwarf, Dwarf, Empire, Knight 這些種族有這個研發。 在研發 Weaponsmith 和 Armorer 之後,Dark Dwarf 與 Dwarf 還可以研發 Mithril; Knight 則有 Full Plate Armor 可以提升騎兵的 armor。 Undead 則是在 Weaponsmith 之後還可以研發 Dark Mithril。 其它種族也有類似的研發, Minotaur 的 Iron Clad HornsIron Shod Hooves 各提供了 +10 melee damage, Shield of Sartek 提供了 +5 armor 與 +10 armor。 Fey 的 Faerie Blade 研發後可以 +5 melee damage,Panoply 提供了 +5 armor 與 +10 armor。 Daemon 的 Intangibility 提供了 +5 armor 與 +10 armor。 Barbarian 的 Magical Tattoos 提供了 +5 armor。

FletcherBowyer 為加強弓箭手的科技研發, 前者 +5 damage,後者 +2 range,包含 Dark Elf, Dwarf, Empire, High Elf, Knight, Wood Elf 這些種族有這個研發。 Flaming Arrows 則是可以將攻擊類型從 Piercing 變為 Fire, 包含 Dark Elf, Empire, High Elf, Knight, Wood Elf 有這項研發。 Fey 也有類似的研發,Faerie Sight 這項研發提供了 Faerie Dragon, Leprechaun, Pixie 以及 Sprite 這些兵種 +2 range。

對於大多數的種族來說,關於視野與地圖迷霧 (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, 用來去除地圖迷霧。Daemon 的 Daemonic Sight 也是視野相關的研發,效果為視野距離 +2 與 +4。

Minotaur 與 Dwarf 有 Dwarven Brew 這項研發, Minotaur 在 Ale Store 研發,Dwarf 在 Brewery 研發,功用是花費某些 Gold 作為代價, 暫時提升 Combat 與 Speed,並且暫時免疫四種精神效果的狀態和二種疾病, 但是之前如果已經處於四種精神效果或者二種疾病的狀態中,那麼並沒有移除的能力。 在與敵人大會戰之前或者需要提升作戰單位的移動速度十分有用(特別是對沒有醫療能力以及移動速度不快的 Dwarf 而言)。

Barbarian 與 Minotaur 有 Berserker 這項研發, Barbarian 在 Altar of Tempest 研發並且對 Barbarian 與 Reaver 有用, Minotaur 在 Altar of Sartek 研發並且對 Minotaur, Axe Thrower 與 Minotaur Shaman 有用, 功用是啟動後,選定的單位將著火,持續對單位造成傷害,但同時獲得 +4 speed, +6 combat 與 +15 fire resistance。

Heroes

每個種族的英雄都有其各自的技能,加上英雄職業專長的技能,就組成了一個英雄能夠學習的技能表。 如果你選擇的種族英雄與你選擇的職業專長技能相同,那麼玩家將獲得 Synergy Bonus,使該技能在 1 級時可用, 並且你的技能也會獲得加成。

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

  • Strength
    • +1 Combat per 2 points of Strength (Every odd level)
    • +1 Damage per point of Strength
    • +3 Hit Points per point of Strength
    • +1 Life Regen (per 20 sec) for every 3 points of Strength (1,4,7,etc)
  • Dexterity
    • +1 Movement Speed per 2 points of Dexterity (Every odd level)
    • +1 Resistance per 2 points of Dexterity (Every even level)
    • +1 Armor per 4 points of Dexterity
    • -1 Second to Conversion Time per point of Dexterity (min 10 sec’s)
  • Intelligence
    • +3 Mana Points per point of Intelligence
    • +1 Mana Regeneration (per 20 sec) for every 10 points of Intelligence
    • +1 Initial Troop XP per 2 points of Intelligence (Every even level)
    • +3% Spellcasting Chance per point of Intelligence
  • Charisma
    • +1 Command Radius per 4 points of Charisma
    • +1 Morale per 2 points of Charisma (at 2,4,6,etc…)
    • +1% Discount per point of Charisma over 5
    • +1 Retinue Slot for every 4 Points of Charisma

一名英雄最多可以有 8 名隨從 (Retinue),使用 Charisma 計算的 Army Setup Point 決定隨從的人數。

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

  • 戰士:
    一開始就有 Ferocity 技能 - Chieftain, Dragonslayer, Warrior
    Warrior 擁有增加生命值的 Constitution 與提高生命值恢復率的 Regeneration;
    Chieftain 的技能 Leadership 可以提升士氣 (Morale),Barbarian King 技能用來加強 Barbarian 的 Barbarian, Rider 與 Warlord;
    Dragonslayer 的技能 Wealth 可以帶來 Gold 收入

    戰士加上法術技能的混合類型 - Daemonslayer, Deathknight, Paladin
    Daemonslayer 使用 Summoning 法術,以及 Smelting 技能增加 Metal 收入;
    Deathknight 使用 Chaos Magic 與 Necromancy 法術;
    Paladin 使用 Healing Magic 法術,Knight Protector 增加新產出的 Knight 騎兵 XP
  • 法師: 初始技能為單一系列的法術技能加上 Ritual 技能,lv25 有 Arcane Magic - Alchemist, Defiler, Druid, Healer, Ice Mage, Illusionist, Necromancer, Priest, Pyromancer, Runemaster, Sage, Shaman, Summoner
    Priest 這個職業特別的地方在於,除了一開始的 Healing Magic,lv5 的技能為另外一個法術系列 Divination。
    多種法術技能 - Archmage (Summoning, Alchemy, Divination, Illusion), Elementalist (Pyromancy, Ice Magic, Rune Magic), Lichelord (Necromancy, Poison Magic)
  • 團隊輔助(提供資源、提高士氣或者是戰鬥輔助): Assassin, Bard, Merchant, Ranger,Tinker, Thief
    Assassin 有 Wealth 可以帶來 Gold 收入、Assassin 則有一定的機率可以立刻殺掉敵人;
    Bard 有 Wealth 可以帶來 Gold 收入、Leadership 提升士氣 (Morale) 以及使用 Divination 法術輔助戰鬥;
    Merchant 擁有 Merchant 和 Trade 技能,Wealth 增加 Gold, Gemcutting 增加 Crystal;
    Tinker 的 Engineer 技能增加建築物生命值, Smelting 增加 Metal, Quarrying 增加 Stone,以及使用 Alchemy 法術;
    Ranger 一開始就有 Running 技能,Griffonmaster 加強 Griffon,Taming 加強 monsters 以及使用 Nature Magic 法術;
    Thief 一開始就有 Running 技能,Warding 加強部隊的 Resistance,以及使用 Illusion 法術

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

  • 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 Ice Mage, Merchant (class)

(注意:在一些 unofficial patch 中,Dragonslayer 被移除了 Wealth 技能, 而 Fey 種族英雄則是被增加了 Gemcutting 技能)

英雄每一個種族一開始都會有增加士氣 (Morale) 的技能,每一級都加 2 點,包含 Dwarf 的 Dwarf Lord, Empire 的 Imperial Lord, High Elf 的 High Lord, Knight 的 Knight Lord, Barbarian 的 Horse Lord, Fey 的 Dream Lord, Minotaur 的 Horned Lord, Ssrathi 的 Serpent Lord, Wood Elf 的 Forest Lord, Daemon 的 Daemon Lord, Dark Elf 的 Dark Lord, Dark Dwarf 的 Siege Lord, Orc 的 Orc Lord, Plaguelord 的 Plague Lord, The Swarm 的 Scorpion Lord, Undead 的 Skull Lord。

要注意的是,遊戲並沒有限制一定要某個種族的英雄才能夠領導某個種族, 因此不同種族的英雄領導另外一個種族是可以的(只是因為個人的習慣,我通常不會這樣做)。

遊戲中有英雄可以穿戴物品的設計(物品有 Minor, Lesser, Greater, Artifact 四個等級)。 物品可以加強或者是補足英雄不足的地方,或者因應英雄或者種族的需要使用特定的物品。 部位包含 Headgear, Body Equipment, Weapon, Shield/Banner, 2 accessories and Boots。 物品可以提供英雄額外的技能,同時有一些物品還有一定的機率可以施展一些法術。 同時遊戲中也有 Set Items 的設計,例如在劇情中可以在 New Selentia 收集 The Gifts of Couatl(英雄可以 +100 Spell Casting)。

Name Code Details
Giant's Helm 03 Combat +12
The Stone Crown C1 Dwarf Lord +5, Casts Stoneskin at level 2 (5%), Casts Doomstones at level 1 (5%)
Circlet of Thull 3E Summoning Magic +3, Spell Casting +5
Bane's Crown 2A Skull Lord +2, Casts Scare at level 1 (10%)
Royal Runemail 27 Armor +25, Health +20(劇情模式中,如果是 Orc 的友好方,在 Kor 幫助他們之後可以拿到這個物品)
Ultimate Cloak of Protection A7 Resistance +15, Magic Resistance +10, Armor +5
Armor of Brilliance D5 Armor +5, Resistance +5, Spell Casting +10
Orc King's Blade 0C Slashing Damage +15, Combat +6
Ogre's Blade BD Slashing Damage +20, Man Slayer +1
The Stinger CF Piercing Damage +15, Casts Spray Poison at level 1 (5%)
Sun Staff 9C Fire Damage +10, Casts Pillar of Fire at level 1 (5%)
Staff of Zhur CB Crushing Damage +10, Necromancy Magic +3, Memories +3(劇情模式中,可以在 Zhur 取得這個物品)
Staff of Regret D4 Crushing Damage +10, Lore +4
Banner of Frost BC Fire Resistance +20, Mana Regen +20, Casts Hand of Ice at level 1 (8%)
Lost Banner of Lysea 4C Command +4, Imperial Lord +7
Banner of Zhur CC Skull Lord +2, Undead Legion +2(劇情模式中,可以在 Zhur 取得這個物品)
Horn of K'Varr B3 Combat +2, Speed +2, Life Regen +40
Tome of Pure Light 40 Healing Magic +3, Casts Purify at level 1 (5%)
Orb of Healing 67 Health +20, Life Regen +20, Casts Heal Self at level 1 (5%) (劇情模式中,在 Silvermyr 幫助 Wood Elf 之後可以拿到這個物品)
Ring of Heaven C0 Life Regen +20, Casts Purify at level 1 (5%), Spell Range +20
Orb of Etheria 4F Morale +5, Combat +5, Casts Soul Flame at level 5 (5%)
Tome of Knowledge 5F Divination Magic +6, Spell Casting +5
Tome of Change 60 Chaos Magic +6, Spell Casting +5
Tome of Lies 61 Illusion Magic +6, Spell Casting +5
Orb of Godly Power 88 Health +60, Spell Casting +5
Greater Orb of Protection 83 Armor +15, Spell Casting +5
Shaman Stones 66 Spell Casting +15, Electric Resistance +10
Dragonstones BB Dragon Master +2, Morale +1, Magic Resistance +5
Ultimate Troll Ring 72 Life Regen +100
The Vault Key 97 Wealth +2
Boots of the Tundra 4E Speed +2, Cold Resistance +10, Spell Casting +10
Elven Boots A3 Speed +3, Resistance +5

Spells

魔法有以下的法術類別 (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.

要注意的是,多個法術系列都有召喚某些單位的能力(包含 Alchemy, Divination Magic, Illusion Magic, Nature Magic, Necromancy, Poison Magic, Pyromancy, Rune Magic, Summoning Magic), 而使用法術召喚的單位一樣算在 Army Limit 中,也就是如果到達限制數目,英雄會無法順利召喚。 另外,雖然 Illusion Magic 召喚的單位只是攻擊力為 1 的幻影(但是其它方面例如 health points 與精神效果是相同的), 但是一樣受到影響。

英雄都是近戰 (melee) 類型,除了使用魔法暫時變成遠程(例如 Ice Magic 的 Ice Floe), 以及使用技能(例如 unofficial patch 中 Pyromancer 的其中一項技能從 Demolition 被修改為遠程的 Fire Missile)。 另外,使用 Pyromancy 的 Firebreath 可以給與施法者以外的附近部隊暫時有造成 10 點傷害的遠程 Fire 攻擊。

通常每場戰役英雄都有 4 個 Health Potions 與 4 個 Mana Potions, 按 h 可以使用 Health Potion,按 m 可以使用 Mana Potion。Alchemy 法術中的 Brew Potion 可以用來創造新的 Health Potion; 而 Healing Magic 的 Heal Self, Cure, Heal Group, Major Healing, 與 Nature Magic 的 Gemberry,和 Pyromancy 的 Cauterize 可以用來恢復 health points。 Chaos Magic 的 Morph Health 則是給與部隊 +30 到 -30 之間的 health points(也就是可能補血也可能扣血)。

Healing Magic 的 Cure 與 Poison Magic 的 Antidote 可以移除疾病(不管是 Poison 或 Disease)。 Poison Magic 的 Immunity 則是使用後施法者可以暫時免疫疾病。 Ice Magic 的 Calm 可以移除精神效果的狀態。Healing Magic 的 White Ward 可以暫時免疫精神效果。

Illusion Magic 的法術 Scare 可以讓看到施法者的敵人 Fear,Awe 可以讓看到施法者的敵人處於 Awe 的精神效果, Dragonfear 可以製造龍的幻影造成 Terror 的精神效果。

有些法術可以提高 Armor 或者是 Resistance,包含 Pyromancy 的 Resist Fire 給予施法者 +25 Fire Resistance; Healing Magic 的 White Ward 給予周圍部隊 +5 Resistance; Divination Magic 的 Elemental Lore 給予施法者 +10 Resistance 和 Defense Lore 給予施法者 +10 Armor; Rune Magic 的 Stoneskin 給予施法者 +10 Armor,Resist Magic 給予施法者 +25 magic protection, 與 Resist Missile 給予施法者 50% missile resistance(Fandom 網頁上的 immune 在 1.03 是錯誤的, 不確定是否為 unofficial patch 的修改);Ice Magic 的 Ice Armor 給予施法者 +5 Armor; Illusion Magic 的 Shadowform 給予施法者 +1 Speed, +5 Armor and +5 Resistance。

有些法術可以用來降低對手的移動速度或者攻擊速度,Ice Magic 的法術 Freeze 可以降低移動速度 2 點並且降低攻擊速度 20%; Nature Magic 的法術 Entangle 可以降低移動速度 4 點。

另外,Healing Magic 的 Blessing 可以提高施法者的士氣 (Morale) 2 點, Invigorate 可以提高附近友軍的移動速度 2 點。Chaos Magic 的法術 Morph Speed 其效果是隨機的, 效果從 -3 到 3 之間隨機決定。

Necromancy 的法術 Vampirism 可以讓友方單位獲取偷取生命的能力,+2 hits per attack。

Necromancy 的法術 Black Portal 在召喚 Black Portal 之後在附近使用可以提升法術 1 個等級。 Summoning Magic 的法術 Circle of Power 在召喚 Circle of Power 之後在附近使用可以提升法術 1 個等級。

Summoning Magic 的法術 Phantom Steed 可以用來加強騎兵;Blink 則是可以隨機的改變自己到附近的位置; Home Portal 則是傳送施法者到一開始的啟始位置。

Alchemy 的法術 Acquire 可以立即轉化附近的資源,在搶奪資源時是很有用的法術。 Alchemy 與 Rune Magic 都有 Summon Guardian 這項法術,雖然有時間限制,但是被視為建築,在臨時需要防守建築的情況十分好用。 Rune Magic 的法術 Dig 可以降低建造建築的時間 20%,是一項有用的法術。

如果使用的種族沒有 Trade 研發項目可以用來交換資源(例如 Gold 交換 Metal,不過交換後只能換到約 50% 的資源), 二個法術系列的法術也有同樣的效果,一個是 Alchemy 的 Transmute,一個是 Chaos Magic 的 Morph Resources

有些法術可以用來改變日夜或者是氣候。 Ice Magic 的 Storm 法術可以將天氣改為 thunder 與 rain。 Nature Magic 的 Change Weather 法術可以將天氣改為 night/day/fine/rain。 Necromancy 的 Darkstorm 法術可以將天氣改為 night 並且將其設定為 rain。

當然,也有一些法術是在施法範圍內直接造成傷害的法術,下面是一些例子。 Arcane Magic 作為輔助用的法術系列,Destruction (100 Mana) 是其對敵方單位與建築造成大量傷害的法術。 Chaos Magic 的 Wildfire (32 Mana) 法術可以造成施法範圍內的敵人 50 點 Fire 傷害; Chaos Plague (70 Mana) 法術將施法範圍內的敵人目前的生命值刪減 50% 並且處於 Disease 的狀態。 Ice Magic 與 Necromancy 的 Ring of Ice (35 Mana) 法術可以造成施法者周圍的敵人 40 點 Cold 傷害。 Ice Magic 的 Ice Storm (65 Mana) 法術可以造成施法範圍內的敵人 100 點 Cold 傷害。 Nature Magic 的 Call Lightning (35 Mana) 法術可以造成施法範圍內的敵人 60 點 Electric 傷害。 Poison Magic 的 Spray Poison (30 Mana) 法術可以造成施法範圍內的敵人 40 點傷害。 Pyromancy 的 Pillar of Fire (40 Mana) 法術可以造成敵人 120 點 Fire 傷害; Armageddon (75 Mana) 法術可以造成施法範圍內的敵人 100 點 Fire 傷害。 Rune Magic 的 Doomstones (16 Mana) 法術可以造成施法範圍內的敵人 30 點 crushing 傷害。 Healing Magic 的 Purify (20 Mana) 法術可以造成施法範圍內的 Evil 單位 50 點 Magic 傷害。 Divination Magic 與 Summoning Magic 的 Banish (30 Mana) 法術可以殺掉所有 extra-planar level 1-2 的敵人, 例如 Demons, Elementals 與 Archons。

Hotkey

按鍵:
F12 = Pause game
Alt + g = Game menu
Ctrl + 1 ~ 9 = Define a group

. (dot) 鍵可以用來選擇正在閒置的 builder(包含英雄在內)。
Ctrl + a = 選擇全部
Ctrl + h = 選擇英雄
S = Open Spellbookc
開啟 Spellbook 之後選擇子分類 -
h = Healing Spells
s = Summoning Spells
d = Druidic/Nature spells
i = Illusion Spells
n = Necromancy Spells
p = Pyromancy Spells
a = Alchemy Spells
r = Rune Spells
e = Ice Spells
x = Chaos Spells
z = Poison Spells
v = Divination Spells
c = Arcane Spells
Cast spell from open Book = 1, 2, 3, ... 0
F1 ~ F8 可以用來設定施法快速鍵。