first stable version

This commit is contained in:
Jerry Wu 2018-06-01 18:17:10 +08:00
parent 152a71ff05
commit 4e8525f4cf
5 changed files with 737 additions and 595 deletions

263
card.py
View File

@ -3,6 +3,7 @@ import game
from room import Room from room import Room
from json import dumps from json import dumps
cards = dict() cards = dict()
card_name = ["1.攻擊","2.防禦","3.治癒","4.補給","5.強奪","6.奇襲","7.交易","8.洞悉","9.妙策","10.掃射","11.加護","12.劇毒","13.詛咒","14.反制","15.狂亂","16.逆轉"] card_name = ["1.攻擊","2.防禦","3.治癒","4.補給","5.強奪","6.奇襲","7.交易","8.洞悉","9.妙策","10.掃射","11.加護","12.劇毒","13.詛咒","14.反制","15.狂亂","16.逆轉"]
unattackable = ['2','8','14','17','18'] unattackable = ['2','8','14','17','18']
@ -10,9 +11,14 @@ unrobable = ['8','17','18']
for i in range(len(card_name)): for i in range(len(card_name)):
cards[str(i+1)] = card_name[i] # initialize cards 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 +32,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 +43,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 +70,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 +97,206 @@ 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 = []
r.append(( (wscur, ), dumps({"msg": "rob", "data": [cur.name, ene.name],
"action": "toRob", "value": {"enemy_card": ene.hand}})))
cur.robbing = True cur.status = Room.ROBBING
print("{} 正在對 {} 行搶".format(cur.name,ene.name)) r.append(( (wsene, ), dumps({"msg": "rob", "data": [cur.name, ene.name]})))
if ene.keep(): return r
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
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 = []
if ene.hand:
r.append(( (wsene, wscur),
dumps({"msg": "trade", "data": [cur.name, ene.name]})
))
print("{} 想與 {} 進行交易".format(cur.name,ene.name)) r.append(( (wscur,),
cur.remove_card("7") # you can't trade the using card "trade" dumps({"action": "toTrade", "value": {"hand": cur.hand}}) # 更新已被移除的trade
game.display(cur) # 顯示手牌 ))
while True: cur.status = Room.TRADE
choice = input("選擇一張手牌以交換 ") else:
if choice in cur.hand: r.append(( (wscur,wsene),
cur_item = choice dumps({"msg": "tradeNoCard", "data": [cur.name]})
print("{} 選擇了 {}".format(cur.name,cards[choice])) ))
break r.extend(Room.start_turn(wsene, wscur))
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 return r
def aware(wscur,wsene): def aware(wscur,wsene):
cur, ene = wscur.player, wsene.player cur, ene = wscur.player, wsene.player
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, "奇襲"]})))
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)
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
"""while True:
choice = input("選擇一張卡加入手牌 ") choice = input("選擇一張卡加入手牌 ")
if choice in options: if choice in options:
cur.add_card(choice) cur.add_card(choice)
break break"""
return r
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
r.extend(Room.start_turn(wsene, wscur))
cur.attacking = False cur.attacking = False
cur.damage = 0 # reset 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 = []
r.append(( (wsene,wscur), dumps({"msg": "bless", "data": [cur.name]})))
print("{} 獲得加護,身上的毒素一掃而空,並回復三點生命,還抽取了兩張手牌".format(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 = []
r.append(( (wsene,wscur), dumps({"msg": "poison", "data": [cur.name, ene.name]})))
if ene.poison != 0:
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
msg = "curseNoCard"
if ene.hand:
drop = random.choice(ene.hand) drop = random.choice(ene.hand)
ene.remove_card(drop) 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 = []
r.append(( (wsene,wscur), dumps({"msg": "reverse", "data": [cur.name, ene.name]})))
print("{} 進入狂亂模式,回復三點生命,並對 {} 造成三點傷害".format(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]

51
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
try:
self.hand.remove(id) self.hand.remove(id)
self.display.remove(card.cards[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:
@ -65,7 +66,7 @@ def display(player):
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 +74,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!

113
pyws.py
View File

@ -3,11 +3,12 @@ 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() character = dict()
name=["","圭月","","小兔","","正作","W","桑德","海爾","雪村"] name=["","圭月","","小兔","","正作","W","桑德","海爾","雪村"]
@ -18,6 +19,7 @@ for i in range(len(name)):
sad = None 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,33 +27,27 @@ 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):
if list(done)[0].exception() == None:
return list(done)[0].result() return list(done)[0].result()
else: else:
#print("SADDDDD") return "exception"
return def random_room(room_list):
def random_room():
global connected, rooms while len(room_list)>=1:
try: enter = random.choice(room_list)
print(rooms) print("rooms", enter, room_list)
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 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
@ -66,7 +62,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)
@ -91,15 +87,16 @@ async def enter_room(websocket):
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,sad, 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 +110,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
@ -130,41 +128,92 @@ async def handler(websocket, path):
print("SAD", "FIRST" if websocket == sad else "SECOND") 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 connected[websocket.room]
del 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") print("SADDDDDD", "FIRST" if websocket == sad else "SECOND")
elif websocket.status == Room.PLAYING: 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) message_to_send = connected[websocket.room].process(websocket, message)
for ws_list, message in message_to_send: for ws_list, message in message_to_send:
await sendTo(message, *ws_list) 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("FIRST" if websocket == sad else "SECOND", "was 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()

163
room.py
View File

@ -1,12 +1,12 @@
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
@ -15,7 +15,8 @@ class Room:
DEFENCE = 2 DEFENCE = 2
ROBBING = 3 ROBBING = 3
TRADE = 4 TRADE = 4
PLAN = 5 TRADE_ENE = 5
PLAN = 6
def __init__(self, room): def __init__(self, room):
self.room = room self.room = room
self.players = [] self.players = []
@ -38,6 +39,10 @@ class Room:
def player_delete(self, player): def player_delete(self, player):
try: try:
self.players.remove(player) self.players.remove(player)
if len(self) == 1:
return True
else:
return False
except: except:
pass pass
@ -84,36 +89,62 @@ class Room:
message_to_send = [] message_to_send = []
cur.playing, ene.playing = ene.playing, cur.playing cur.playing, ene.playing = ene.playing, cur.playing
cur.turn += 1 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,), game.draw(cur)))
message_to_send.append(( (wscur,), message_to_send.append(( (wscur,),
dumps({"player": { dumps({"player": {
"turn": cur.turn, "hand": cur.hand, "deck_left": len(cur.deck), "turn": cur.turn, "hand": cur.hand, "deck_left": len(cur.deck),
"life": cur.life "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,), message_to_send.append(( (wsene,),
dumps({"enemy": { 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), "turn": cur.turn, "deck_left": len(cur.deck),
"life": cur.life # cur為當前回合之玩家故此處仍為cur "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]}))) message_to_send.append(( (wsene,), dumps({"msg": "drawEne", "data": [cur.name]})))
cur.status = Room.IN_TURN cur.status = Room.IN_TURN
if cur.poison_check():
message_to_send.append(( (wscur,wsene), "{} 受到了劇毒的侵蝕, 損失{}點生命".format(cur.name,cur.poison)))
if cur.life <= 0: if cur.life <= 0:
pass 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(health(p1,p2), wsp1, wsp2)
#await sendTo(draw(cur), wsp1, wsp2) # 抽卡 #await sendTo(draw(cur), wsp1, wsp2) # 抽卡
#message_to_send.append(( (wscur,), game.display(cur))) # 顯示手牌 #message_to_send.append(( (wscur,), game.display(cur))) # 顯示手牌
@ -128,50 +159,134 @@ class Room:
ene = wsene.player ene = wsene.player
message_to_send = [] message_to_send = []
choice = message choice = message
if cur.status == self.IN_TURN: if cur.status == self.IN_TURN:
if choice in cur.hand: 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)) message_to_send.extend(card.skills[choice](wscur, wsene))
if choice in start_next_turn_cards: if choice in start_next_turn_cards:
cur.status = self.NOTHING cur.status = self.NOTHING
message_to_send.extend(Room.start_turn(wsene, wscur)) message_to_send.extend(Room.start_turn(wsene, wscur))
cur.remove_card(choice) else: # 直接結束
elif choice == "0":
cur.status = self.NOTHING cur.status = self.NOTHING
message_to_send.extend(Room.start_turn(wsene, wscur)) message_to_send.extend(Room.start_turn(wsene, wscur))
"""elif choice == "-1": """elif choice == "-1":
cur.surrender() cur.surrender()
{}投降".format(cur.name)""" {}投降".format(cur.name)"""
elif cur.status == self.ROBBING: elif cur.status == self.ROBBING:
pass 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: elif cur.status == self.ROBBED:
pass 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是被攻擊方 elif cur.status == self.DEFENCE: # cur是被攻擊方
if choice in cur.hand: if choice in cur.hand:
if choice in card.unattackable: if choice in card.unattackable:
message_to_send.extend(card.skills[choice](wscur,wsene)) message_to_send.extend(card.skills[choice](wscur,wsene))
cur.remove_card(choice) cur.remove_card(choice)
elif choice == "0":
message_to_send.append(( (wsene, wscur), "{} 受到{}點傷害".format(cur.name,ene.damage)))
ene.life -= cur.damage
else: else:
message_to_send.append(( (wscur,wsene), "{} 受到{}點傷害".format(cur.name,ene.damage))) if ene.surprise:
cur.life -= cur.damage 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.attacking = False
ene.surprise = False # 兩個都取消
ene.damage = 0 # reset ene.damage = 0 # reset
message_to_send.extend(Room.start_turn(wscur, wsene)) message_to_send.extend(Room.start_turn(wscur, wsene))
elif cur.status == self.TRADE: elif cur.status == self.TRADE:
pass 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: elif cur.status == self.PLAN:
pass 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 return message_to_send
async def sendTo(message, *ws_list): async def sendTo(message, *ws_list):
for ws in ws_list: for ws in ws_list:

View File

@ -1,7 +1,7 @@
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
: :
@ -12,13 +12,14 @@ enter_room: room number / "n" // "n" to create a random room and enter it
{ {
"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": "{} 攻擊 {}", "attack": "{} 攻擊 {}",
"damaged": "{} 受到{}點傷害", "damaged": "{} 受到{}點傷害",
@ -28,8 +29,8 @@ enter_room: room number / "n" // "n" to create a random room and enter it
"heal": "{} 回復兩點生命", "heal": "{} 回復兩點生命",
"supply": "{} 增加兩張手牌", "supply": "{} 增加兩張手牌",
"rob": "{} 正在對 {} 行搶", "rob": "{} 正在對 {} 行搶",
"cantRob": "可惜,{} 有夠窮,沒東西能搶", "cantRob": "{}沒有搶到任何東西",
"robbed": "{} 搶到了 {}" "robbed": "{} 搶到了 {}",
"surprise": "{} 發動奇襲", "surprise": "{} 發動奇襲",
"surprised": "{} 受到{}點傷害,而且掉了一張手牌", "surprised": "{} 受到{}點傷害,而且掉了一張手牌",
"trade": "{} 想與 {} 進行交易", "trade": "{} 想與 {} 進行交易",
@ -66,7 +67,9 @@ enter_room: room number / "n" // "n" to create a random room and enter it
"firstAttack": "{}先攻", "firstAttack": "{}先攻",
"win": "{}獲勝", "win": "{}獲勝",
"draw": "{}抽到了{}", "draw": "{}抽到了{}",
"drawEne": "{}抽了一張卡片" "drawEne": "{}抽了一張卡片",
"use": "{}使用了{}",
"eneDisconn": "因敵方斷線,所以{}獲勝",
} }
@ -76,13 +79,13 @@ enter_room: room number / "n" // "n" to create a random room and enter it
in: "1" in: "1"
out: out:
cur: {"msg": "attack", "data": [cur.name, ene.name]} cur: {"msg": "attack", "data": [cur.name, ene.name]}
ene: {"msg": "attack", "data": [cur.name, ene.name], ene: cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "attack"}} /
"action": "toDefend", "value": {"damage": cur.damage}} / () cur()
in: "2" / "8" / "14" / "0" in: "2" / "8" / "14" / "0"
out: out:
cur: {"msg": "defended", "data": [ene.name]} / cur: {"msg": "defended", "data": [ene.name]} /
{"msg": "countered", "data": [ene.name]} / {"msg": "countered", "data": [ene.name]} /
{"msg": "awared", "data": [ene.name, "攻擊"]} / {"msg": "awared", "data": [cur.name, ene.name, "攻擊"]} /
{"msg": "damaged", "data": [ene.name, cur.damage]} {"msg": "damaged", "data": [ene.name, cur.damage]}
ene: ene:
2. defend //使 2. defend //使
@ -104,37 +107,39 @@ enter_room: room number / "n" // "n" to create a random room and enter it
in: "5" in: "5"
out: out:
cur: {"msg": "rob", "data": [cur.name, ene.name], cur: {"msg": "rob", "data": [cur.name, ene.name],
"action": "toRob", "value": {"emeny_card:", ene.hand}} / "action": "toRob", "value": {"enemy_card": ene.hand}} /
{"msg": "cantRob", "data": [ene.name]} {{"msg": "cantRob", "data": [cur.name]}]}
in: card number in: card number
out: out:
ene: {"action": "toBeRobbed"} / () ene: {"action": "toBeRobbed"} / ()
in: "8" / "0" in: "8" / "0"
out: out:
cur: {"msg": "defended", "data": [ene.name]} / cur: {"msg": "awared", "data": [cur.name, ene.name, "搶奪"]} /
{"msg": "robbed", "data": [ene.name, card]} {"msg": "robbed", "data": [ene.name, card]}
ene: ene:
ene: / {"msg": "cantRob", "data": [ene.name]} ene: / {{"msg": "cantRob", "data": [cur.name]}]}
6. surprise 6. surprise
in: "6" in: "6"
out: out:
cur: cur: {"msg": "surprise", "data": [cur.name]}
ene: {"action": "toDefend", "value": {"damage": cur.damage}} / () ene: cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "suprise"}} /
cur()
in: "2" / "8" / "14" / "0" in: "2" / "8" / "14" / "0"
out: out:
cur: {"msg": "defended", "data": [ene.name]} / cur: {"msg": "defended", "data": [ene.name]} /
{"msg": "counteredSur", "data": [ene.name]} / {"msg": "counteredSur", "data": [ene.name]} /
{"msg": "awared", "data": [ene.name, "奇襲"]} / {"msg": "awared", "data": [cur.name, ene.name, "奇襲"]} /
{"msg": "surprised", "data": [ene.name, cur.damage]} {"msg": "surprised", "data": [ene.name, cur.damage]}
ene: ene:
7. trade 7. trade
in: "7" in: "7"
out: out:
cur: {"msg": "trade", "data": [cur.name, ene.name], "action": "toTrade"} cur: {"msg": "trade", "data": [cur.name, ene.name]},
{"action": "toTrade", "value": ["hand": cur.hand]}
in: card number in: card number
out: out:
cur: {"msg": "tradeChoose", "data": [cur.name, card number]} cur: {"msg": "tradeChoose", "data": [cur.name, card number]}
ene: {"action": "toTrade"} ene: cur, {"action": "toTrade"}
ene: {"msg": "trade", "data": [cur.name, ene.name]} ene: {"msg": "trade", "data": [cur.name, ene.name]}
8. aware //使 8. aware //使
in: "8" in: "8"
@ -144,8 +149,8 @@ enter_room: room number / "n" // "n" to create a random room and enter it
9. plan 9. plan
in: "9" in: "9"
out: out:
cur: {"msg": "plan", "data": [cur.name], cur: {"msg": "plan", "data": [cur.name]},
"action": "toAdd", "value": {"cards": list}} {"action": "toAdd", "value": {"cards": list}}
in: card number in: card number
ene: {"msg": "plan", "data": [cur.name]} ene: {"msg": "plan", "data": [cur.name]}
10. bless 10. bless
@ -156,13 +161,14 @@ enter_room: room number / "n" // "n" to create a random room and enter it
11. sweep 11. sweep
in: "11" in: "11"
out: out:
cur: cur: {"msg": "sweep", "data": [cur.name, ene.name, cur.damage]}
ene: {"action": "toDefend", "value": {"damage": cur.damage}} / () ene: cur, {"action": "toDefend", "value": {"damage": cur.damage, "type": "sweep"}} /
()
in: "2" / "8" / "14" / "0" in: "2" / "8" / "14" / "0"
out: out:
cur: {"msg": "defended", "data": [ene.name]} / cur: {"msg": "defended", "data": [ene.name]} /
{"msg": "countered", "data": [ene.name]} / {"msg": "countered", "data": [ene.name]} /
{"msg": "awared", "data": [ene.name, "掃射"]} / {"msg": "awared", "data": [cur.name, ene.name, "掃射"]} /
{"msg": "damaged", "data": [ene.name, cur.damage]} {"msg": "damaged", "data": [ene.name, cur.damage]}
ene: ene:
12. poison 12. poison