This commit is contained in:
t510599 2018-06-02 00:38:16 +08:00
commit fca4dd2acb
5 changed files with 710 additions and 624 deletions

299
card.py
View File

@ -3,16 +3,18 @@ import game
from room import Room from room import Room
from json import dumps from json import dumps
cards = dict() unattackable = ['2','8','14']
card_name = ["1.攻擊","2.防禦","3.治癒","4.補給","5.強奪","6.奇襲","7.交易","8.洞悉","9.妙策","10.掃射","11.加護","12.劇毒","13.詛咒","14.反制","15.狂亂","16.逆轉"] unrobable = ['8','17']
unattackable = ['2','8','14','17','18']
unrobable = ['8','17','18']
for i in range(len(card_name)):
cards[str(i+1)] = card_name[i] # initialize cards
# create default deck # 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'] 攻擊*7 防禦*7 治癒*7
default_deck = ['3', '4', '2', '1']*15 補給*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 random.shuffle(default_deck) # wash
# card functions # card functions
@ -26,11 +28,10 @@ def attack(wscur, wsene):
r = [] r = []
cur.damage = 2 # 給反制判斷的 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(): if ene.defence():
r.append(( (wsene, ), r.append(( (wsene, ),
dumps({"msg": "attack", "data": [cur.name, ene.name], dumps({"action": "toDefend", "value": {"damage": cur.damage, "type": "attack"}})
"action": "toDefend", "value": {"damage": cur.damage}})
)) ))
cur.status = Room.NOTHING cur.status = Room.NOTHING
ene.status = Room.DEFENCE ene.status = Room.DEFENCE
@ -38,7 +39,10 @@ def attack(wscur, wsene):
r.append(( (wsene, wscur), r.append(( (wsene, wscur),
dumps({"msg": "damaged", "data": [ene.name, cur.damage]}) dumps({"msg": "damaged", "data": [ene.name, cur.damage]})
)) ))
cur.status = Room.NOTHING
ene.life -= cur.damage ene.life -= cur.damage
r.extend(Room.start_turn(wsene, wscur))
cur.attacking = False cur.attacking = False
cur.damage = 0 # reset cur.damage = 0 # reset
""" """
@ -62,10 +66,10 @@ def defend(wscur,wsene): # cur是用卡方
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = [] r = []
if ene.attacking or ene.surprise: if ene.attacking or ene.surprise:
r.append(( (wsene,wscur), "{} 防禦成功".format(cur.name))) r.append(( (wsene,wscur), dumps({"msg": "defended", "data": [cur.name]})))
else: else:
r.append(( (wsene,wscur), "{} 沒什麼可以防禦的,回復一點生命".format(cur.name))) r.append(( (wsene,wscur), dumps({"msg": "defend", "data": [cur.name]})))
cur.life += 1 cur.life += 1
return r return r
@ -89,209 +93,202 @@ def supply(wscur,wsene):
def rob(wscur,wsene): def rob(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
cur.robbing = True r.append(( (wscur, ), dumps({"msg": "rob", "data": [cur.name, ene.name],
print("{} 正在對 {} 行搶".format(cur.name,ene.name)) "action": "toRob", "value": {"enemy_card": ene.hand}})))
if ene.keep():
game.display(ene) # 顯示手牌 cur.status = Room.ROBBING
while True: r.append(( (wsene, ), dumps({"msg": "rob", "data": [cur.name, ene.name]})))
choice = input("請問要防禦嗎? 不使用請輸入0 ") return r
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
def surprise(wscur,wsene): def surprise(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
cur.surprise = True 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(): if ene.defence():
game.display(ene) # 顯示手牌 r.append(( (wsene, ),
while True: dumps({"action": "toDefend", "value": {"damage": cur.damage, "type": "surprise"}})
choice = input("請問要防禦嗎? 不使用請輸入0 ") ))
if choice in ene.hand: cur.status = Room.NOTHING
if choice in unattackable: ene.status = Room.DEFENCE
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
else: 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 ene.life -= cur.damage
drop = random.choice(ene.hand) drop = random.choice(ene.hand)
ene.remove_card(drop) ene.remove_card(drop)
cur.surprise = False cur.surprise = False
cur.damage = 0 # reset cur.damage = 0 # reset
r.extend(Room.start_turn(wsene, wscur))
return r
def trade(wscur,wsene): def trade(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
print("{} 想與 {} 進行交易".format(cur.name,ene.name)) if ene.hand:
cur.remove_card("7") # you can't trade the using card "trade" r.append(( (wsene, wscur),
game.display(cur) # 顯示手牌 dumps({"msg": "trade", "data": [cur.name, ene.name]})
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])
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): def aware(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
if cur.attacking: if ene.attacking:
print("{} 洞悉了 {} 的攻擊,並抽取了一張手牌".format(ene.name,cur.name)) r.append(( (wsene,wscur), dumps({"msg": "awared", "data": [cur.name, ene.name, "攻擊"]})))
game.draw(ene)
elif cur.robbing: elif ene.robbing != "0":
print("{} 洞悉了 {} 的強奪,並抽取了一張手牌".format(ene.name,cur.name)) r.append(((wscur, wsene), dumps({"msg": "awared", "data": [cur.name, ene.name, "搶奪"]})))
game.draw(ene)
elif cur.surprise: elif ene.surprise:
print("{} 洞悉了 {} 的奇襲,並抽取了一張手牌".format(ene.name,cur.name)) r.append(( (wsene,wscur), dumps({"msg": "awared", "data": [cur.name, ene.name, "奇襲"]})))
game.draw(ene)
else: else:
r.append(((wscur, wsene), dumps({"msg": "aware", "data": [cur.name]})))
for _ in range(3): for _ in range(3):
print("{} 增加三張手牌".format(cur.name))
game.draw(cur) game.draw(cur)
return r
def plan(wscur,wsene): def plan(wscur,wsene):
cur, ene = wscur.player, wsene.player 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) options = random.sample(cur.deck,3)
o_name = [] # names of cards in options r.append(( (wscur, ),
for id in options: dumps({"action": "toAdd", "value": {"cards": options}})
o_name.append(cards[id]) ))
print(o_name) cur.planning = options
while True: cur.status = Room.PLAN
choice = input("選擇一張卡加入手牌 ")
if choice in options: return r
cur.add_card(choice)
break
def sweep(wscur,wsene): def sweep(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
cur.attacking = True cur.attacking = True
r = []
cur.damage = random.randint(0,5) 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(): if ene.defence():
game.display(ene) # 顯示手牌 r.append(( (wsene, ),
while True: dumps({"action": "toDefend", "value": {"damage": cur.damage, "type": "sweep"}})
choice = input("請問要防禦嗎? 不使用請輸入0 ") ))
if choice in ene.hand: cur.status = Room.NOTHING
if choice in unattackable: ene.status = Room.DEFENCE
skills[choice](cur,ene)
ene.remove_card(choice)
break
elif choice == "0":
print("{} 受到{}點傷害".format(ene.name,cur.damage))
ene.life -= cur.damage
break
else: 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 ene.life -= cur.damage
cur.attacking = False r.extend(Room.start_turn(wsene, wscur))
cur.damage = 0 # reset cur.attacking = False
cur.damage = 0 # reset
return r
def bless(wscur,wsene): def bless(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
print("{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌".format(cur.name)) r.append(( (wsene,wscur), dumps({"msg": "bless", "data": [cur.name]})))
cur.poison = 0 # 解毒 cur.poison = 0 # 解毒
cur.life += 3 cur.life += 3
for _ in range(2): for _ in range(2):
game.draw(cur) game.draw(cur)
return r
def poison(wscur,wsene): def poison(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
if ene.poison != 0: r.append(( (wsene,wscur), dumps({"msg": "poison", "data": [cur.name, ene.name]})))
s = ""
else:
s = ""
print("{} 在食物下毒,{} {}中毒了".format(cur.name,ene.name, s))
ene.poison += 1 ene.poison += 1
return r
def curse(wscur,wsene): def curse(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
print("{} 詛咒了 {},使其損失四點生命,並掉了一張手牌".format(cur.name,ene.name))
ene.life -= 4 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): def counter(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
if cur.attacking: if ene.attacking:
print("{} 反制了 {} 的攻擊,反彈了{}點傷害".format(ene.name,cur.name,cur.damage)) r.append(( (wsene,wscur), dumps({"msg": "countered", "data": [cur.name, ene.name, ene.damage]})))
cur.life -= cur.damage ene.life -= ene.damage
elif cur.surprise: elif ene.surprise:
print("{} 反制了 {} 的奇襲,反彈了{}點傷害,並使其掉了一張手牌".format(ene.name,cur.name,cur.damage)) r.append(( (wsene,wscur), dumps({"msg": "counteredSur", "data": [cur.name, ene.name, ene.damage]})))
cur -= cur.damage ene.life -= ene.damage
drop = random.choice(cur.hand) drop = random.choice(ene.hand)
cur.remove_card(drop) ene.remove_card(drop)
else: else:
print("{} 反制了敵手,使 {} 生命值減半了!".format(cur.name,ene.name)) r.append(( (wsene,wscur), dumps({"msg": "counter", "data": [cur.name, ene.name]})))
ene.life = ene.life//2 ene.life = ene.life//2
return r
def chaos(wscur,wsene): def chaos(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
r = []
print("{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害".format(cur.name,ene.name)) r.append(( (wsene,wscur), dumps({"msg": "chaos", "data": [cur.name, ene.name]})))
cur.life += 3 cur.life += 3
ene.life -= 3 ene.life -= 3
return r
def reverse(wscur,wsene): def reverse(wscur,wsene):
cur, ene = wscur.player, wsene.player 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 cur.life,ene.life = ene.life,cur.life
return r
skills = dict() skills = dict()
skill_name = [attack,defend,heal,supply,rob,surprise,trade,aware,plan,sweep,bless,poison,curse,counter,chaos,reverse] 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)): for i in range(len(skill_name)):
skills[str(i+1)] = skill_name[i] skills[str(i+1)] = skill_name[i]

59
game.py
View File

@ -8,13 +8,15 @@ class Player:
self.name = name self.name = name
self.deck = deck[:] # to pass by value instead of by reference self.deck = deck[:] # to pass by value instead of by reference
self.hand = [] self.hand = []
self.display = [] # names of cards in hand self.status = -1
self.life = 20 self.life = 15
self.poison = 0 self.poison = 0
self.damage = 0 # 因為反制要拿來判斷掃射 self.damage = 0 # 因為反制要拿來判斷掃射
self.playing = False self.playing = False
self.attacking = 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.surprise = False # 又是因為反制要判斷奇襲
self.turn = 0 self.turn = 0
@ -27,18 +29,17 @@ class Player:
def add_card(self,id): def add_card(self,id):
self.hand.append(id) self.hand.append(id)
self.display.append(card.cards[id])
self.deck.remove(id) self.deck.remove(id)
def remove_card(self,id): def remove_card(self,id):
self.hand.remove(id) self.hand.remove(id)
self.display.remove(card.cards[id])
self.deck.append(id) self.deck.append(id)
def robbed(self,id): # be robbed def robbed(self,id): # be robbed
self.hand.remove(id) try:
self.display.remove(card.cards[id]) self.hand.remove(id)
except:
print("rob except:", id, self.hand)
def defence(self): # to decide if player is able to defend or not def defence(self): # to decide if player is able to defend or not
for c in self.hand: for c in self.hand:
if c in card.unattackable: if c in card.unattackable:
@ -56,16 +57,10 @@ class Player:
# game functions # game functions
def health(p1,p2):
return "{} 的生命: {}\n{} 的生命: {}".format(p1.name,p1.life, p2.name, p2.life)
def display(player):
return "這是 {} 的手牌\n{}".format(player.name, player.display)
def draw(player): # 抽卡 def draw(player): # 抽卡
if len(player.deck) == 0: if len(player.deck) == 0:
player.life = -99999999 # 牌抽乾了就讓他死 player.life = -99999999 # 牌抽乾了就讓他死
return dumps({"msg": "noCard", "data": [player.name]}) return False
new = random.choice(player.deck) new = random.choice(player.deck)
player.add_card(new) player.add_card(new)
@ -73,37 +68,3 @@ def draw(player): # 抽卡
# turn control # turn control
# cur:current player # cur:current player
# ene:enemy # 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!

147
pyws.py
View File

@ -3,21 +3,16 @@ import game
from room import Room, sendTo from room import Room, sendTo
import asyncio import asyncio
import datetime
import random import random
import websockets import websockets
from json import dumps, loads from json import dumps, loads
import ssl
connected = {-1: []} connected = {-1: []}
character = dict()
name=["","圭月","","小兔","","正作","W","桑德","海爾","雪村"]
for i in range(len(name)):
character[str(i+1)] = name[i]
sad = None
fut = None fut = None
wait_fut = [0, 0]
async def wait(websocket, *cors, timeout=45, futs=None): async def wait(websocket, *cors, timeout=45, futs=None):
if futs != None: if futs != None:
fut_cor = futs fut_cor = futs
@ -25,39 +20,33 @@ async def wait(websocket, *cors, timeout=45, futs=None):
fut_cor = [cor() for cor in cors] fut_cor = [cor() for cor in cors]
done, pending = await asyncio.wait(fut_cor, done, pending = await asyncio.wait(fut_cor,
return_when=asyncio.FIRST_EXCEPTION, timeout=timeout) return_when=asyncio.FIRST_EXCEPTION, timeout=timeout)
#print(done, pending)
#print("Futures:", done, pending)
if pending: if pending:
#print("coroutine doesn't finish its work") for task in pending:
pass task.cancel()
if len(done): if len(done):
return list(done)[0].result() if list(done)[0].exception() == None:
else: return list(done)[0].result()
#print("SADDDDD") else:
return return "exception"
def random_room(): def random_room(room_list):
global connected, rooms
try: while len(room_list)>=1:
print(rooms) enter = random.choice(room_list)
except: print("rooms", enter, room_list)
rooms = list(connected)
rooms.remove(-1)
print(rooms)
while len(rooms)>=1:
enter = random.choice(rooms)
print("rooms", enter, rooms)
rooms.remove(enter)
if len(connected[enter]) < 2: if len(connected[enter]) < 2:
return enter return enter
while 1: while 1:
enter = random.randint(1, 99999) enter = random.randint(1, 99999)
if enter not in connected: if enter not in connected:
rooms.append(enter)
return enter return enter
async def enter_room(websocket): async def enter_room(websocket):
global connected ,sad, fut global connected, fut
room_list = [room_id for room_id in connected if len(connected[room_id])<2 and room_id != -1] room_list = [room_id for room_id in connected if len(connected[room_id])<2 and room_id != -1]
#print("I'm here") #print("I'm here")
@ -66,7 +55,7 @@ async def enter_room(websocket):
message = await wait(websocket, websocket.recv) message = await wait(websocket, websocket.recv)
if message == "n": if message == "n":
room_id = random_room() room_id = random_room(room_list)
else: else:
room_id = int(message) room_id = int(message)
@ -85,21 +74,21 @@ async def enter_room(websocket):
if count+1 == 1: # 該玩家已加入房間 if count+1 == 1: # 該玩家已加入房間
await websocket.send(str(room_id)) await websocket.send(str(room_id))
sad = websocket
else: else:
players = connected[websocket.room].start() players = connected[websocket.room].start()
for ws in connected[room_id]: for ws in connected[room_id]:
ws.status = Room.PLAYING ws.status = Room.PLAYING
wsene = connected[room_id].players[0] if connected[room_id].players[1] is websocket else connected[room_id].players[1] 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": websocket.player.name, "ene": wsene.player.name})) 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})) await ws.send(dumps({"msg": "firstAttack", "data": [players[0].player.name], "hand": ws.player.hand}))
fut.cancel() fut.cancel()
for ws_list, message in Room.start_turn(*players): for ws_list, message in Room.start_turn(*players):
await sendTo(message, *ws_list) await sendTo(message, *ws_list)
async def handler(websocket, path): async def handler(websocket, path):
global connected,sad, fut global connected, fut, wait_fut, rooms
print("initialize")
# Register. # Register.
connected[-1].append(websocket) connected[-1].append(websocket)
websocket.status = Room.CONNECTED websocket.status = Room.CONNECTED
@ -113,7 +102,8 @@ async def handler(websocket, path):
websocket.player = game.Player(name[int(choice)-1], card.default_deck) websocket.player = game.Player(name[int(choice)-1], card.default_deck)
websocket.status = Room.MATCHING websocket.status = Room.MATCHING
except: except Exception as e:
print(e)
return # close the connection return # close the connection
@ -127,44 +117,91 @@ async def handler(websocket, path):
if websocket.status == Room.MATCHING: if websocket.status == Room.MATCHING:
await enter_room(websocket) await enter_room(websocket)
elif websocket.status == Room.WAITING: elif websocket.status == Room.WAITING:
print("SAD", "FIRST" if websocket == sad else "SECOND")
fut = asyncio.ensure_future(websocket.recv()) fut = asyncio.ensure_future(websocket.recv())
try: try:
message = await wait(websocket, timeout=100000, futs=[fut]) message = await wait(websocket, timeout=100, futs=[fut])
print(message)
print(fut)
if message == "e": if message == "e":
connected[websocket.room].player_delete(websocket) connected[websocket.room].player_delete(websocket)
await websocket.send("You have left Room "+str(connected[websocket.room])) 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) connected[-1].append(websocket)
websocket.status = Room.MATCHING websocket.status = Room.MATCHING
elif message == "exception":
break
except asyncio.CancelledError: except asyncio.CancelledError:
pass 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")
message_to_send = connected[websocket.room].process(websocket, message)
for ws_list, message in message_to_send: elif websocket.status == Room.PLAYING:
await sendTo(message, *ws_list)
try:
enemy = 0 if websocket == connected[websocket.room].players[1] else 1
wait_fut[(enemy+1)%2] = asyncio.ensure_future(websocket.recv())
message = await wait(websocket, timeout=30, futs=[wait_fut[(enemy+1)%2]])
print("received message", 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
except asyncio.CancelledError:
print("Canceled\n\n")
elif websocket.status == Room.DISCONNECT:
break
finally: finally:
# Unregister. # Unregister.
try: 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: except:
connected[-1].remove(websocket) connected[-1].remove(websocket)
print(connected) 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") 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_until_complete(start_server)
asyncio.get_event_loop().run_forever() asyncio.get_event_loop().run_forever()

441
room.py
View File

@ -1,178 +1,263 @@
import game, card import game, card
import random import random
from json import dumps, loads from json import dumps, loads
class Room:
class Room: CONNECTED = 0
CONNECTED = 0 MATCHING = 1
MATCHING = 1 PLAYING = 2
PLAYING = 2 WAITING = -1
WAITING = -1 DISCONNECT = -2
# Player Status Definition # Player Status Definition
NOTHING = -1 NOTHING = -1
IN_TURN = 0 IN_TURN = 0
ROBBED = 1 ROBBED = 1
DEFENCE = 2 DEFENCE = 2
ROBBING = 3 ROBBING = 3
TRADE = 4 TRADE = 4
PLAN = 5 TRADE_ENE = 5
def __init__(self, room): PLAN = 6
self.room = room def __init__(self, room):
self.players = [] self.room = room
self.players = []
def __len__(self):
return len(self.players) def __len__(self):
return len(self.players)
def __repr__(self):
return "ROOM {}, {} player(s)".format(str(self.room), len(self)) def __repr__(self):
return "ROOM {}, {} player(s)".format(str(self.room), len(self))
def __iter__(self):
return iter(self.players) def __iter__(self):
return iter(self.players)
def player_add(self, player):
if len(self) >= 2: def player_add(self, player):
return if len(self) >= 2:
self.players.append(player) return
self.players.append(player)
def player_delete(self, player):
try: def player_delete(self, player):
self.players.remove(player) try:
except: self.players.remove(player)
pass if len(self) == 1:
return True
else:
return False
"""async def start(self): except:
p1, p2 = self.players[0].player, self.players[1].player pass
first = random.choice([p1, p2])
print(first, p1, p2)
first.playing = True # so the first one will be random def start(self): # initialize the game
await sendTo(first.name + "先攻", *self.players) p1, p2 = self.players[0].player, self.players[1].player
print(first.name,"先攻") ws_list = self.players[:]
print() # change line
for _ in range(3): # 初始手牌*3 firstws = ws_list.pop(random.randint(0, 1))
game.draw(p1) #print(first, p1, p2)
game.draw(p2) firstws.player.playing = True # so the first one will be random
#await sendTo(first.player.name + "先攻", *self.players)
while p1.life > 0 and p2.life > 0:
print("game.turn start") print(firstws.player.name,"先攻")
await game.turn(self.players[0], self.players[1]) print() # change line
print("game.turn end") for _ in range(3): # 初始手牌*3
if p1.life <= 0: game.draw(p1)
print("{} 獲勝".format(p2.name)) game.draw(p2)
elif p2.life <= 0: return firstws, ws_list[0] # it will be second player
print("{} 獲勝".format(p1.name))""" @staticmethod
def start(self): # initialize the game def start_turn(wscur, wsene):
p1, p2 = self.players[0].player, self.players[1].player cur, ene = wscur.player, wsene.player
ws_list = self.players[:]
message_to_send = []
firstws = ws_list.pop(random.randint(0, 1))
#print(first, p1, p2)
firstws.player.playing = True # so the first one will be random cur.playing, ene.playing = ene.playing, cur.playing
#await sendTo(first.player.name + "先攻", *self.players)
cur.turn += 1
print(firstws.player.name,"先攻") draw_res = game.draw(cur)
print() # change line if not draw_res:
for _ in range(3): # 初始手牌*3 message_to_send.append(( (wscur, wsene), dumps({"msg": "noCard", "data": [cur.name]})))
game.draw(p1) else:
game.draw(p2) message_to_send.append(( (wscur,), draw_res))
return firstws, ws_list[0] # it will be second player
@staticmethod if cur.poison_check():
def start_turn(wscur, wsene): message_to_send.append(( (wscur,wsene), dumps({"msg": "poisonDamaged", "data": [cur.name,cur.poison]})))
cur, ene = wscur.player, wsene.player
message_to_send.append(( (wscur,),
message_to_send = [] dumps({"player": {
"turn": cur.turn, "hand": cur.hand, "deck_left": len(cur.deck),
cur.playing, ene.playing = ene.playing, cur.playing "life": cur.life, "poison": cur.poison,
},
cur.turn += 1 "enemy": {
"life": ene.life, "deck_left": len(ene.deck),
message_to_send.append(( (wscur,), game.draw(cur))) "hand": len(ene.hand), "poison": ene.poison,
message_to_send.append(( (wscur,), },
dumps({"player": { "now": "player",
"turn": cur.turn, "hand": cur.hand, "deck_left": len(cur.deck), }
"life": cur.life )
} ))
}
) message_to_send.append(( (wsene,),
)) dumps({"player": {
"turn": ene.turn, "hand": ene.hand, "deck_left": len(ene.deck),
message_to_send.append(( (wsene,), "life": ene.life, "poison": ene.poison,
dumps({"enemy": { },
"turn": cur.turn, "deck_left": len(cur.deck), "enemy": {
"life": cur.life # cur為當前回合之玩家故此處仍為cur "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 message_to_send.append(( (wsene,), dumps({"msg": "drawEne", "data": [cur.name]})))
if cur.poison_check():
message_to_send.append(( (wscur,wsene), "{} 受到了劇毒的侵蝕, 損失{}點生命".format(cur.name,cur.poison))) cur.status = Room.IN_TURN
if cur.life <= 0:
pass if cur.life <= 0:
#await sendTo(health(p1,p2), wsp1, wsp2) message_to_send.append(( (wscur,), dumps({"msg": "win", "data": ["enemy"]})))
#await sendTo(draw(cur), wsp1, wsp2) # 抽卡 message_to_send.append(( (wsene,), dumps({"msg": "win", "data": ["player"]})))
#message_to_send.append(( (wscur,), game.display(cur))) # 顯示手牌
#message_to_send.append(( (wscur,), "請問要使用手牌嗎? 若不使用請輸入0")) elif ene.life <= 0:
return message_to_send message_to_send.append(( (wscur,), dumps({"msg": "win", "data": ["player"]})))
message_to_send.append(( (wsene,), dumps({"msg": "win", "data": ["enemy"]})))
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'] return message_to_send
cur = wscur.player
wsene = self.players[1] if wscur is self.players[0] else self.players[0] def process(self, wscur, message): # cur is the person who send message to server
ene = wsene.player
message_to_send = [] start_next_turn_cards = ['2', '3', '4', '8', '11', '12', '13', '14', '15', '16']
choice = message cur = wscur.player
if cur.status == self.IN_TURN: wsene = self.players[1] if wscur is self.players[0] else self.players[0]
ene = wsene.player
if choice in cur.hand: message_to_send = []
choice = message
message_to_send.extend(card.skills[choice](wscur, wsene))
if choice in start_next_turn_cards: if cur.status == self.IN_TURN:
cur.status = self.NOTHING
message_to_send.extend(Room.start_turn(wsene, wscur)) if choice in cur.hand:
message_to_send.append(((wsene, wscur), dumps({"msg": "use", "data": [cur.name, choice]})))
cur.remove_card(choice) cur.remove_card(choice)
elif choice == "0":
cur.status = self.NOTHING message_to_send.extend(card.skills[choice](wscur, wsene))
message_to_send.extend(Room.start_turn(wsene, wscur))
"""elif choice == "-1": if choice in start_next_turn_cards:
cur.surrender() cur.status = self.NOTHING
{}投降".format(cur.name)""" message_to_send.extend(Room.start_turn(wsene, wscur))
elif cur.status == self.ROBBING: else: # 直接結束
pass cur.status = self.NOTHING
message_to_send.extend(Room.start_turn(wsene, wscur))
elif cur.status == self.ROBBED:
pass
elif cur.status == self.DEFENCE: # cur是被攻擊方 elif cur.status == self.ROBBING:
if choice in cur.hand: swag = choice
if choice in card.unattackable: ene.status = self.NOTHING
message_to_send.extend(card.skills[choice](wscur,wsene)) if swag in ene.hand:
cur.remove_card(choice) cur.robbing = swag
elif choice == "0": if ene.keep():
message_to_send.append(( (wsene, wscur), "{} 受到{}點傷害".format(cur.name,ene.damage))) cur.status = Room.NOTHING
ene.life -= cur.damage ene.status = Room.ROBBED
else: message_to_send.append(((wsene, ), dumps({"action": "toBeRobbed"})))
message_to_send.append(( (wscur,wsene), "{} 受到{}點傷害".format(cur.name,ene.damage))) else:
cur.life -= cur.damage ene.robbed(swag)
ene.attacking = False cur.add_card(swag)
ene.damage = 0 # reset message_to_send.append(( (wscur,wsene), dumps({"msg": "robbed", "data": [cur.name, cur.robbing]})))
message_to_send.extend(Room.start_turn(wscur, wsene)) cur.robbing = "0"
cur.status = Room.NOTHING
elif cur.status == self.TRADE:
pass message_to_send.extend(Room.start_turn(wsene, wscur))
elif cur.status == self.PLAN: else: # 直接結束
pass message_to_send.append(((wsene, wscur), dumps({"msg": "cantRob", "data": [cur.name]})))
return message_to_send message_to_send.extend(Room.start_turn(wsene, wscur))
async def sendTo(message, *ws_list):
for ws in ws_list:
await ws.send(message) 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)

388
spec.json
View File

@ -1,192 +1,198 @@
choose character: "5" choose character: "5"
enter_room: room number / "n" // "n" to create a random room and enter it enter_room: room number / "n" // "n" to create a random room and enter it
out: room number / {"room": 18693, "cur": "圭月", "ene": "小兔"} out: room number / {"room": 7122, "cur": "圭月", "ene": "小兔"}
// shows room number, or send a object shows your player and enemy's // shows room number, or send a object shows your player and enemy's
: :
{"msg": "firstAttack", "data": [firstPlayer.name], "hand": player.hand} {"msg": "firstAttack", "data": [firstPlayer.name], "hand": player.hand}
: :
{ {
"player": { "player": {
"turn": 3, "hand": ['1','2','3','1','1','1'], "deck_left": 35, "turn": 3, "hand": ['1','2','3','1','1','1'], "deck_left": 35,
"life": 20 "life": 20, "poison": 0,
}, },
"enemy": {"turn": 3, "life": 20, "deck_left": 35 "enemy": {"turn": 3, "life": 20, "deck_left": 35, "hand": 30, "poison": 1,
} }
} }
{
"attack": "{} 攻擊 {}", {
"damaged": "{} 受到{}點傷害", "attack": "{} 攻擊 {}",
//"toDefend": "請問要防禦嗎?不出牌請輸入0", "damaged": "{} 受到{}點傷害",
"defended": "{} 防禦成功", //"toDefend": "請問要防禦嗎?不出牌請輸入0",
"defend": "{} 沒什麼可以防禦的,回復一點生命", "defended": "{} 防禦成功",
"heal": "{} 回復兩點生命", "defend": "{} 沒什麼可以防禦的,回復一點生命",
"supply": "{} 增加兩張手牌", "heal": "{} 回復兩點生命",
"rob": "{} 正在對 {} 行搶", "supply": "{} 增加兩張手牌",
"cantRob": "可惜,{} 有夠窮,沒東西能搶", "rob": "{} 正在對 {} 行搶",
"robbed": "{} 搶到了 {}" "cantRob": "{}沒有搶到任何東西",
"surprise": "{} 發動奇襲", "robbed": "{} 搶到了 {}",
"surprised": "{} 受到{}點傷害,而且掉了一張手牌", "surprise": "{} 發動奇襲",
"trade": "{} 想與 {} 進行交易", "surprised": "{} 受到{}點傷害,而且掉了一張手牌",
"tradeChoose": "{} 選擇了 {}", "trade": "{} 想與 {} 進行交易",
//"toRob": "{} 要搶哪張?", "tradeChoose": "{} 選擇了 {}",
//"toBeRobbed": "請問要防禦嗎?" //"toRob": "{} 要搶哪張?",
//"toTrade": "選擇一張手牌以交換", //"toBeRobbed": "請問要防禦嗎?"
"awared": "{} 洞悉了 {} 的{},並抽取了一張手牌", //"toTrade": "選擇一張手牌以交換",
/* "awared": "{} 洞悉了 {} 的{},並抽取了一張手牌",
"": "{} 洞悉了 {} 的強奪,並抽取了一張手牌", /*
"": "{} 洞悉了 {} 的奇襲,並抽取了一張手牌", "": "{} 洞悉了 {} 的強奪,並抽取了一張手牌",
*/ "": "{} 洞悉了 {} 的奇襲,並抽取了一張手牌",
"aware": "{} 增加三張手牌", */
"plan": "{} 有個妙策", "aware": "{} 增加三張手牌",
//"toAdd": "選擇一張卡加入手牌", "plan": "{} 有個妙策",
"sweep": "{} 對 {} 進行掃射,威力是 {}", //"toAdd": "選擇一張卡加入手牌",
"bless": "{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌", "sweep": "{} 對 {} 進行掃射,威力是 {}",
"poison": "{} 在食物下毒,{}中毒了", "bless": "{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌",
"curse": "{} 詛咒了 {},使其損失四點生命,並掉了一張手牌", "poison": "{} 在食物下毒,{}中毒了",
"countered": "{} 反制了 {} 的攻擊,反彈了{}點傷害", "curse": "{} 詛咒了 {},使其損失四點生命,並掉了一張手牌",
"counteredSur": "{} 反制了 {} 的攻擊,反彈了{}點傷害,並使其掉了一張手牌", "countered": "{} 反制了 {} 的攻擊,反彈了{}點傷害",
"counter": "{} 反制了敵手,使 {} 生命值減半了!", "counteredSur": "{} 反制了 {} 的攻擊,反彈了{}點傷害,並使其掉了一張手牌",
"chaos": "{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害", "counter": "{} 反制了敵手,使 {} 生命值減半了!",
"reverse": "{} 一口氣逆轉了情勢", "chaos": "{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害",
//"": "{} 的生命: {}", "reverse": "{} 一口氣逆轉了情勢",
//"": "這是 {} 的手牌", //"": "{} 的生命: {}",
"noCard": "你抽到了死神", //"": "這是 {} 的手牌",
"left": "牌組剩餘: {} 張", "noCard": "你抽到了死神",
//"": "{} 抽到了 {}", "left": "牌組剩餘: {} 張",
//"inTurn": "請問要使用手牌嗎? 若不使用請輸入0", //"": "{} 抽到了 {}",
"turnNumber": "{} 的第{}回合", //"inTurn": "請問要使用手牌嗎? 若不使用請輸入0",
"poisonDamaged": "{} 受到了劇毒的侵蝕,損失{}點生命", "turnNumber": "{} 的第{}回合",
"surrender": "{}投降", "poisonDamaged": "{} 受到了劇毒的侵蝕,損失{}點生命",
"firstAttack": "{}先攻", "surrender": "{}投降",
"win": "{}獲勝", "firstAttack": "{}先攻",
"draw": "{}抽到了{}", "win": "{}獲勝",
"drawEne": "{}抽了一張卡片" "draw": "{}抽到了{}",
"drawEne": "{}抽了一張卡片",
} "use": "{}使用了{}",
"eneDisconn": "因敵方斷線,所以{}獲勝",
}
1. attack
in: "1"
out:
cur: {"msg": "attack", "data": [cur.name, ene.name]} 1. attack
ene: {"msg": "attack", "data": [cur.name, ene.name], in: "1"
"action": "toDefend", "value": {"damage": cur.damage}} / () out:
in: "2" / "8" / "14" / "0" cur: {"msg": "attack", "data": [cur.name, ene.name]}
out: ene: cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "attack"}} /
cur: {"msg": "defended", "data": [ene.name]} / cur()
{"msg": "countered", "data": [ene.name]} / in: "2" / "8" / "14" / "0"
{"msg": "awared", "data": [ene.name, "攻擊"]} / out:
{"msg": "damaged", "data": [ene.name, cur.damage]} cur: {"msg": "defended", "data": [ene.name]} /
ene: {"msg": "countered", "data": [ene.name]} /
2. defend //使 {"msg": "awared", "data": [cur.name, ene.name, "攻擊"]} /
in: "2" {"msg": "damaged", "data": [ene.name, cur.damage]}
out: ene:
cur: {"msg": "defend", "data": [cur.name]} 2. defend //使
ene: in: "2"
3. heal out:
in: "3" cur: {"msg": "defend", "data": [cur.name]}
out: ene:
cur: {"msg": "heal", "data": [cur.name]} 3. heal
ene: in: "3"
4. supply out:
in: "4" cur: {"msg": "heal", "data": [cur.name]}
out: ene:
cur: {"msg": "supply", "data": [cur.name]} 4. supply
ene: in: "4"
5. rob out:
in: "5" cur: {"msg": "supply", "data": [cur.name]}
out: ene:
cur: {"msg": "rob", "data": [cur.name, ene.name], 5. rob
"action": "toRob", "value": {"emeny_card:", ene.hand}} / in: "5"
{"msg": "cantRob", "data": [ene.name]} out:
in: card number cur: {"msg": "rob", "data": [cur.name, ene.name],
out: "action": "toRob", "value": {"enemy_card": ene.hand}} /
ene: {"action": "toBeRobbed"} / () {{"msg": "cantRob", "data": [cur.name]}]}
in: "8" / "0" in: card number
out: out:
cur: {"msg": "defended", "data": [ene.name]} / ene: {"action": "toBeRobbed"} / ()
{"msg": "robbed", "data": [ene.name, card]} in: "8" / "0"
ene: out:
ene: / {"msg": "cantRob", "data": [ene.name]} cur: {"msg": "awared", "data": [cur.name, ene.name, "搶奪"]} /
6. surprise {"msg": "robbed", "data": [ene.name, card]}
in: "6" ene:
out: ene: / {{"msg": "cantRob", "data": [cur.name]}]}
cur: 6. surprise
ene: {"action": "toDefend", "value": {"damage": cur.damage}} / () in: "6"
in: "2" / "8" / "14" / "0" out:
out: cur: {"msg": "surprise", "data": [cur.name]}
cur: {"msg": "defended", "data": [ene.name]} / ene: cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "suprise"}} /
{"msg": "counteredSur", "data": [ene.name]} / cur()
{"msg": "awared", "data": [ene.name, "奇襲"]} / in: "2" / "8" / "14" / "0"
{"msg": "surprised", "data": [ene.name, cur.damage]} out:
ene: cur: {"msg": "defended", "data": [ene.name]} /
7. trade {"msg": "counteredSur", "data": [ene.name]} /
in: "7" {"msg": "awared", "data": [cur.name, ene.name, "奇襲"]} /
out: {"msg": "surprised", "data": [ene.name, cur.damage]}
cur: {"msg": "trade", "data": [cur.name, ene.name], "action": "toTrade"} ene:
in: card number 7. trade
out: in: "7"
cur: {"msg": "tradeChoose", "data": [cur.name, card number]} out:
ene: {"action": "toTrade"} cur: {"msg": "trade", "data": [cur.name, ene.name]},
ene: {"msg": "trade", "data": [cur.name, ene.name]} {"action": "toTrade", "value": ["hand": cur.hand]}
8. aware //使 in: card number
in: "8" out:
out: cur: {"msg": "tradeChoose", "data": [cur.name, card number]}
cur: {"msg": "aware", "data": [cur.name]} ene: cur, {"action": "toTrade"}
ene: ene: {"msg": "trade", "data": [cur.name, ene.name]}
9. plan 8. aware //使
in: "9" in: "8"
out: out:
cur: {"msg": "plan", "data": [cur.name], cur: {"msg": "aware", "data": [cur.name]}
"action": "toAdd", "value": {"cards": list}} ene:
in: card number 9. plan
ene: {"msg": "plan", "data": [cur.name]} in: "9"
10. bless out:
in: "10" cur: {"msg": "plan", "data": [cur.name]},
out: {"action": "toAdd", "value": {"cards": list}}
cur: {"msg": "bless", "data": [cur.name]} in: card number
ene: ene: {"msg": "plan", "data": [cur.name]}
11. sweep 10. bless
in: "11" in: "10"
out: out:
cur: cur: {"msg": "bless", "data": [cur.name]}
ene: {"action": "toDefend", "value": {"damage": cur.damage}} / () ene:
in: "2" / "8" / "14" / "0" 11. sweep
out: in: "11"
cur: {"msg": "defended", "data": [ene.name]} / out:
{"msg": "countered", "data": [ene.name]} / cur: {"msg": "sweep", "data": [cur.name, ene.name, cur.damage]}
{"msg": "awared", "data": [ene.name, "掃射"]} / ene: cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "sweep"}} /
{"msg": "damaged", "data": [ene.name, cur.damage]} ()
ene: in: "2" / "8" / "14" / "0"
12. poison out:
in: "12" cur: {"msg": "defended", "data": [ene.name]} /
out: {"msg": "countered", "data": [ene.name]} /
cur: {"msg": "poison", "data": [cur.name, ene.name]} {"msg": "awared", "data": [cur.name, ene.name, "掃射"]} /
ene: {"msg": "damaged", "data": [ene.name, cur.damage]}
13. curse ene:
in: "13" 12. poison
out: in: "12"
cur: {"msg": "curse", "data": [cur.name, ene.name]} out:
ene: cur: {"msg": "poison", "data": [cur.name, ene.name]}
14. counter //使 ene:
in: "14" 13. curse
out: in: "13"
cur: {"msg": "counter", "data": [cur.name, ene.name]} out:
ene: cur: {"msg": "curse", "data": [cur.name, ene.name]}
15. chaos ene:
in: "15" 14. counter //使
out: in: "14"
cur: {"msg": "chaos", "data": [cur.name, ene.name]} out:
ene: cur: {"msg": "counter", "data": [cur.name, ene.name]}
16. reverse ene:
in: "16" 15. chaos
out: in: "15"
cur: {"msg": "reverse", "data": [cur.name]} out:
cur: {"msg": "chaos", "data": [cur.name, ene.name]}
ene:
16. reverse
in: "16"
out:
cur: {"msg": "reverse", "data": [cur.name]}
ene: ene: