2012 程式設計比賽 Openfind 天使帝國 v2.0 (蓋亞的紋章)
Preview
比賽規則 (1/2) 由Player(Blue)的部隊跟CPU(Red)控制的部隊互攻 地圖大小 10x7 每場戰役結束(一方全滅 or 50回合到達) 每殺死CPU部隊,獲得50% 死亡部隊價格當作score 戰役結束,玩家每剩下一支部隊(不論血量),獲得50% 該存活部隊價格當作score
比賽規則 (2/2) 每場戰役玩家會得到 1000元(基本消費) + 上一場戰役得到score + 上一場戰役剩下的錢 CPU 每場戰役會比上一場多 300元 總共10場戰役,10 場戰役每場 score累加,最高者得冠軍
戰士 生命值:500 攻擊:170 防禦:50 移動力:3 攻擊方式:近戰 特殊能力:被近身攻擊可反擊 價格:200
法師 生命值:240 攻擊:200 防禦:0 移動力:1 攻擊方式:遠程法術 施法距離:3 移動方式:步行 特殊能力:攻擊無視防禦 價格:400
屬性相剋 總共有風火水土四種屬性 土剋水 水剋火 火剋風 風剋土 相剋屬性(土屬性攻擊水屬性),可獲得200%攻擊效果 被剋屬性(水屬性攻擊土屬性),攻擊效果削弱50% 不相干屬性互打,沒特別加成或是削弱
每回合輪到 Player 每支部隊只能行動一次,行動完畢必須要等下回合 CMD_MOVE: 移動,之後此部隊本回合行動結束 CMD_MOVE_AND_ATTACK: 移動後施展攻擊,之後此部隊本回合行動結束 CMD_END_TURN: Player 主動宣告此回合結束 移動 src => dest,其中 src 可以等於 dest (代表站在原地) 每支部隊都行動過後,本回合自動結束換 CPU 部隊行動
移動規則 每步只能走上下左右四個方向 (不能走斜線) 步行 – 移動距離(3)當作例子,可以走 0步(停在原地)、1步、2步、或是3步。只是每一步都必須有空地可以停留。(如右圖)
近戰攻擊規則 (A 攻擊 B) B 必須為敵軍 每回合可施展移動後攻擊一次 殺傷力= (A.攻擊 – B.防禦)xAdj(屬性調整) (3)若屬性A剋B,Adj為 200% (4)若屬性B剋A,Adj為 50% (5)B存活且具備近戰反擊能力,將自動反擊A一次
遠程法術攻擊規則 (A 攻擊 B) B 必須為敵軍 每回合可施展移動後攻擊一次 殺傷力= A.攻擊力(無視對方防禦)xAdj(屬性調整) 屬性相剋調整同上頁 (50%、100%、200%)
分數計算 & 戰役結束 戰役結束條件為 (1)一方全滅或(2)超過50回合 戰役中擊殺敵軍 B 可以得到 B.價格x50% 獎金 戰役結束後,PLAYER方殘存部隊得 A.價格x50%獎金 總獎金 + 本戰役剩下的錢可帶入下一場戰役,所以下一場戰役起始會有上述金額 + 1,000元 的經費 每場戰役打越好,下一場錢越多,富人越富 每場戰役打越差,下一場錢越少,窮人越窮 搞砸一場戰役,等於打入深淵
處罰條件 有任何錯誤 (buildArmy, move, moveAndAttack),直接判定該戰役得零分 超過 30 秒沒有移動,該戰役得零分 找到一個系統錯誤,可以拔 Mike 頭髮一根
Openfind 天使帝國 Programming Guide
User.dll 主程式 scoring.exe 將呼叫 User.dll (dynamic) User project 中包括 User.dsw(VC++ compiler) User.cpp -> 主要回傳 functions 都在此 check.h -> 資料結構以及輔助 functions 都在此
Callback function (1/2) void buildArmy(int team[21], int money) Main system 每場戰役開始前會呼叫此 function Users 把自己的起始部隊配置放在 team[21](位置如右圖),且花的錢不能超過 money
Callback function (2/2) int playerMove(POINT pt[3]) Main system 每回合不斷呼叫,直到使用者行動完畢回合結束 Pt[0]: src, pt[1]: dest, pt[2]: target CMD_MOVE: 從 pt[0] 走到 pt[1] CMD_MOVE_AND_ATTACK: 從pt[0]走到pt[1]並攻擊pt[2] CMD_END_TURN: 主動宣告回合結束
Data structure (#define and global) #define WALL 0 #define SPACE 1 #define WARRIOR_WIND 2 #define WARRIOR_FIRE 3 #define WARRIOR_WATER 4 #define WARRIOR_EARTH 5 #define MAGICIAN_WIND 6 #define MAGICIAN_FIRE 7 #define MAGICIAN_WATER 8 #define MAGICIAN_EARTH 9 g_nTurn : The current turn.
Data structure (g_map) struct MAP { int armyType; // can be 2 ~ 9 int armySide; // 1 is Player, 2 is CPU int live; // 這支部隊剩下多少生命值 int alreadyMoved; // 0 is false, 1 is true int id; // An unique id for each army (繪圖使用) } g_map[MAP_X_SIZE][MAP_Y_SIZE]; 地圖大小:MAP_X_SIZE * MAP_Y_SIZE Global variable g_map:整張地圖上每個點的資訊
Data structure (g_army) { int live; //生命值 int attack; //攻擊力、法術攻擊量 int defence; //防禦力 int attackRange; //攻擊範圍 int moveRange; //移動力 int type; //風(0) 火(1) 水(2) 土(3) int isFightBack; //是否可近戰反擊 (0) or (1) int isSpell; //是否為法術攻擊 (0) or (1) int price; // 部隊價格 } g_army[TOTAL_ICON]; 可用範圍:g_army[2]~g_army[9] 僅當作 check functions 的參考,自行修改是沒用的
Utils 自我檢查 PLAYER build army 是否合法 // Function: int checkBuildArmy(int player[21], int money) // Input // int player[21]: 對應到地圖左邊的三排位置, // 每個位置放入兵種 2 ~ 9 或是 SPACE(代表空的) // Return // >=0: The content of player[21] is ok, return 剩下的金額 // ERR_INVALID_TYPE: At least one of the position contains invalid type // ERR_EXCEED_COST: The total cost of player[21] exceeds the maximum value (傳入的 money)
Utils 取得 src 可以移動到那些 dest[] // Function int getMove(POINT src, POINT dest[70], int userType) // Input // src: The original point of the army you want to move // dest[70]: All the result of available move points will be stored in this array // userType: should be PLAYER(1) or CPU(2) // // Return // 0 ~ positive value: The count of total available moves. // ERR_INPUT: The input userType is not PLAYER(1) or CPU(2) // ERR_NOT_PLAYER: The army in the src does not belong to you // ERR_ALREADY_MOVE: The army in the src has performed an move already.
Utils 取得 src 可以法術攻擊那些 dest[] // Function int getSpellAttack(POINT src, POINT dest[70], int userType) // Input // src: The original point of the army that you want to cast an offence spell // dest[70]: All the result of available targets will be stored in this array // userType: should be PLAYER(1) or CPU(2) // // Return // 0 ~ positive value: The count of total available points of targets. // ERR_INPUT: The input userType is not PLAYER(1) or CPU(2) // ERR_NOT_PLAYER: The army in the src does not belong to you // ERR_ALREADY_MOVE: The army in the src has performed move and attack already // ERR_CANNOT_CAST: The army in the src does have the ability to case an offence spell
Utils 自我檢查 src => dest 是否正確 // Function int checkMove(POINT src, POINT dest, int userType) // To check move from src to dest is legal or not, but will not perform it. // // Input // src: The original point that you want to move your army // dest: The destination point that you want to move your army // userType: Should be PLAYER(1) or CPU(2) // Return // SUCCESS: Your move is valid. // ERR_INPUT: The input userType is not PLAYER(1) or CPU(2) // ERR_NOT_PLAYER: The src does not belong to you // ERR_ALREADY_MOVE: The src has performed move already. // ERR_ILLEGAL_DEST: The dest is not empty or out of range
Utils 自我檢查 src => dest 然後攻擊 target 是否正確 // Function int checkMoveAndAttack(src,dest,target,userType) // To preform move then attack. If you don't want to move, you can just input src==dest // Once performing attacking, the army cannot be moved anymore. // // Input // src: The original point of your army // dest: The destination point of your army // target: The target point that you want to attack // userType: Should be PLAYER(1) or CPU(2) // Return // SUCCESS: Your move and attack is valid // ERR_INPUT: The input userType is not PLAYER(1) or CPU(2) // ERR_NOT_PLAYER: The src does not belong to you, or cannot perform attack // ERR_ALREADY_MOVE: The src has performed move already // ERR_ILLEGAL_DEST: The dest is not empty or out of range // ERR_ILLEGAL_TARGET: The target cannot be attacked (not enemy or not reachable)