--- tags: 資訊營 --- # 2020 台大椰林資訊營 AI Challenge ElectroShock 遊戲介紹 :::info 7/18 16:20 在規則新增攻擊冷卻時間 7/18 19:02 新增6個好用的函數,有需要的小隊員請自行重載遊戲,謝謝大家 `get_nearest_player_position(): tuple(float, float)` `get_nearest_specific_item_position(item_id): tuple(float, float)` `get_nearest_drop_pistol_bullet_position(): tuple(float, float)` `get_nearest_drop_banana_peel_position(): tuple(float, float)` `get_nearest_drop_big_black_hole_position(): tuple(float, float)` `get_nearest_drop_cancer_bomb_position(): tuple(float, float)` 7/18 19:26 即將新增2個關於禮物盒的函數 `get_gift_position(): tuple(float, float)` `get_gift_velocity(): tuple(float, float)` 7/19 12:15 修復 `get_self_attack_radius` 的問題。 現在在使用「無敵電池」的期間,`get_self_attack_radius` 會正確地回傳乘過 1.5 倍的長度。 ::: [TOC] ## 遊戲內容 在德田館工作站的深處,有著四顆小電球,因為資源有限的關係,他們必須進行一場驚心動魄的電球大亂鬥,為了繼續占用工作站的記憶體和運算資源,它們將奮不顧身。在這場大亂鬥中,四顆小電球將在工作站的擂台上爭霸,他們必須在保護自身處境的情況下,嘗試將敵人電飛,因為最終,只有一顆小電球能留下,其他小電球終將被電飛,喪失工作站的使用權,永久不得賦歸... ### 程式執行 `$ python main.py [<name>] [<name>] [<name>] [<name>]` * 如果`<name> == "m"`: 手動玩家。 * 如果有`<name>`,程式會讀取`AI/team_<name>.py`。 * 如果給的`<name>`不足4個,會自動加入手動玩家。 `eg: $ python main.py kaguya Rem Emilia` ### 操作 ![](https://i.imgur.com/mDIWcS5.png) | P1 | P2 | P3 | P4 | Function | |:---:|:---:|:---:|:-------:| -------------------- | | A D | F H | J L | ← → | 控制玩家的方向(左右) | | W | T | I | ↑ | 跳躍 | | S | G | K | ↓ | 放電 | | Q | R | U | Shift | 使用道具 | 1. 在遊戲開始的選單中,以按鍵`1`,`2`,`3`,`R`來選擇關卡,按空白鍵開始。 2. 在遊戲進行間,以空白鍵暫停,再按一次空白鍵繼續。 3. 在任何時間,皆可以`F11`切換全螢幕或縮小視窗。 ### 規則 1. 在鄰近對手時放電,可以使得對手沿著法線方向被電飛。 2. 在遊戲畫面底下,每顆小電球有屬於自己電壓表,電壓越高,被他人電擊時的速度越快。 3. 場地上的道具隨機生成,經過便可撿取道具,每顆小電球最多只能同時擁有一項道具,且會顯示在自己的電壓表旁。 4. 每人有五條命,若被擊出場外,則被K.O.一次,減損一條命。 5. 復活時會有2秒的無敵時間。 6. 每顆小電球可以在空中彈跳三次。 7. 小電球可以從下往上穿越平台,但由上往下會被擋住。 8. 遊戲時間結束時,分數結算最高者獲勝。 9. 隨著遊戲進行,水平移動速度及道具產生數量都會持續上升。 10. 基本的攻擊冷卻時間是$1.5$秒(受道具卡影響) ### 地圖 1. 在遊戲選單有三種地圖可以選擇,選擇地圖然後按下空白鍵會開始遊戲。 ![](https://i.imgur.com/xIh6YmU.png) 2. 三種地圖 (1) ![](https://i.imgur.com/bzPgRsV.png) (2) ![](https://i.imgur.com/qdG1M8q.png) (3) ![](https://i.imgur.com/elP0fl5.png) 3. 地圖的座標,左上角是原點,對於所有位置,第一個index是x軸,第二個index是y軸,往右是x正向,往下是y正向。地圖的大小是$1132\times 623$,x軸和y軸的方向對`TeamAI`的設計很重要喔!示意圖: ![](https://i.imgur.com/QkZ8KI4.png =60%x) ### 道具 | Figure | Name | Description | Effect | |:------------------------------------:|:--------:|:------------------------------------------------------------------------------------------------------------------------- | --- | | ![](https://i.imgur.com/Znlo3cH.png) | 蕉蕉手槍 | 發動時,蕉蕉的內容物將朝前方射出,擊中對手時將使對方受到極大的羞辱,並在完成任務之後,成為地上的蕉蕉皮,遺臭萬年。 | 被擊中者+10V,如同被電擊會有一法向速度 | | ![](https://i.imgur.com/8oGUoyM.png) | 大黑洞 | 集結所有質量於一身的大黑洞,在被發動時會使用萬有引力將其他玩家與道具吸引過來,再頑強的人都難以抵抗他的吸引力。 | 讓道具與其他玩家在黑洞周遭以一定的半徑環繞中心 | | ![](https://i.imgur.com/byTV7nb.png) | 毒瘤炸彈 | 作為毒瘤code的化身,被擊中者將深陷debug的輪迴之中,永遠找不到bug,憤怒之氣將進一步使得電壓大幅提升 | 被波及者+40V,如同被電擊會有一法向速度 | | ![](https://i.imgur.com/c6qSFLX.png) | 電電電! | 使用此道具時,電神們將聽到你的呼喚,並降下雷霆萬鈞,使得方圓五公里以內的人都無法倖免,被高強度的電流電的不要不要。 | 發動者+15V 被擊中者+30V,如同被電擊會有一法向速度 | | ![](https://i.imgur.com/nqkQ7A4.png) | 蕉蕉皮 | 生活習慣不佳的小電球們,在享用完蕉蕉之後所留下的產物,遺落各處的蕉蕉看似毫無用處,卻使得戰場危機四伏。 | 誤觸香蕉皮者失去控制方向的能力0.5秒(可疊加) | | ![](https://i.imgur.com/3sIQZ0J.png)| 彩虹接地器 | 在這個黑白單調的世界裡,彩虹接地器不但能繽紛你的世界,還能降低你的電壓。 | 使用者電壓值-25V | | ![](https://i.imgur.com/Z8jy85o.jpg) | 無敵電池 | 吃了這個電池將使得小電球的大小變為1.5倍,且不受他人電擊或道具影響,讓你在短時間內所向披靡! | 使用者獲得5s無敵時間,攻擊範圍1.5倍,大小變為1.5倍 | ### 禮物 | Figure | Name | Description | Effect | |:------------------------------------:|:--------:|:--------------------: | --- | | ![](https://i.imgur.com/VAcFpRn.png =100x) | 禮物 | 覺得遊戲步調太慢了嗎?覺得自己太電,道具不敷使用嗎?從天而降來自聖誕老公公的禮物盒將顛覆你的想像。搶到禮物盒之後,如洪水般的道具將淹沒所有小電球,使得再電的小電球都變得「眼撲朔,腳迷離」| 在遊戲最後的1分鐘內出現,碰到後在短時間內將會大量產生道具 | ### 道具卡 * 取得方式:在課堂上回答問題! | 實體卡 | 效果 | 實體卡 | 效果 | | :------: |:--------------: | :------: |:--------------: | | ![](https://i.imgur.com/nECUwFx.png =150x) | 攻擊範圍增加1% |![](https://i.imgur.com/mouPDny.png =150x) | 放電威力增加1% | |![](https://i.imgur.com/pK62WcL.png =150x) | 水平移動速度增加1% |![](https://i.imgur.com/3j6Idgx.png =150x)| 攻擊冷卻時間減少1% | ### 計分方式 | Events | Score | | :---------------: | :----: | | 將對手 K.O. | +300 | | 死亡 | -150 | | 我就電 (擊殺數最高者) | +500 | | 我就怕 (從未死亡) | +2000 | * KO判定: ``` if A 死亡: if A 在 3 秒內被 B 攻擊過: 判定 B KO A (B得分) elif A 在 3 秒內被 C 碰撞過: 判定 C KO A (C得分) else: 判定 A 是自己跳下去的 * 重點:假如 A 死亡前 3 秒被 B 攻擊過,也被 C 碰撞過,則 B 得分,C 不得分。 ``` ### 物理模型(有興趣再看,沒興趣可以跳過) (長度單位pixel, 時間單位s) 1. 重力加速度為 $a=70$ ,方向向下。 2. 水平的初速度,遊戲開始時為 $v=300$ ,結束時為 $v=600$ ,以二次函數方式增長。 3. 跳躍的初速度 $v=1500$ 。 4. 摩擦力造成之加速度為 $\overrightarrow{a}=-k\widehat{v}$ , $k=6000$ 。 5. 空氣阻力造成之加速度為 $\overrightarrow{a}=-k\overrightarrow{v}$ , $k=3$ 。 6. 放電加速度為 $a=\displaystyle\frac{100000\times (1+0.02V)}{d}$ ,方向為遠離攻擊者的方向,$V$ 為被攻擊者電壓,$d$ 為攻擊者與被攻擊者間的距離。 7. 放電增加電壓為 $\displaystyle\Delta V=\frac{1000}{d}$。 8. 玩家間的碰撞為彈性碰撞,與平台的碰撞會損失一些動能 ## TeamAI - 檔案: - 檔名要取 team_{NAME}.py,NAME 長度盡量不要超過8個字元(會超出計分板寬度),只能是英文大小寫或數字 `eg: team_kaguya.py team_Rem.py team_Emilia.py ......` - 程式檔案要放在 `AI` 資料夾中 - AI 的運作方式: - 在每個 tick (六十分之一秒),主程式會呼叫你們的 `TeamAI` 的 `decide()` 函數,問它在這個 tick 想要做什麼動作。你們寫的`decide()` 必須回傳8個動作的其中一個,分別是向左移動、向右移動、跳、向左跳、向右跳、攻擊、使用道具、什麼事都不做。 - `TeamAI`裡面有兩個variables,分別是`helper`和`enhancement`。`helper`會提供各種函數來讓`TeamAI`知道場上的資訊,因此你們的`TeamAI`應該根據`helper`提供的資訊來做適當的判斷。`enhancement`是道具卡的數量,依序是攻擊範圍、水平移動速度、攻擊威力、冷卻時間。 - 範例程式(team_default.py) ```python= # action AI_DIR_LEFT = 0 AI_DIR_RIGHT = 1 AI_DIR_JUMP = 2 AI_DIR_LEFT_JUMP = 3 AI_DIR_RIGHT_JUMP = 4 AI_DIR_ATTACK = 5 AI_DIR_USE_ITEM = 6 AI_DIR_STAY = 7 # item_id NO_ITEM = 0 BANANA_PISTOL = 1 BIG_BLACK_HOLE = 2 CANCER_BOMB = 3 ZAP_ZAP_ZAP = 4 BANANA_PEEL = 5 RAINBOW_GROUNDER = 6 INVINCIBLE_BATTERY = 7 class TeamAI: def __init__(self, helper): self.helper = helper self.enhancement = [0, 0, 0, 0] def decide(self): if self.helper.get_self_keep_item_id() != NO_ITEM: return AI_DIR_USE_ITEM # get distance to other player distance = self.helper.get_all_player_distance() distance.pop(self.helper.get_self_id()) if self.helper.get_self_can_attack() and\ min(d for d in distance if not d is None) < self.helper.get_self_attack_radius(): return AI_DIR_ATTACK platform_id = self.helper.get_above_which_platform(self.helper.get_self_position()) if platform_id != -1: # go to middle of the platform platform_pos = self.helper.get_platform_position()[platform_id] platform_mid = ((platform_pos[0][0] + platform_pos[1][0]) / 2, platform_pos[0][1]) return self.helper.walk_to_position(platform_mid) else: # go to closest platform pos = self.helper.get_self_position() closest_land_vec = self.helper.get_position_vector_to_closest_land() closest_land_pos = (pos[0] + closest_land_vec[0], pos[1] + closest_land_vec[1]) return self.helper.walk_to_position(closest_land_pos) ``` ## Helper :::info function_name(): 回傳值型別 ::: ### 獲取常數專區 * `player_id: int` * 玩家編號 ### 獲取遊戲資訊專區 * `get_game_left_time(): int` * 獲得遊戲剩下時間 * `get_game_stage(): int` * 獲到場地編號 * 場地1編號為0,場地2編號為1,場地3編號為2 * `get_game_arena_boundary(): tuple(tuple(int, int), tuple(int, int))` * 獲得場地邊界的左上角及右下角座標 * `get_game_life_boundary(): tuple(tuple(int, int), tuple(int, int))` * 獲得死亡邊界的左上角及右下角座標 * `get_game_gravity_acceleration(): float` * 獲得場地的重力加速度 * `get_live_player_num(): int` * 獲得存活玩家數量 ### 獲取個人資訊專區 * `get_self_id(): int` * 獲得自己的id * `get_self_position(): tuple(float, float)` * 獲得自己的位置 * 如果自己已經沒有命則回傳`None` * `get_self_velocity(): tuple(float, float)` * 獲得自己的速度 * 如果自己已經沒有命則回傳`None` * `get_self_direction(): tuple(int, int)` * 獲得自己的水平方向方向,回傳值只有`(1, 0)`和`(-1, 0)`,分別代表向右和向左 * 如果自己已經沒有命則回傳`None` * `get_self_normal_speed(): float` * 獲得自己 x 方向的移動速度,即按下向左和向右獲得的速度 * 如果自己已經沒有命則回傳`None` * `get_self_jump_speed(): float` * 獲得自己跳躍速度,即按下跳躍獲得的速度 * 如果自己已經沒有命則回傳`None` * `get_self_keep_item_id(): int` * 獲得自己擁有的道具編號 * 如果自己已經沒有命則回傳`None` * `get_self_voltage(): float` * 獲得自己的電壓 * 如果自己已經沒有命則回傳`None` * `get_self_radius(): float` * 獲得自己的半徑 * 如果自己已經沒有命則回傳`None` * `get_self_attack_radius(): float` * 獲得自己的攻擊半徑 * 如果自己已經沒有命則回傳`None` * `get_self_is_invincible(): bool` * 獲得自己是否無敵 * 如果自己已經沒有命則回傳`None` * `get_self_invincible_time(): float` * 獲得自己無敵時間的剩餘時間 * 如果自己已經沒有命則回傳`None` * `get_self_is_controllable(): bool` * 獲得自己是否在可以控制的狀態 * 如果自己已經沒有命則回傳`None` * `get_self_uncontrollable_time(): float` * 獲得自己無法控制的時間的剩餘時間 * 如果自己已經沒有命則回傳`None` * `get_self_can_attack(): bool` * 獲得自己是否可以攻擊 * 如果自己已經沒有命則回傳`None` * `get_self_can_attack_time(): float` * 獲得自己攻擊冷卻的剩餘時間 * 如果自己已經沒有命則回傳`None` * `get_self_can_jump(): bool` * 獲得自己是否可以跳躍 * 如果自己已經沒有命則回傳`None` * `get_self_jump_quota(): int` * 獲得自己剩餘跳躍次數 * 如果自己已經沒有命則回傳`None` * `get_self_life(): int` * 獲得自己的剩餘生命數 * `get_self_score(): int` * 獲得自己的分數 * `get_self_jump_to_the_highest_time(): float` * 獲得自己到最高點的時間 * 如果y方向速度為正(向下),則回傳`0` * 如果自己已經沒有命則回傳`None` * `get_self_have_platform_below(): bool` * 獲得自己的正下方是否有平台 * 如果自己已經沒有命則回傳`None` ### 獲取所有玩家資訊專區 * `get_all_position(): [tuple(float, float), tuple(float, float), ......]` * 獲得所有的玩家的位置 * 沒有命的玩家的數值會是`None`,例如`[(0, 0), (1, 2), None, None]` 代表編號2, 3的玩家已經沒有命了 * `get_all_velocity(): [tuple(float, float), tuple(float, float), ......]` * 獲得所有玩家的速度 * 沒有命的玩家的數值會是`None` * `get_all_direction(): [tuple(int, int), tuple(int, int), ......]` * 獲得所有玩家的水平移動方向,回傳值只有`(1, 0)`和`(-1, 0)`,分別代表向右和向左 * 沒有命的玩家的數值會是`None` * `get_all_normal_speed(): [float, float, ......]` * 獲得所有玩家 x 方向的移動速度,即按下向左和向右獲得的速度 * 沒有命的玩家的數值會是`None` * `get_all_jump_speed(): [float, float, ......]` * 獲得所有玩家跳躍速度,即按下跳躍獲得的速度 * 沒有命的玩家的數值會是`None` * `get_all_keep_item_id(): [int, int, ......]` * 獲得所有玩家擁有的道具編號 * 沒有命的玩家的數值會是`None` * `get_all_voltage() [float, float, ......]` * 獲得所有玩家的電壓 * 沒有命的玩家的數值會是`None` * `get_all_radius(): [float, float, ......]` * 獲得所有玩家的半徑 * 沒有命的玩家的數值會是`None` * `get_all_attack_radius(): [float, float, ......]` * 獲得所有玩家的攻擊半徑 * 沒有命的玩家的數值會是`None` * `get_all_is_invincible(): [bool, bool, ......]` * 獲得所有玩家是否無敵 * 沒有命的玩家的數值會是`None` * `get_all_invincible_time(): [float, float, ......]` * 獲得所有玩家無敵時間的剩餘時間 * 沒有命的玩家的數值會是`None` * `get_all_is_controllable(): [bool, bool, ...]` * 獲得所有玩家是否在可以控制的狀態 * 沒有命的玩家的數值會是`None` * `get_all_uncontrollable_time(): [float, float, ......]` * 獲得所有玩家無法控制的時間的剩餘時間 * 沒有命的玩家的數值會是`None` * `get_all_can_attack(): [bool, bool, ......]` * 獲得所有玩家是否可以攻擊 * 沒有命的玩家的數值會是`None` * `get_all_can_attack_time(): [float, float, ......]` * 獲得所有玩家攻擊冷卻的剩餘時間 * 沒有命的玩家的數值會是`None` * `get_all_can_jump(): [bool, bool, ...]` * 獲得所有玩家是否可以跳躍 * 沒有命的玩家的數值會是`None` * `get_all_jump_quota(): [int, int, ......]` * 獲得所有玩家剩餘跳躍次數 * 沒有命的玩家的數值會是`None` * `get_all_life(): [int, int, ......]` * 獲得所有玩家的剩餘生命數 * `get_all_score(): [int, int, ......]` * 獲得所有玩家的分數 * `get_all_jump_to_the_highest_time() [float, float, ......]:` * 獲得所有玩家到最高點的時間 * 如果該玩家的y方向速度為正(向下),時間為`0` * 沒有命的玩家的數值會是`None` * `get_all_player_vector(): [tuple(float, float), tuple(float, float), ......]` * 獲得自己位置到所有玩家位置的方向向量(包含自己到自己的方向向量) * 沒有命的玩家的數值會是`None` * `get_all_player_distance(): [float, float, ......]` * 獲得自己與所有玩家的距離(包含自己到自己的距離) * 沒有命的玩家的數值會是`None` ### 獲取特定玩家資訊專區 * `get_other_position(player_id): tuple(float, float)` * 獲得特定玩家的位置 * 如果該玩家沒有命了,回傳`None` * `get_other_velocity(player_id): tuple(float, float)` * 獲得特定玩家的速度 * 如果該玩家沒有命了,回傳`None` * `get_other_direction(player_id): tuple(int, int)` * 獲得特定玩家的水平移動方向,回傳值只有`(1, 0)`和`(-1, 0)`,分別代表向右和向左 * 如果該玩家沒有命了,回傳`None` * `get_other_normal_speed(player_id): float` * 獲得特定玩家 x 方向的移動速度,即按下向左和向右獲得的速度 * 如果該玩家沒有命了,回傳`None` * `get_other_jump_speed(player_id): float` * 獲得特定玩家跳躍速度,即按下跳躍獲得的速度 * 如果該玩家沒有命了,回傳`None` * `get_other_keep_item_id(player_id): int` * 獲得特定玩家擁有的道具編號 * 如果該玩家沒有命了,回傳`None` * `get_other_voltage(player_id): float` * 獲得特定玩家的電壓 * 如果該玩家沒有命了,回傳`None` * `get_other_radius(player_id): float` * 獲得特定玩家的半徑 * 如果該玩家沒有命了,回傳`None` * `get_other_attack_radius(player_id): float` * 獲得特定玩家的攻擊半徑 * 如果該玩家沒有命了,回傳`None` * `get_other_is_invincible(player_id): bool` * 獲得特定玩家是否無敵 * 如果該玩家沒有命了,回傳`None` * `get_other_invincible_time(player_id): float` * 獲得特定玩家無敵時間的剩餘時間 * 如果該玩家沒有命了,回傳`None` * `get_other_is_controllable(player_id): bool` * 獲得特定玩家是否處於可以控制的狀態 * 如果該玩家沒有命了,回傳`None` * `get_other_uncontrollable_time(player_id): float` * 獲得特定玩家無法控制的時間的剩餘時間 * 如果該玩家沒有命了,回傳`None` * `get_other_can_jump(player_id): bool` * 獲得特定玩家是否可以跳躍 * 如果該玩家沒有命了,回傳`None` * `get_other_jump_quota(player_id): int` * 獲得特定玩家剩餘跳躍次數 * 如果該玩家沒有命了,回傳`None` * `get_other_can_attack(player_id): bool` * 獲得特定玩家是否可以攻擊 * 如果該玩家沒有命了,回傳`None` * `get_other_can_attack_time(player_id): float` * 獲得特定玩家攻擊冷卻的剩餘時間 * 如果該玩家沒有命了,回傳`None` * `get_other_life(player_id): int` * 獲得特定玩家的剩餘生命數 * `get_other_score(player_id): int` * 獲得特定玩家的分數 * `get_other_jump_to_the_highest_time(player_id): float` * 獲得特定玩家到最高點的時間 * 如果y方向速度為正(向下),回傳`0` * 如果該玩家沒有命了,回傳`None` * `get_other_have_platform_below(player_id): bool` * 獲得特定玩家下方是否有平台 * 如果該玩家沒有命了,回傳`None` * `get_other_player_vector(player_id): tuple(float, float)` * 獲得自己位置到特定玩家位置的方向向量 * 如果該玩家沒有命了,回傳`None` * `get_other_player_distance(player_id): float` * 獲得自己與特定玩家的距離 * 如果該玩家沒有命了,回傳`None` ### 獲取平台資訊專區 * `get_platform_position(): [tuple(tuple(float, float), ...]` * 獲得所有平台的左上角位置與右下角位置 * `get_distance_to_closest_land(): float` * 計算最近的陸地距離 * `get_position_vector_to_closest_land(): tuple(float, float)` * 計算所在位置到最近的陸地的向量 * `get_above_which_platform(position): int` * 回傳該位置位於哪個平台之上。 * 如果該位置在某個平台之上,回傳該平台在 `get_platform_position` 中的index;如果不在任何平台上,則回傳`-1` * 注意:此函式判斷時以該平台的上緣為基準,如給此函式在平台中間的位置(如長方形的內部),則程式不會判斷此點在該平台上 ### 獲取道具資訊專區 * `item_exists(): bool` * 詢問地圖上是否有道具 * `get_nearest_item_position(): tuple(float, float)` * 獲得最近道具的位置,如果沒有道具,則回傳`None` * `get_nearest_specific_item_position(item_id): tuple(float, float)` * 獲得特定道具最近的位置,如果沒有該道具,則回傳`None` * `get_all_item_position(): [tuple(float, float), ......]` * 獲得所有道具的位置 * 如果沒有道具則回傳`[]` * `get_all_banana_pistol_position(): [tuple(float, float), ......]` * 獲得所有蕉蕉手槍的位置 * 如果沒有該道具則回傳`[]` * `get_all_banana_pistol_velocity(): [tuple(float, float), ......]` * 獲得所有蕉蕉手槍的速度 * 如果沒有該道具則回傳`[]` * `get_all_big_black_hole_position(): [tuple(float, float), ......]` * 獲得所有大黑洞的位置 * 如果沒有該道具則回傳`[]` * `get_all_big_black_hole_velocity(): [tuple(float, float), ......]` * 獲得所有大黑洞的速度 * 如果沒有該道具則回傳`[]` * `get_all_cancer_bomb_position(): [tuple(float, float), ......]` * 獲得所有毒瘤炸彈的位置 * 如果沒有該道具則回傳`[]` * `get_all_cancer_bomb_velocity(): [tuple(float, float), ......]` * 獲得所有毒瘤炸彈的速度 * 如果沒有該道具則回傳`[]` * `get_all_zap_zap_zap_position(): [tuple(float, float), ......]` * 獲得所有電電電的位置 * 如果沒有該道具則回傳`[]` * `get_all_zap_zap_zap_velocity(): [tuple(float, float), ......]` * 獲得所有電電電的速度 * 如果沒有該道具則回傳`[]` * `get_all_banana_peel_position(): [tuple(float, float), ......]` * 獲得所有香蕉皮的位置 * 如果沒有該道具則回傳`[]` * `get_all_banana_peel_velocity(): [tuple(float, float), ......]` * 獲得所有香蕉皮的速度 * 如果沒有該道具則回傳`[]` * `get_all_rainbow_grounder_position(): [tuple(float, float), ......]` * 獲得所有彩虹接地器的位置 * 如果沒有該道具則回傳`[]` * `get_all_rainbow_grounder_velocity(): [tuple(float, float), ......]` * 獲得所有彩虹接地器的速度 * 如果沒有該道具則回傳`[]` * `get_all_invincible_battery_position(): [tuple(float, float), ......]` * 獲得所有無敵電池的位置 * 如果沒有該道具則回傳`[]` * `get_all_invincible_battery_velocity(): [tuple(float, float), ......]` * 獲得所有無敵電池的的速度 * 如果沒有該道具則回傳`[]` ### 獲取物件資訊專區 * `entity_exists(): bool` * 檢查場上是否存在物件,有則回傳True,沒有則回傳False * `get_all_entity_position(): [tuple(float, float), ......]` * 回傳場上所有物件的位置 * 如果沒有該物件則回傳`[]` * `get_all_drop_pistol_bullet_position(): [tuple(float, float), ......]` * 回傳場上所有蕉蕉手槍子彈的位置 * 如果沒有該物件則回傳`[]` * `get_all_drop_pistol_bullet_timer(): [float, float, ......]` * 回傳場上所有蕉蕉手槍子彈的剩餘存活時間 * 如果沒有該物件則回傳`[]` * `get_all_pistol_bullet_velocity(): [tuple(float, float), ......]` * 回傳場上所有蕉蕉手槍子彈的速度 * 如果沒有該物件則回傳`[]` * `get_nearest_drop_pistol_bullet_position(): tuple(float, float)` * 回傳場上最近蕉蕉手槍子彈的位置 * 如果沒有該物件則回傳`None` * `get_all_drop_banana_peel_position(): [tuple(float, float), ......]` * 回傳場上所有香蕉皮的位置 * 如果沒有該物件則回傳`[]` * `get_all_drop_banana_peel_timer(): [float, float, ......]` * 回傳場上所有香蕉皮的剩餘存活時間 * 如果沒有該物件則回傳`[]` * `get_nearest_drop_banana_peel_position(): tuple(float, float)` * 回傳場上最近香蕉皮的位置 * 如果沒有該物件則回傳`None` * `get_all_drop_cancer_bomb_position(): [tuple(float, float), ......]` * 回傳場上所有毒瘤炸彈的位置 * 如果沒有該物件則回傳`[]` * `get_all_drop_cancer_bomb_timer(): [float, float, ......]` * 回傳場上所有毒瘤炸彈的爆炸剩餘時間 * 如果沒有該物件則回傳`[]` * `get_nearest_drop_cancer_bomb_position(): tuple(float, float)` * 回傳場上最近毒瘤炸彈的位置 * 如果沒有該物件則回傳`None` * `get_all_drop_big_black_hole_position(): [tuple(float, float), ......]` * 回傳場上所有大黑洞的位置 * 如果沒有該物件則回傳`[]` * `get_all_drop_big_black_hole_timer(): [float, float, ......]` * 回傳場上所有大黑洞的剩餘存活時間 * 如果沒有該物件則回傳`[]` * `get_nearest_drop_big_black_hole_position(): tuple(float, float)` * 回傳場上最近大黑洞的位置 * 如果沒有該物件則回傳`None` * `get_black_hole_effect_radius(): int` * 獲得大黑洞的影響範圍半徑 * `get_cancer_bomb_effect_radius(): int` * 獲得毒瘤炸彈的影響範圍半徑 * `get_zap_zap_zap_effect_range(): int` * 獲得電電電的水平影響範圍 ### 獲取特別資訊專區 * `get_nearest_player(): int` * 獲得除自己以外場上最近的活著玩家 player_id * 如果有多個玩家都是最近的,回傳 player_id 最小者 * 如果沒有符合的玩家,回傳 `None` * `get_nearest_player_position(): tuple(float, float)` * 獲得除自己以外場上最近的活著玩家的位置 * 如果有多個玩家都是最近的,回傳 player_id 最小者的位置 * 如果沒有符合的玩家,回傳 `None` * `get_highest_voltage_player(): int` * 獲得除自己以外電壓最高的活著玩家 player_id * 如果有多個玩家電壓都是最高的,回傳 player_id 最小者 * 如果沒有符合的玩家,回傳 `None` * `get_highest_score_player(): int` * 獲得除自己以外分數最高的活著玩家 player_id * 如果有多個玩家分數都是最高的,回傳 player_id 最小者 * 如果沒有符合的玩家,回傳 `None` * `get_gift_position(): tuple(float, float)` * 獲得禮物盒的位置 * 如果沒有禮物盒,回傳`None` * `get_gift_velocity(): tuple(float, float)` * 獲得禮物盒的速度 * 如果沒有禮物盒,回傳`None` * `get_distance(position1, position2): float` * 計算兩點之間的距離 * `get_vector(position1, position2): tuple(float, float)` * 獲得position1到position2的位置向量 ### 新手友善(懶人)特別專區 * `walk_to_position(position): command` * 只要輸入位置,這個函式就可以回傳讓AI自動地走到指定位置當前所需的指令,並且有一定的防掉落能力 * 注意1:該函式不是距離最短或最優化,並且該函式無法躲避任何攻擊,就只是單純地走到指定位置 * 注意2:若想在原本平台平移,y座標請直接使用平台最上方的y座標,無須特意選平台內的點(如長方形中心),否則小則不動、繞遠路,大則自殺 * 注意3:儘管這個函數有一定的防掉落能力,但如果你指定小電球走到一個會掉下去的地方,它還是會依照你的指示去做