From 4e8525f4cf7efbdbeaeec8de3f0e3886b80bc9ad Mon Sep 17 00:00:00 2001 From: Jerry Wu Date: Fri, 1 Jun 2018 18:17:10 +0800 Subject: [PATCH] first stable version --- card.py | 289 +++++++++++++++++---------------- game.py | 53 ++---- pyws.py | 131 ++++++++++----- room.py | 471 +++++++++++++++++++++++++++++++++--------------------- spec.json | 388 ++++++++++++++++++++++---------------------- 5 files changed, 737 insertions(+), 595 deletions(-) diff --git a/card.py b/card.py index 1c09e68..ebce663 100644 --- a/card.py +++ b/card.py @@ -3,6 +3,7 @@ import game from room import Room from json import dumps + cards = dict() card_name = ["1.攻擊","2.防禦","3.治癒","4.補給","5.強奪","6.奇襲","7.交易","8.洞悉","9.妙策","10.掃射","11.加護","12.劇毒","13.詛咒","14.反制","15.狂亂","16.逆轉"] unattackable = ['2','8','14','17','18'] @@ -10,9 +11,14 @@ unrobable = ['8','17','18'] for i in range(len(card_name)): cards[str(i+1)] = card_name[i] # initialize cards # create default deck -# 攻擊*15 防禦*15 治癒*15 補給*10 強奪*10 奇襲*10 交易*10 洞悉*5 妙策*5 掃射*5 加護*5 劇毒*2 詛咒*2 反制*2 狂亂*2 逆轉*2 -#default_deck = ['1', '2', '3'] * 5 + ['4', '5', '6', '7'] * 3 + ['8', '9', '10', '11'] * 2 + ['12', '13', '14', '15', '16'] -default_deck = ['3', '4', '2', '1']*15 +""" +攻擊*7 防禦*7 治癒*7 +補給*4 強奪*4 奇襲*4 交易*4 +洞悉*2 妙策*2 掃射*2 加護*2 +劇毒*1 詛咒*1 反制*1 狂亂*1 逆轉*1 +""" +default_deck = ['1', '2', '3'] * 7 + ['4', '5', '6', '7'] * 4 + ['8', '9', '10', '11'] * 2 + ['12', '13', '14', '15', '16'] + random.shuffle(default_deck) # wash # card functions @@ -26,11 +32,10 @@ def attack(wscur, wsene): r = [] cur.damage = 2 # 給反制判斷的 - r.append(( (wscur, ), dumps({"msg": "attack", "data": [cur.name, ene.name]}))) + r.append(( (wscur, wsene), dumps({"msg": "attack", "data": [cur.name, ene.name]}))) if ene.defence(): r.append(( (wsene, ), - dumps({"msg": "attack", "data": [cur.name, ene.name], - "action": "toDefend", "value": {"damage": cur.damage}}) + dumps({"action": "toDefend", "value": {"damage": cur.damage, "type": "attack"}}) )) cur.status = Room.NOTHING ene.status = Room.DEFENCE @@ -38,7 +43,10 @@ def attack(wscur, wsene): r.append(( (wsene, wscur), dumps({"msg": "damaged", "data": [ene.name, cur.damage]}) )) + + cur.status = Room.NOTHING ene.life -= cur.damage + r.extend(Room.start_turn(wsene, wscur)) cur.attacking = False cur.damage = 0 # reset """ @@ -62,10 +70,10 @@ def defend(wscur,wsene): # cur是用卡方 cur, ene = wscur.player, wsene.player r = [] if ene.attacking or ene.surprise: - r.append(( (wsene,wscur), "{} 防禦成功".format(cur.name))) + r.append(( (wsene,wscur), dumps({"msg": "defended", "data": [cur.name]}))) else: - r.append(( (wsene,wscur), "{} 沒什麼可以防禦的,回復一點生命".format(cur.name))) + r.append(( (wsene,wscur), dumps({"msg": "defend", "data": [cur.name]}))) cur.life += 1 return r @@ -89,209 +97,206 @@ def supply(wscur,wsene): def rob(wscur,wsene): cur, ene = wscur.player, wsene.player - - cur.robbing = True - print("{} 正在對 {} 行搶".format(cur.name,ene.name)) - if ene.keep(): - game.display(ene) # 顯示手牌 - while True: - choice = input("請問要防禦嗎? 不使用請輸入0 ") - if choice in ene.hand: - if choice in unrobable: - skills[choice](cur,ene) - ene.remove_card(choice) - break - elif choice == "0": - break - else: - if len(ene.hand) == 0: - print("可惜,{} 有夠窮,沒東西能搶".format(ene.name)) - else: - game.display(ene) - while True: - swag = input("{} 要搶哪張?".format(cur.name)) - if swag in ene.hand: - ene.robbed(swag) - cur.add_card(swag) - break - cur.robbing = False + r = [] + r.append(( (wscur, ), dumps({"msg": "rob", "data": [cur.name, ene.name], + "action": "toRob", "value": {"enemy_card": ene.hand}}))) + + cur.status = Room.ROBBING + r.append(( (wsene, ), dumps({"msg": "rob", "data": [cur.name, ene.name]}))) + return r def surprise(wscur,wsene): cur, ene = wscur.player, wsene.player - cur.surprise = True - cur.damage = 1 # 給反制判斷 - print("{} 發動奇襲".format(cur.name)) + + r = [] + + cur.damage = 1 + r.append(( (wscur, wsene), dumps({"msg": "surprise", "data": [cur.name]}))) if ene.defence(): - game.display(ene) # 顯示手牌 - while True: - choice = input("請問要防禦嗎? 不使用請輸入0 ") - if choice in ene.hand: - if choice in unattackable: - skills[choice](cur,ene) - ene.remove_card(choice) - break - elif choice == "0": - print("{} 受到{}點傷害,而且掉了一張手牌".format(ene.name,cur.damage)) - ene.life -= cur.damage - drop = random.choice(ene.hand) - ene.remove_card(drop) - break + r.append(( (wsene, ), + dumps({"action": "toDefend", "value": {"damage": cur.damage, "type": "surprise"}}) + )) + cur.status = Room.NOTHING + ene.status = Room.DEFENCE else: - print("{} 受到{}點傷害,而且掉了一張手牌".format(ene.name,cur.damage)) + r.append(( (wsene, wscur), + dumps({"msg": "surprised", "data": [ene.name, cur.damage]}) + )) + + cur.status = Room.NOTHING ene.life -= cur.damage drop = random.choice(ene.hand) ene.remove_card(drop) - cur.surprise = False - cur.damage = 0 # reset + cur.surprise = False + cur.damage = 0 # reset + + r.extend(Room.start_turn(wsene, wscur)) + + return r def trade(wscur,wsene): cur, ene = wscur.player, wsene.player - - print("{} 想與 {} 進行交易".format(cur.name,ene.name)) - cur.remove_card("7") # you can't trade the using card "trade" - game.display(cur) # 顯示手牌 - while True: - choice = input("選擇一張手牌以交換 ") - if choice in cur.hand: - cur_item = choice - print("{} 選擇了 {}".format(cur.name,cards[choice])) - break - game.display(ene) # 顯示手牌 - while True: - choice = input("選擇一張手牌以交換 ") - if choice in ene.hand: - ene_item = choice - print(ene.name,"choose",cards[choice]) - break - # current player part - cur.hand.remove(cur_item) - cur.display.remove(cards[cur_item]) - cur.hand.append(ene_item) - cur.display.append(cards[ene_item]) - # enemy part - ene.hand.remove(ene_item) - ene.display.remove(cards[ene_item]) - ene.hand.append(cur_item) - ene.display.append(cards[cur_item]) + r = [] + if ene.hand: + r.append(( (wsene, wscur), + dumps({"msg": "trade", "data": [cur.name, ene.name]}) + )) - cur.add_card("7") # add back the card. game system will remove this card right away + r.append(( (wscur,), + dumps({"action": "toTrade", "value": {"hand": cur.hand}}) # 更新已被移除的trade + )) + cur.status = Room.TRADE + else: + r.append(( (wscur,wsene), + dumps({"msg": "tradeNoCard", "data": [cur.name]}) + )) + r.extend(Room.start_turn(wsene, wscur)) + + return r def aware(wscur,wsene): cur, ene = wscur.player, wsene.player - - if cur.attacking: - print("{} 洞悉了 {} 的攻擊,並抽取了一張手牌".format(ene.name,cur.name)) - game.draw(ene) - elif cur.robbing: - print("{} 洞悉了 {} 的強奪,並抽取了一張手牌".format(ene.name,cur.name)) - game.draw(ene) - elif cur.surprise: - print("{} 洞悉了 {} 的奇襲,並抽取了一張手牌".format(ene.name,cur.name)) - game.draw(ene) + r = [] + if ene.attacking: + r.append(( (wsene,wscur), dumps({"msg": "awared", "data": [cur.name, ene.name, "攻擊"]}))) + + elif ene.robbing != "0": + r.append(((wscur, wsene), dumps({"msg": "awared", "data": [cur.name, ene.name, "搶奪"]}))) + + elif ene.surprise: + r.append(( (wsene,wscur), dumps({"msg": "awared", "data": [cur.name, ene.name, "奇襲"]}))) + else: + r.append(((wscur, wsene), dumps({"msg": "aware", "data": [cur.name]}))) for _ in range(3): - print("{} 增加三張手牌".format(cur.name)) game.draw(cur) + + return r def plan(wscur,wsene): cur, ene = wscur.player, wsene.player + r = [] + + r.append(( (wsene, wscur), + dumps({"msg": "plan", "data": [cur.name]}) + )) - print("{} 有個妙策".format(cur.name)) options = random.sample(cur.deck,3) - o_name = [] # names of cards in options - for id in options: - o_name.append(cards[id]) - print(o_name) - while True: + r.append(( (wscur, ), + dumps({"action": "toAdd", "value": {"cards": options}}) + )) + cur.planning = options + cur.status = Room.PLAN + """while True: choice = input("選擇一張卡加入手牌 ") if choice in options: cur.add_card(choice) - break + break""" + return r def sweep(wscur,wsene): cur, ene = wscur.player, wsene.player - cur.attacking = True + + r = [] + cur.damage = random.randint(0,5) - print("{} 對 {} 進行掃射,威力是 {}".format(cur.name,ene.name,cur.damage)) + r.append(( (wscur, wsene), dumps({"msg": "sweep", "data": [cur.name, ene.name, cur.damage]}))) if ene.defence(): - game.display(ene) # 顯示手牌 - while True: - choice = input("請問要防禦嗎? 不使用請輸入0 ") - if choice in ene.hand: - if choice in unattackable: - skills[choice](cur,ene) - ene.remove_card(choice) - break - elif choice == "0": - print("{} 受到{}點傷害".format(ene.name,cur.damage)) - ene.life -= cur.damage - break + r.append(( (wsene, ), + dumps({"action": "toDefend", "value": {"damage": cur.damage, "type": "sweep"}}) + )) + cur.status = Room.NOTHING + ene.status = Room.DEFENCE else: - print("{} 受到{}點傷害".format(ene.name,cur.damage)) + r.append(( (wsene, wscur), + dumps({"msg": "damaged", "data": [ene.name, cur.damage]}) + )) + + cur.status = Room.NOTHING ene.life -= cur.damage - cur.attacking = False - cur.damage = 0 # reset + r.extend(Room.start_turn(wsene, wscur)) + cur.attacking = False + cur.damage = 0 # reset + + return r + def bless(wscur,wsene): cur, ene = wscur.player, wsene.player - - print("{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌".format(cur.name)) + r = [] + r.append(( (wsene,wscur), dumps({"msg": "bless", "data": [cur.name]}))) + cur.poison = 0 # 解毒 cur.life += 3 + for _ in range(2): game.draw(cur) - + return r def poison(wscur,wsene): cur, ene = wscur.player, wsene.player - - if ene.poison != 0: - s = "又" - else: - s = "" - print("{} 在食物下毒,{} {}中毒了".format(cur.name,ene.name, s)) + r = [] + r.append(( (wsene,wscur), dumps({"msg": "poison", "data": [cur.name, ene.name]}))) + ene.poison += 1 + return r def curse(wscur,wsene): cur, ene = wscur.player, wsene.player + r = [] - print("{} 詛咒了 {},使其損失四點生命,並掉了一張手牌".format(cur.name,ene.name)) + ene.life -= 4 - drop = random.choice(ene.hand) - ene.remove_card(drop) + + msg = "curseNoCard" + if ene.hand: + drop = random.choice(ene.hand) + ene.remove_card(drop) + msg = "curse" + r.append(( (wsene,wscur), dumps({"msg": msg, "data": [cur.name, ene.name]}))) + return r def counter(wscur,wsene): cur, ene = wscur.player, wsene.player + r = [] - if cur.attacking: - print("{} 反制了 {} 的攻擊,反彈了{}點傷害".format(ene.name,cur.name,cur.damage)) - cur.life -= cur.damage - elif cur.surprise: - print("{} 反制了 {} 的奇襲,反彈了{}點傷害,並使其掉了一張手牌".format(ene.name,cur.name,cur.damage)) - cur -= cur.damage - drop = random.choice(cur.hand) - cur.remove_card(drop) + if ene.attacking: + r.append(( (wsene,wscur), dumps({"msg": "countered", "data": [cur.name, ene.name, ene.damage]}))) + ene.life -= ene.damage + elif ene.surprise: + r.append(( (wsene,wscur), dumps({"msg": "counteredSur", "data": [cur.name, ene.name, ene.damage]}))) + ene.life -= ene.damage + drop = random.choice(ene.hand) + ene.remove_card(drop) else: - print("{} 反制了敵手,使 {} 生命值減半了!".format(cur.name,ene.name)) + r.append(( (wsene,wscur), dumps({"msg": "counter", "data": [cur.name, ene.name]}))) ene.life = ene.life//2 + + return r def chaos(wscur,wsene): cur, ene = wscur.player, wsene.player - - print("{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害".format(cur.name,ene.name)) + r = [] + r.append(( (wsene,wscur), dumps({"msg": "reverse", "data": [cur.name, ene.name]}))) + cur.life += 3 ene.life -= 3 - + return r + def reverse(wscur,wsene): cur, ene = wscur.player, wsene.player + r = [] + r.append(( (wsene,wscur), dumps({"msg": "reverse", "data": [cur.name]}))) + - print("{} 一口氣逆轉了情勢".format(cur.name)) cur.life,ene.life = ene.life,cur.life + return r skills = dict() skill_name = [attack,defend,heal,supply,rob,surprise,trade,aware,plan,sweep,bless,poison,curse,counter,chaos,reverse] for i in range(len(skill_name)): skills[str(i+1)] = skill_name[i] + diff --git a/game.py b/game.py index 5ad9817..43a38d9 100644 --- a/game.py +++ b/game.py @@ -8,13 +8,15 @@ class Player: self.name = name self.deck = deck[:] # to pass by value instead of by reference self.hand = [] - self.display = [] # names of cards in hand - self.life = 20 + self.status = -1 + self.life = 15 self.poison = 0 self.damage = 0 # 因為反制要拿來判斷掃射 self.playing = False self.attacking = False - self.robbing = False + self.robbing = "0" + self.planning = [] # data temp for plan + self.trading = "0" # data temp for trade self.surprise = False # 又是因為反制要判斷奇襲 self.turn = 0 @@ -27,18 +29,17 @@ class Player: def add_card(self,id): self.hand.append(id) - self.display.append(card.cards[id]) self.deck.remove(id) def remove_card(self,id): self.hand.remove(id) - self.display.remove(card.cards[id]) self.deck.append(id) def robbed(self,id): # be robbed - self.hand.remove(id) - self.display.remove(card.cards[id]) - + try: + self.hand.remove(id) + except: + print("rob except:", id, self.hand) def defence(self): # to decide if player is able to defend or not for c in self.hand: if c in card.unattackable: @@ -65,7 +66,7 @@ def display(player): def draw(player): # 抽卡 if len(player.deck) == 0: player.life = -99999999 # 牌抽乾了就讓他死 - return dumps({"msg": "noCard", "data": [player.name]}) + return False new = random.choice(player.deck) player.add_card(new) @@ -73,37 +74,3 @@ def draw(player): # 抽卡 # turn control # cur:current player # ene:enemy -async def turn(wsp1,wsp2): - p1, p2 = wsp1.player, wsp2.player - wscur, wsene = (wsp1, wsp2) if p1.playing == True else (wsp2, wsp1) - - cur, ene = wscur.player, wsene.player - - cur.turn += 1 - - await wscur.send("{} 的第{}回合".format(cur.name,cur.turn)) - if cur.poison_check(): - await wscur.send("{} 受到了劇毒的侵蝕".format(cur.name)) - await wscur.send("{} 損失{}點生命".format(cur.name,cur.poison)) - if cur.life <= 0: - return - await sendTo(health(p1,p2), wsp1, wsp2) - await sendTo(draw(cur), wsp1, wsp2) # 抽卡 - await sendTo(display(cur), wscur) # 顯示手牌 - while True: - await sendTo("請問要使用手牌嗎? 若不使用請輸入0", wscur) - print("Wait receive") - choice = await wscur.recv() - print("Received") - if choice in cur.hand: - card.skills[choice](wscur, wsene) - cur.remove_card(choice) - break - elif choice == "0": - break - elif choice == "-1": - cur.surrender() - await sendTo("{}投降".format(cur.name), wsp1, wsp2) - break - del choice # prevent reading old data - p1.playing,p2.playing = p2.playing,p1.playing # switch! diff --git a/pyws.py b/pyws.py index cff2ac7..ceb11ea 100644 --- a/pyws.py +++ b/pyws.py @@ -3,10 +3,11 @@ import game from room import Room, sendTo import asyncio -import datetime import random import websockets -from json import dumps, loads +from json import dumps, loads + +import ssl connected = {-1: []} character = dict() @@ -18,6 +19,7 @@ for i in range(len(name)): sad = None fut = None +wait_fut = [0, 0] async def wait(websocket, *cors, timeout=45, futs=None): if futs != None: fut_cor = futs @@ -25,37 +27,31 @@ async def wait(websocket, *cors, timeout=45, futs=None): fut_cor = [cor() for cor in cors] done, pending = await asyncio.wait(fut_cor, return_when=asyncio.FIRST_EXCEPTION, timeout=timeout) - #print(done, pending) + + #print("Futures:", done, pending) if pending: - #print("coroutine doesn't finish its work") - pass + for task in pending: + task.cancel() + if len(done): - return list(done)[0].result() - else: - #print("SADDDDD") - return -def random_room(): - global connected, rooms - try: - print(rooms) - except: - rooms = list(connected) - rooms.remove(-1) - print(rooms) - while len(rooms)>=1: - enter = random.choice(rooms) - print("rooms", enter, rooms) - rooms.remove(enter) + if list(done)[0].exception() == None: + return list(done)[0].result() + else: + return "exception" +def random_room(room_list): + + while len(room_list)>=1: + enter = random.choice(room_list) + print("rooms", enter, room_list) if len(connected[enter]) < 2: return enter while 1: enter = random.randint(1, 99999) if enter not in connected: - rooms.append(enter) return enter - - + + async def enter_room(websocket): global connected ,sad, fut @@ -66,7 +62,7 @@ async def enter_room(websocket): message = await wait(websocket, websocket.recv) if message == "n": - room_id = random_room() + room_id = random_room(room_list) else: room_id = int(message) @@ -91,15 +87,16 @@ async def enter_room(websocket): for ws in connected[room_id]: ws.status = Room.PLAYING - wsene = connected[room_id].players[0] if connected[room_id].players[1] is websocket else connected[room_id].players[1] - await ws.send(dumps({"room": room_id, "cur": websocket.player.name, "ene": wsene.player.name})) + wsene = connected[room_id].players[0] if connected[room_id].players[1] is ws else connected[room_id].players[1] + await ws.send(dumps({"room": room_id, "cur": ws.player.name, "ene": wsene.player.name})) await ws.send(dumps({"msg": "firstAttack", "data": [players[0].player.name], "hand": ws.player.hand})) fut.cancel() for ws_list, message in Room.start_turn(*players): await sendTo(message, *ws_list) async def handler(websocket, path): - global connected,sad, fut + global connected,sad, fut, wait_fut, rooms + print("initialize") # Register. connected[-1].append(websocket) websocket.status = Room.CONNECTED @@ -113,7 +110,8 @@ async def handler(websocket, path): websocket.player = game.Player(name[int(choice)-1], card.default_deck) websocket.status = Room.MATCHING - except: + except Exception as e: + print(e) return # close the connection @@ -130,41 +128,92 @@ async def handler(websocket, path): print("SAD", "FIRST" if websocket == sad else "SECOND") fut = asyncio.ensure_future(websocket.recv()) + try: - message = await wait(websocket, timeout=100000, futs=[fut]) + message = await wait(websocket, timeout=100, futs=[fut]) + print(message) + print(fut) if message == "e": connected[websocket.room].player_delete(websocket) await websocket.send("You have left Room "+str(connected[websocket.room])) - del websocket.room + del connected[websocket.room] + del websocket.room connected[-1].append(websocket) websocket.status = Room.MATCHING + elif message == "exception": + break except asyncio.CancelledError: pass + print("SADDDDDD", "FIRST" if websocket == sad else "SECOND") elif websocket.status == Room.PLAYING: - print("wait for message", "FIRST" if websocket == sad else "SECOND") - message = await wait(websocket, websocket.recv, timeout=100000) - print("received message", "FIRST" if websocket == sad else "SECOND") + + try: + enemy = 0 if websocket == connected[websocket.room].players[1] else 1 + wait_fut[(enemy+1)%2] = asyncio.ensure_future(websocket.recv()) + + print("wait for", "FIRST" if websocket == sad else "SECOND") + message = await wait(websocket, timeout=30, futs=[wait_fut[(enemy+1)%2]]) + print("received message", message) + print("FIRST" if websocket == sad else "SECOND", ":", message) + if message == "exception": + break + message_to_send = connected[websocket.room].process(websocket, message) + for ws_list, message in message_to_send: + await sendTo(message, *ws_list) + if message_to_send != []: + try: + if loads(message_to_send[-1][1])['msg'] == 'win': # 取最後一筆訊息的msg + connected[websocket.room].player_delete(websocket) + break + except KeyError: + pass + wait_fut[enemy].cancel() # 取消另一方的await - message_to_send = connected[websocket.room].process(websocket, message) - for ws_list, message in message_to_send: - await sendTo(message, *ws_list) + + except asyncio.CancelledError: + print("FIRST" if websocket == sad else "SECOND", "was Canceled\n\n") + + + + elif websocket.status == Room.DISCONNECT: + break finally: # Unregister. try: - connected[websocket.room].player_delete(websocket) + + if websocket not in connected[websocket.room]: + connected[websocket.room].players[0].status = Room.DISCONNECT + wait_fut[0].cancel() + wait_fut[1].cancel() + + else: + if connected[websocket.room].player_delete(websocket): + await connected[websocket.room].players[0].send(dumps({"msg": "eneDisconn", "data": [connected[websocket.room].players[0].player.name]})) + connected[websocket.room].players[0].status = Room.DISCONNECT + wait_fut[0].cancel() + wait_fut[1].cancel() + + # it will leave the loop and disconnect + + + if len(connected[websocket.room]) == 0: # clear the dictionary + print("delete") + del connected[websocket.room] + except: connected[-1].remove(websocket) + print(connected) -"""cert = ssl.SSLContext() +cert = ssl.SSLContext() cert.load_cert_chain("/etc/letsencrypt/live/stoneapp.tech/fullchain.pem","/etc/letsencrypt/live/stoneapp.tech/privkey.pem") -start_server = websockets.serve(handler, '10.128.0.2', 8787,ssl=cert)""" +start_server = websockets.serve(handler, '10.128.0.2', 8787,ssl=cert) -start_server = websockets.serve(handler, '127.0.0.1', 9000) +#start_server = websockets.serve(handler, '127.0.0.1', 9000) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() diff --git a/room.py b/room.py index 27c60e2..acbc9af 100644 --- a/room.py +++ b/room.py @@ -1,178 +1,293 @@ -import game, card -import random -from json import dumps, loads - -class Room: - CONNECTED = 0 - MATCHING = 1 - PLAYING = 2 - WAITING = -1 - - # Player Status Definition - NOTHING = -1 - IN_TURN = 0 - ROBBED = 1 - DEFENCE = 2 - ROBBING = 3 - TRADE = 4 - PLAN = 5 - def __init__(self, room): - self.room = room - self.players = [] - - - def __len__(self): - return len(self.players) - - def __repr__(self): - return "ROOM {}, {} player(s)".format(str(self.room), len(self)) - - def __iter__(self): - return iter(self.players) - - def player_add(self, player): - if len(self) >= 2: - return - self.players.append(player) - - def player_delete(self, player): - try: - self.players.remove(player) - except: - pass - - - - """async def start(self): - p1, p2 = self.players[0].player, self.players[1].player - first = random.choice([p1, p2]) - print(first, p1, p2) - first.playing = True # so the first one will be random - await sendTo(first.name + "先攻", *self.players) - print(first.name,"先攻") - print() # change line - for _ in range(3): # 初始手牌*3 - game.draw(p1) - game.draw(p2) - - while p1.life > 0 and p2.life > 0: - print("game.turn start") - await game.turn(self.players[0], self.players[1]) - print("game.turn end") - if p1.life <= 0: - print("{} 獲勝".format(p2.name)) - elif p2.life <= 0: - print("{} 獲勝".format(p1.name))""" - def start(self): # initialize the game - p1, p2 = self.players[0].player, self.players[1].player - ws_list = self.players[:] - - firstws = ws_list.pop(random.randint(0, 1)) - #print(first, p1, p2) - firstws.player.playing = True # so the first one will be random - #await sendTo(first.player.name + "先攻", *self.players) - - print(firstws.player.name,"先攻") - print() # change line - for _ in range(3): # 初始手牌*3 - game.draw(p1) - game.draw(p2) - return firstws, ws_list[0] # it will be second player - @staticmethod - def start_turn(wscur, wsene): - cur, ene = wscur.player, wsene.player - - message_to_send = [] - - cur.playing, ene.playing = ene.playing, cur.playing - - cur.turn += 1 - - message_to_send.append(( (wscur,), game.draw(cur))) - message_to_send.append(( (wscur,), - dumps({"player": { - "turn": cur.turn, "hand": cur.hand, "deck_left": len(cur.deck), - "life": cur.life - } - } - ) - )) - - message_to_send.append(( (wsene,), - dumps({"enemy": { - "turn": cur.turn, "deck_left": len(cur.deck), - "life": cur.life # cur為當前回合之玩家,故此處仍為cur - } - } - ) - )) - - message_to_send.append(( (wsene,), dumps({"msg": "drawEne", "data": [cur.name]}))) - - cur.status = Room.IN_TURN - if cur.poison_check(): - message_to_send.append(( (wscur,wsene), "{} 受到了劇毒的侵蝕, 損失{}點生命".format(cur.name,cur.poison))) - if cur.life <= 0: - pass - #await sendTo(health(p1,p2), wsp1, wsp2) - #await sendTo(draw(cur), wsp1, wsp2) # 抽卡 - #message_to_send.append(( (wscur,), game.display(cur))) # 顯示手牌 - #message_to_send.append(( (wscur,), "請問要使用手牌嗎? 若不使用請輸入0")) - return message_to_send - - def process(self, wscur, message): # cur is the person who send message to server - - start_next_turn_cards = ['2', '3', '4', '8', '11', '12', '13', '14', '15', '16'] - cur = wscur.player - wsene = self.players[1] if wscur is self.players[0] else self.players[0] - ene = wsene.player - message_to_send = [] - choice = message - if cur.status == self.IN_TURN: - - if choice in cur.hand: - - message_to_send.extend(card.skills[choice](wscur, wsene)) - if choice in start_next_turn_cards: - cur.status = self.NOTHING - message_to_send.extend(Room.start_turn(wsene, wscur)) - - cur.remove_card(choice) - elif choice == "0": - cur.status = self.NOTHING - message_to_send.extend(Room.start_turn(wsene, wscur)) - """elif choice == "-1": - cur.surrender() - {}投降".format(cur.name)""" - - elif cur.status == self.ROBBING: - pass - - elif cur.status == self.ROBBED: - pass - elif cur.status == self.DEFENCE: # cur是被攻擊方 - if choice in cur.hand: - if choice in card.unattackable: - message_to_send.extend(card.skills[choice](wscur,wsene)) - cur.remove_card(choice) - elif choice == "0": - message_to_send.append(( (wsene, wscur), "{} 受到{}點傷害".format(cur.name,ene.damage))) - ene.life -= cur.damage - else: - message_to_send.append(( (wscur,wsene), "{} 受到{}點傷害".format(cur.name,ene.damage))) - cur.life -= cur.damage - ene.attacking = False - ene.damage = 0 # reset - - message_to_send.extend(Room.start_turn(wscur, wsene)) - - elif cur.status == self.TRADE: - pass - - elif cur.status == self.PLAN: - pass - - return message_to_send -async def sendTo(message, *ws_list): - for ws in ws_list: - await ws.send(message) +import game, card +import random +from json import dumps, loads +class Room: + CONNECTED = 0 + MATCHING = 1 + PLAYING = 2 + WAITING = -1 + DISCONNECT = -2 + + # Player Status Definition + NOTHING = -1 + IN_TURN = 0 + ROBBED = 1 + DEFENCE = 2 + ROBBING = 3 + TRADE = 4 + TRADE_ENE = 5 + PLAN = 6 + def __init__(self, room): + self.room = room + self.players = [] + + + def __len__(self): + return len(self.players) + + def __repr__(self): + return "ROOM {}, {} player(s)".format(str(self.room), len(self)) + + def __iter__(self): + return iter(self.players) + + def player_add(self, player): + if len(self) >= 2: + return + self.players.append(player) + + def player_delete(self, player): + try: + self.players.remove(player) + if len(self) == 1: + return True + else: + return False + except: + pass + + + + """async def start(self): + p1, p2 = self.players[0].player, self.players[1].player + first = random.choice([p1, p2]) + print(first, p1, p2) + first.playing = True # so the first one will be random + await sendTo(first.name + "先攻", *self.players) + print(first.name,"先攻") + print() # change line + for _ in range(3): # 初始手牌*3 + game.draw(p1) + game.draw(p2) + + while p1.life > 0 and p2.life > 0: + print("game.turn start") + await game.turn(self.players[0], self.players[1]) + print("game.turn end") + if p1.life <= 0: + print("{} 獲勝".format(p2.name)) + elif p2.life <= 0: + print("{} 獲勝".format(p1.name))""" + def start(self): # initialize the game + p1, p2 = self.players[0].player, self.players[1].player + ws_list = self.players[:] + + firstws = ws_list.pop(random.randint(0, 1)) + #print(first, p1, p2) + firstws.player.playing = True # so the first one will be random + #await sendTo(first.player.name + "先攻", *self.players) + + print(firstws.player.name,"先攻") + print() # change line + for _ in range(3): # 初始手牌*3 + game.draw(p1) + game.draw(p2) + return firstws, ws_list[0] # it will be second player + @staticmethod + def start_turn(wscur, wsene): + cur, ene = wscur.player, wsene.player + + message_to_send = [] + + + cur.playing, ene.playing = ene.playing, cur.playing + + cur.turn += 1 + draw_res = game.draw(cur) + if not draw_res: + message_to_send.append(( (wscur, wsene), dumps({"msg": "noCard", "data": [cur.name]}))) + else: + message_to_send.append(( (wscur,), draw_res)) + + if cur.poison_check(): + message_to_send.append(( (wscur,wsene), dumps({"msg": "poisonDamaged", "data": [cur.name,cur.poison]}))) + + message_to_send.append(( (wscur,), + dumps({"player": { + "turn": cur.turn, "hand": cur.hand, "deck_left": len(cur.deck), + "life": cur.life, "poison": cur.poison, + }, + "enemy": { + "life": ene.life, "deck_left": len(ene.deck), + "hand": len(ene.hand), "poison": ene.poison, + }, + "now": "player", + } + ) + )) + + message_to_send.append(( (wsene,), + dumps({"player": { + "turn": ene.turn, "hand": ene.hand, "deck_left": len(ene.deck), + "life": ene.life, "poison": ene.poison, + }, + "enemy": { + "turn": cur.turn, "deck_left": len(cur.deck), + "life": cur.life, "hand": len(cur.hand), "poison": cur.poison, + # cur為當前回合之玩家,故此處仍為cur + }, + "now": "enemy" + } + ) + )) + message_to_send.append(( (wsene,), dumps({"msg": "drawEne", "data": [cur.name]}))) + + cur.status = Room.IN_TURN + + if cur.life <= 0: + message_to_send.append(( (wscur,), dumps({"msg": "win", "data": ["enemy"]}))) + message_to_send.append(( (wsene,), dumps({"msg": "win", "data": ["player"]}))) + + elif ene.life <= 0: + message_to_send.append(( (wscur,), dumps({"msg": "win", "data": ["player"]}))) + message_to_send.append(( (wsene,), dumps({"msg": "win", "data": ["enemy"]}))) + + + + + #await sendTo(health(p1,p2), wsp1, wsp2) + #await sendTo(draw(cur), wsp1, wsp2) # 抽卡 + #message_to_send.append(( (wscur,), game.display(cur))) # 顯示手牌 + #message_to_send.append(( (wscur,), "請問要使用手牌嗎? 若不使用請輸入0")) + return message_to_send + + def process(self, wscur, message): # cur is the person who send message to server + + start_next_turn_cards = ['2', '3', '4', '8', '11', '12', '13', '14', '15', '16'] + cur = wscur.player + wsene = self.players[1] if wscur is self.players[0] else self.players[0] + ene = wsene.player + message_to_send = [] + choice = message + + if cur.status == self.IN_TURN: + + if choice in cur.hand: + message_to_send.append(((wsene, wscur), dumps({"msg": "use", "data": [cur.name, choice]}))) + cur.remove_card(choice) + + message_to_send.extend(card.skills[choice](wscur, wsene)) + + if choice in start_next_turn_cards: + cur.status = self.NOTHING + message_to_send.extend(Room.start_turn(wsene, wscur)) + + else: # 直接結束 + cur.status = self.NOTHING + message_to_send.extend(Room.start_turn(wsene, wscur)) + + """elif choice == "-1": + cur.surrender() + {}投降".format(cur.name)""" + + elif cur.status == self.ROBBING: + swag = choice + ene.status = self.NOTHING + if swag in ene.hand: + cur.robbing = swag + if ene.keep(): + cur.status = Room.NOTHING + ene.status = Room.ROBBED + message_to_send.append(((wsene, ), dumps({"action": "toBeRobbed"}))) + else: + ene.robbed(swag) + cur.add_card(swag) + message_to_send.append(( (wscur,wsene), dumps({"msg": "robbed", "data": [cur.name, cur.robbing]}))) + + cur.robbing = "0" + cur.status = Room.NOTHING + + message_to_send.extend(Room.start_turn(wsene, wscur)) + + else: # 直接結束 + message_to_send.append(((wsene, wscur), dumps({"msg": "cantRob", "data": [cur.name]}))) + + message_to_send.extend(Room.start_turn(wsene, wscur)) + + + elif cur.status == self.ROBBED: + if choice in cur.hand and choice in card.unrobable: + + message_to_send.extend(card.skills[choice](wscur,wsene)) + cur.remove_card(choice) + else: + message_to_send.append(( (wscur,wsene), dumps({"msg": "robbed", "data": [ene.name, ene.robbing]}))) + cur.robbed(ene.robbing) + ene.add_card(ene.robbing) + + ene.robbing = "0" + + message_to_send.extend(Room.start_turn(wscur, wsene)) + + elif cur.status == self.DEFENCE: # cur是被攻擊方 + if choice in cur.hand: + if choice in card.unattackable: + message_to_send.extend(card.skills[choice](wscur,wsene)) + cur.remove_card(choice) + else: + if ene.surprise: + msg = "surNoCard" + if ene.hand: + drop = random.choice(ene.hand) + ene.remove_card(drop) + msg = "surprised" + message_to_send.append(( (wsene, wscur), dumps({"msg": msg, "data": [cur.name, ene.damage]}))) + else: + message_to_send.append(( (wsene, wscur), dumps({"msg": "damaged", "data": [cur.name, ene.damage]}))) + cur.life -= ene.damage + else: + if ene.surprise: + drop = random.choice(ene.hand) + ene.remove_card(drop) + message_to_send.append(( (wsene, wscur), dumps({"msg": "surprised", "data": [cur.name, ene.damage]}))) + else: + message_to_send.append(( (wsene, wscur), dumps({"msg": "damaged", "data": [cur.name, ene.damage]}))) + cur.life -= ene.damage + + ene.attacking = False + ene.surprise = False # 兩個都取消 + ene.damage = 0 # reset + + message_to_send.extend(Room.start_turn(wscur, wsene)) + + elif cur.status == self.TRADE: + if choice in cur.hand: + + message_to_send.append(( (wsene, wscur), dumps({"msg": "tradeChoose", "data": [cur.name, choice]}))) + message_to_send.append(( (wsene,), dumps({"action": "toTrade"}))) + cur.trading = choice + cur.status = self.NOTHING + ene.status = self.TRADE_ENE + else: # 直接結束 + message_to_send.extend(Room.start_turn(wsene, wscur)) + + elif cur.status == self.TRADE_ENE: + if cur.hand: + if choice not in cur.hand: + choice = random.sample(cur.hand, 1)[0] # decide a card randomly + + ene.hand.remove(ene.trading) + ene.hand.append(choice) + + cur.hand.remove(choice) + cur.hand.append(ene.trading) + else: + message_to_send.append(( (wsene,wscur), dumps( {"msg": "tradeNoCard", "data": [cur.name]}))) + + + ene.trading = "0" + + message_to_send.extend(Room.start_turn(wscur, wsene)) + + elif cur.status == self.PLAN: + if choice in cur.planning: + cur.add_card(choice) + cur.stauts = Room.NOTHING + cur.planning = [] + message_to_send.extend(Room.start_turn(wsene, wscur)) + print("status of ",cur.name, ":", cur.status) + print("status of ",ene.name, ":", ene.status) + return message_to_send +async def sendTo(message, *ws_list): + for ws in ws_list: + await ws.send(message) diff --git a/spec.json b/spec.json index 06422d7..6e657d0 100644 --- a/spec.json +++ b/spec.json @@ -1,192 +1,198 @@ -choose character: "5" - -enter_room: room number / "n" // "n" to create a random room and enter it - out: room number / {"room": 18693, "cur": "圭月", "ene": "小兔"} - // shows room number, or send a object shows your player and enemy's - -遊戲剛開始時發送: -{"msg": "firstAttack", "data": [firstPlayer.name], "hand": player.hand} - - -每回合開始發送: -{ - "player": { - "turn": 3, "hand": ['1','2','3','1','1','1'], "deck_left": 35, - "life": 20 - }, - "enemy": {"turn": 3, "life": 20, "deck_left": 35 - - } -} - -{ - "attack": "{} 攻擊 {}", - "damaged": "{} 受到{}點傷害", - //"toDefend": "請問要防禦嗎?不出牌請輸入0", - "defended": "{} 防禦成功", - "defend": "{} 沒什麼可以防禦的,回復一點生命", - "heal": "{} 回復兩點生命", - "supply": "{} 增加兩張手牌", - "rob": "{} 正在對 {} 行搶", - "cantRob": "可惜,{} 有夠窮,沒東西能搶", - "robbed": "{} 搶到了 {}" - "surprise": "{} 發動奇襲", - "surprised": "{} 受到{}點傷害,而且掉了一張手牌", - "trade": "{} 想與 {} 進行交易", - "tradeChoose": "{} 選擇了 {}", - //"toRob": "{} 要搶哪張?", - //"toBeRobbed": "請問要防禦嗎?" - //"toTrade": "選擇一張手牌以交換", - "awared": "{} 洞悉了 {} 的{},並抽取了一張手牌", - /* 整併於上 - "": "{} 洞悉了 {} 的強奪,並抽取了一張手牌", - "": "{} 洞悉了 {} 的奇襲,並抽取了一張手牌", - */ - "aware": "{} 增加三張手牌", - "plan": "{} 有個妙策", - //"toAdd": "選擇一張卡加入手牌", - "sweep": "{} 對 {} 進行掃射,威力是 {}", - "bless": "{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌", - "poison": "{} 在食物下毒,{}中毒了", - "curse": "{} 詛咒了 {},使其損失四點生命,並掉了一張手牌", - "countered": "{} 反制了 {} 的攻擊,反彈了{}點傷害", - "counteredSur": "{} 反制了 {} 的攻擊,反彈了{}點傷害,並使其掉了一張手牌", - "counter": "{} 反制了敵手,使 {} 生命值減半了!", - "chaos": "{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害", - "reverse": "{} 一口氣逆轉了情勢", - //"": "{} 的生命: {}", - //"": "這是 {} 的手牌", - "noCard": "你抽到了死神", - "left": "牌組剩餘: {} 張", - //"": "{} 抽到了 {}", - //"inTurn": "請問要使用手牌嗎? 若不使用請輸入0", - "turnNumber": "{} 的第{}回合", - "poisonDamaged": "{} 受到了劇毒的侵蝕,損失{}點生命", - "surrender": "{}投降", - "firstAttack": "{}先攻", - "win": "{}獲勝", - "draw": "{}抽到了{}", - "drawEne": "{}抽了一張卡片" - -} - - - -1. attack - in: "1" - out: - cur: {"msg": "attack", "data": [cur.name, ene.name]} - ene: {"msg": "attack", "data": [cur.name, ene.name], - "action": "toDefend", "value": {"damage": cur.damage}} / 無(不能防禦) - in: "2" / "8" / "14" / "0" - out: - cur: {"msg": "defended", "data": [ene.name]} / - {"msg": "countered", "data": [ene.name]} / - {"msg": "awared", "data": [ene.name, "攻擊"]} / - {"msg": "damaged", "data": [ene.name, cur.damage]} - ene: 同上 -2. defend //此處指主動使用 - in: "2" - out: - cur: {"msg": "defend", "data": [cur.name]} - ene: 同上 -3. heal - in: "3" - out: - cur: {"msg": "heal", "data": [cur.name]} - ene: 同上 -4. supply - in: "4" - out: - cur: {"msg": "supply", "data": [cur.name]} - ene: 同上 -5. rob - in: "5" - out: - cur: {"msg": "rob", "data": [cur.name, ene.name], - "action": "toRob", "value": {"emeny_card:", ene.hand}} / - {"msg": "cantRob", "data": [ene.name]} - in: card number - out: - ene: {"action": "toBeRobbed"} / 無(不能防禦時) - in: "8" / "0" - out: - cur: {"msg": "defended", "data": [ene.name]} / - {"msg": "robbed", "data": [ene.name, card]} - ene: 同上 - ene: 無 / {"msg": "cantRob", "data": [ene.name]} -6. surprise - in: "6" - out: - cur: - ene: {"action": "toDefend", "value": {"damage": cur.damage}} / 無(不能防禦) - in: "2" / "8" / "14" / "0" - out: - cur: {"msg": "defended", "data": [ene.name]} / - {"msg": "counteredSur", "data": [ene.name]} / - {"msg": "awared", "data": [ene.name, "奇襲"]} / - {"msg": "surprised", "data": [ene.name, cur.damage]} - ene: 同上 -7. trade - in: "7" - out: - cur: {"msg": "trade", "data": [cur.name, ene.name], "action": "toTrade"} - in: card number - out: - cur: {"msg": "tradeChoose", "data": [cur.name, card number]} - ene: {"action": "toTrade"} - ene: {"msg": "trade", "data": [cur.name, ene.name]} -8. aware //此處指主動使用 - in: "8" - out: - cur: {"msg": "aware", "data": [cur.name]} - ene: 同上 -9. plan - in: "9" - out: - cur: {"msg": "plan", "data": [cur.name], - "action": "toAdd", "value": {"cards": list}} - in: card number - ene: {"msg": "plan", "data": [cur.name]} -10. bless - in: "10" - out: - cur: {"msg": "bless", "data": [cur.name]} - ene: 同上 -11. sweep - in: "11" - out: - cur: - ene: {"action": "toDefend", "value": {"damage": cur.damage}} / 無(不能防禦) - in: "2" / "8" / "14" / "0" - out: - cur: {"msg": "defended", "data": [ene.name]} / - {"msg": "countered", "data": [ene.name]} / - {"msg": "awared", "data": [ene.name, "掃射"]} / - {"msg": "damaged", "data": [ene.name, cur.damage]} - ene: 同上 -12. poison - in: "12" - out: - cur: {"msg": "poison", "data": [cur.name, ene.name]} - ene: 同上 -13. curse - in: "13" - out: - cur: {"msg": "curse", "data": [cur.name, ene.name]} - ene: 同上 -14. counter //此處指主動使用 - in: "14" - out: - cur: {"msg": "counter", "data": [cur.name, ene.name]} - ene: 同上 -15. chaos - in: "15" - out: - cur: {"msg": "chaos", "data": [cur.name, ene.name]} - ene: 同上 -16. reverse - in: "16" - out: - cur: {"msg": "reverse", "data": [cur.name]} +choose character: "5" + +enter_room: room number / "n" // "n" to create a random room and enter it + out: room number / {"room": 7122, "cur": "圭月", "ene": "小兔"} + // shows room number, or send a object shows your player and enemy's + +遊戲剛開始時發送: +{"msg": "firstAttack", "data": [firstPlayer.name], "hand": player.hand} + + +每回合開始發送: +{ + "player": { + "turn": 3, "hand": ['1','2','3','1','1','1'], "deck_left": 35, + "life": 20, "poison": 0, + }, + "enemy": {"turn": 3, "life": 20, "deck_left": 35, "hand": 30, "poison": 1, + + } +} + + +{ + "attack": "{} 攻擊 {}", + "damaged": "{} 受到{}點傷害", + //"toDefend": "請問要防禦嗎?不出牌請輸入0", + "defended": "{} 防禦成功", + "defend": "{} 沒什麼可以防禦的,回復一點生命", + "heal": "{} 回復兩點生命", + "supply": "{} 增加兩張手牌", + "rob": "{} 正在對 {} 行搶", + "cantRob": "{}沒有搶到任何東西", + "robbed": "{} 搶到了 {}", + "surprise": "{} 發動奇襲", + "surprised": "{} 受到{}點傷害,而且掉了一張手牌", + "trade": "{} 想與 {} 進行交易", + "tradeChoose": "{} 選擇了 {}", + //"toRob": "{} 要搶哪張?", + //"toBeRobbed": "請問要防禦嗎?" + //"toTrade": "選擇一張手牌以交換", + "awared": "{} 洞悉了 {} 的{},並抽取了一張手牌", + /* 整併於上 + "": "{} 洞悉了 {} 的強奪,並抽取了一張手牌", + "": "{} 洞悉了 {} 的奇襲,並抽取了一張手牌", + */ + "aware": "{} 增加三張手牌", + "plan": "{} 有個妙策", + //"toAdd": "選擇一張卡加入手牌", + "sweep": "{} 對 {} 進行掃射,威力是 {}", + "bless": "{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌", + "poison": "{} 在食物下毒,{}中毒了", + "curse": "{} 詛咒了 {},使其損失四點生命,並掉了一張手牌", + "countered": "{} 反制了 {} 的攻擊,反彈了{}點傷害", + "counteredSur": "{} 反制了 {} 的攻擊,反彈了{}點傷害,並使其掉了一張手牌", + "counter": "{} 反制了敵手,使 {} 生命值減半了!", + "chaos": "{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害", + "reverse": "{} 一口氣逆轉了情勢", + //"": "{} 的生命: {}", + //"": "這是 {} 的手牌", + "noCard": "你抽到了死神", + "left": "牌組剩餘: {} 張", + //"": "{} 抽到了 {}", + //"inTurn": "請問要使用手牌嗎? 若不使用請輸入0", + "turnNumber": "{} 的第{}回合", + "poisonDamaged": "{} 受到了劇毒的侵蝕,損失{}點生命", + "surrender": "{}投降", + "firstAttack": "{}先攻", + "win": "{}獲勝", + "draw": "{}抽到了{}", + "drawEne": "{}抽了一張卡片", + "use": "{}使用了{}", + "eneDisconn": "因敵方斷線,所以{}獲勝", + +} + + + +1. attack + in: "1" + out: + cur: {"msg": "attack", "data": [cur.name, ene.name]} + ene: 同cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "attack"}} / + 同cur(不能防禦) + in: "2" / "8" / "14" / "0" + out: + cur: {"msg": "defended", "data": [ene.name]} / + {"msg": "countered", "data": [ene.name]} / + {"msg": "awared", "data": [cur.name, ene.name, "攻擊"]} / + {"msg": "damaged", "data": [ene.name, cur.damage]} + ene: 同上 +2. defend //此處指主動使用 + in: "2" + out: + cur: {"msg": "defend", "data": [cur.name]} + ene: 同上 +3. heal + in: "3" + out: + cur: {"msg": "heal", "data": [cur.name]} + ene: 同上 +4. supply + in: "4" + out: + cur: {"msg": "supply", "data": [cur.name]} + ene: 同上 +5. rob + in: "5" + out: + cur: {"msg": "rob", "data": [cur.name, ene.name], + "action": "toRob", "value": {"enemy_card": ene.hand}} / + {{"msg": "cantRob", "data": [cur.name]}]} + in: card number + out: + ene: {"action": "toBeRobbed"} / 無(不能防禦) + in: "8" / "0" + out: + cur: {"msg": "awared", "data": [cur.name, ene.name, "搶奪"]} / + {"msg": "robbed", "data": [ene.name, card]} + ene: 同上 + ene: 無 / {{"msg": "cantRob", "data": [cur.name]}]} +6. surprise + in: "6" + out: + cur: {"msg": "surprise", "data": [cur.name]} + ene: 同cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "suprise"}} / + 同cur(不能防禦) + in: "2" / "8" / "14" / "0" + out: + cur: {"msg": "defended", "data": [ene.name]} / + {"msg": "counteredSur", "data": [ene.name]} / + {"msg": "awared", "data": [cur.name, ene.name, "奇襲"]} / + {"msg": "surprised", "data": [ene.name, cur.damage]} + ene: 同上 +7. trade + in: "7" + out: + cur: {"msg": "trade", "data": [cur.name, ene.name]}, + {"action": "toTrade", "value": ["hand": cur.hand]} + in: card number + out: + cur: {"msg": "tradeChoose", "data": [cur.name, card number]} + ene: 同cur, {"action": "toTrade"} + ene: {"msg": "trade", "data": [cur.name, ene.name]} +8. aware //此處指主動使用 + in: "8" + out: + cur: {"msg": "aware", "data": [cur.name]} + ene: 同上 +9. plan + in: "9" + out: + cur: {"msg": "plan", "data": [cur.name]}, + {"action": "toAdd", "value": {"cards": list}} + in: card number + ene: {"msg": "plan", "data": [cur.name]} +10. bless + in: "10" + out: + cur: {"msg": "bless", "data": [cur.name]} + ene: 同上 +11. sweep + in: "11" + out: + cur: {"msg": "sweep", "data": [cur.name, ene.name, cur.damage]} + ene: 同cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "sweep"}} / + 無(不能防禦) + in: "2" / "8" / "14" / "0" + out: + cur: {"msg": "defended", "data": [ene.name]} / + {"msg": "countered", "data": [ene.name]} / + {"msg": "awared", "data": [cur.name, ene.name, "掃射"]} / + {"msg": "damaged", "data": [ene.name, cur.damage]} + ene: 同上 +12. poison + in: "12" + out: + cur: {"msg": "poison", "data": [cur.name, ene.name]} + ene: 同上 +13. curse + in: "13" + out: + cur: {"msg": "curse", "data": [cur.name, ene.name]} + ene: 同上 +14. counter //此處指主動使用 + in: "14" + out: + cur: {"msg": "counter", "data": [cur.name, ene.name]} + ene: 同上 +15. chaos + in: "15" + out: + cur: {"msg": "chaos", "data": [cur.name, ene.name]} + ene: 同上 +16. reverse + in: "16" + out: + cur: {"msg": "reverse", "data": [cur.name]} ene: 同上 \ No newline at end of file