import socket
import this
import requests
import sys
import json
from threading import Thread
from queue import Queue
#multithreading?
class Move :
def __init__ ( self , start_loc , end_loc , board ) :
self . start_row = start_loc [ 0 ]
self . start_col = start_loc [ 1 ]
self . end_row = end_loc [ 0 ]
self . end_col = end_loc [ 1 ]
self . nxt_piece = board [ self . end_row ] [ self . end_col ]
self . cur_piece = board [ self . start_row ] [ self . start_col ]
self . attack = self . nxt_piece != ' 00 '
self . moveID = self . start_row + self . start_col * 10 + self . end_row * 100 + self . end_col * 1000 #Hash
def __eq__ ( self , __o : object ) - > bool :
if isinstance ( __o , Move ) :
return self . moveID == __o . moveID
return False
def __str__ ( self ) :
return f " { self . start_row =} , " + f " { self . start_col =} , " + f " { self . end_row =} , " + f " { self . end_col =} "
def get_goal ( self ) :
return ( self . end_row , self . end_col )
def get_start ( self ) :
return ( self . start_row , self . start_col )
def get_goal_chess_comb ( self ) :
return ( self . end_row , self . end_col , self . cur_piece )
def get_turn ( self ) :
return self . cur_piece [ 0 ]
def get_piece ( self ) :
return self . cur_piece
def startNewThread ( target ) :
thread = Thread ( target = target )
thread . daemon = True
thread . start ( )
class GameState :
def __init__ ( self ) :
'''
有关信息 :
1. 棋盘尺寸为7 * 9 ( 横向 )
2. 按照以下命名格式对棋盘中的棋子进行标注 :
( b | r ) ( 1 | 2 | 3 | 4 | 5 | 6 | 7 )
3. 左方为蓝方 , 对应的网络服务器中的side项目编号为0
右方为红方 , 对应的网络服务器中的side项目编号为1
4. 网络版需要额外的类变量 : type , game_id , side , chessman ( piece ) , src , dst
'''
self . board = [
[ ' 00 ' , ' 00 ' , ' b7 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r1 ' , ' 00 ' , ' 00 ' ] ,
[ ' 00 ' , ' b2 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r3 ' , ' 00 ' ] ,
[ ' 00 ' , ' 00 ' , ' b4 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r5 ' , ' 00 ' , ' 00 ' ] ,
[ ' 00 ' , ' 00 ' , ' b6 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r6 ' , ' 00 ' , ' 00 ' ] ,
[ ' 00 ' , ' 00 ' , ' b5 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r4 ' , ' 00 ' , ' 00 ' ] ,
[ ' 00 ' , ' b3 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r2 ' , ' 00 ' ] ,
[ ' 00 ' , ' 00 ' , ' b1 ' , ' 00 ' , ' 00 ' , ' 00 ' , ' r7 ' , ' 00 ' , ' 00 ' ] ,
]
#用数字1-7代替棋子的强弱关系
self . moveFunctions = {
" 1 " : self . getMseMoves ,
" 2 " : self . getEagMoves ,
" 3 " : self . getFoxMoves ,
" 4 " : self . getStdMoves ,
" 5 " : self . getStdMoves ,
" 6 " : self . getLionMoves ,
" 7 " : self . getStdMoves ,
}
self . blue_trap_loc = [ ( 2 , 0 ) , ( 3 , 1 ) , ( 4 , 0 ) ]
self . red_trap_loc = [ ( 3 , 7 ) , ( 2 , 8 ) , ( 4 , 8 ) ]
self . blue_home = ( 3 , 0 )
self . red_home = ( 3 , 8 )
self . blue_pieces = [ 7 , 6 , 5 , 4 , 3 , 2 , 1 ]
self . red_pieces = [ 7 , 6 , 5 , 4 , 3 , 2 , 1 ]
#红方(右)先行
self . red_to_move = True
self . conquered = False
self . win_person = ' '
self . MASSACRE = False
self . isStarted = False
self . move_log = [ ]
def color ( self ) :
return ' r ' if self . red_to_move else ' b '
def exchange ( self ) :
self . red_to_move = not self . red_to_move
def seventy_three_violation ( self , goal , color , showTrace = False ) :
#输入: goal为三元组(格坐标x, 格坐标y, 棋子)
# color为颜色
# showTrace为是否查看轨迹
past7Moves = [ ]
#寻找该动物的移动轨迹
for i in range ( len ( self . move_log ) - 1 , - 1 , - 1 ) :
if self . move_log [ i ] . get_turn ( ) == color :
past7Moves . append ( self . move_log [ i ] )
if len ( past7Moves ) > 7 :
break
# print("past7Moves= ",[move.get_goal_chess_comb() for move in past7Moves])
if len ( past7Moves ) > 7 :
past7Moves = past7Moves [ - 7 : ]
visit_counts = dict ( )
for move in past7Moves :
if move . get_goal ( ) in ( self . blue_trap_loc + self . red_trap_loc ) :
return True
try :
visit_counts [ move . get_goal_chess_comb ( ) ] + = 1
except KeyError :
visit_counts [ move . get_goal_chess_comb ( ) ] = 1
try :
if visit_counts [ goal ] > = 3 :
if showTrace :
return ( goal , [ move . get_goal ( ) for move in past7Moves ] )
else :
return False
else :
return True
except :
return True
def seventeen_five_violation ( self , goal , color , showTrace = False ) :
# 输入: goal为三元组(格坐标x, 格坐标y, 棋子)
# color为颜色
# showTrace为是否查看轨迹
#获取近17步操作
RECENT_COUNT = 17
PERMIT_RANGE = 5
# print("using params: {}, {}, {}".format(goal, color, showTrace))
past17Moves = [ ]
for i in range ( len ( self . move_log ) - 1 , - 1 , - 1 ) :
if self . move_log [ i ] . get_turn ( ) == color :
past17Moves . append ( self . move_log [ i ] )
if len ( past17Moves ) > RECENT_COUNT :
break
if len ( past17Moves ) > = RECENT_COUNT :
past17Moves = past17Moves [ - RECENT_COUNT : ]
else :
return True
#print("past17Movesloc: {}".format([move.get_goal() for move in past17Moves]))
#判断是否为同一棋子的移动
piece = past17Moves [ 0 ] . get_piece ( )
for i in range ( len ( past17Moves ) ) :
if past17Moves [ i ] . get_piece ( ) != piece :
return True
#当为同一棋子时……
visit_locs = [ ]
for move in past17Moves :
if move . get_goal ( ) in ( self . blue_trap_loc + self . red_trap_loc ) :
return True
this_loc = move . get_goal ( )
if this_loc not in visit_locs :
visit_locs . append ( this_loc )
try :
if showTrace and len ( visit_locs ) < = PERMIT_RANGE :
if goal in visit_locs :
return ( goal , visit_locs )
else :
return True
elif len ( visit_locs ) < = PERMIT_RANGE :
if goal in visit_locs :
return False
else :
return True
else :
return True
except :
return True
# 判断特殊位置
def inHome ( self , row , col , color ) :
if color == " b " :
if ( row , col ) == self . blue_home :
return True
else :
if ( row , col ) == self . red_home :
return True
return False
def inWater ( self , row , col ) :
if row in [ 1 , 2 , 4 , 5 ] :
if col in [ 3 , 4 , 5 ] :
return True
return False
def inTrap ( self , row , col , color ) : #是否在color方的陷阱中
if color == " b " :
if ( row , col ) in self . blue_trap_loc :
return True
else :
if ( row , col ) in self . red_trap_loc :
return True
return False
def Eliminate ( self , row , col , nxt_row , nxt_col ) : #下一步可吃对手的棋
next_blank = self . board [ nxt_row ] [ nxt_col ] == ' 00 '
attack = self . board [ nxt_row ] [ nxt_col ] [ 0 ] != self . board [ row ] [ col ] [ 0 ] and ( eval ( self . board [ row ] [ col ] [ 1 ] ) > = eval ( self . board [ nxt_row ] [ nxt_col ] [ 1 ] ) and not ( eval ( self . board [ row ] [ col ] [ 1 ] ) == 7 and eval ( self . board [ nxt_row ] [ nxt_col ] [ 1 ] ) == 1 ) or eval ( self . board [ row ] [ col ] [ 1 ] ) == 1 and eval ( self . board [ nxt_row ] [ nxt_col ] [ 1 ] ) == 7 )
other_in_trap = self . board [ row ] [ col ] [ 0 ] != self . board [ nxt_row ] [ nxt_col ] [ 0 ] and ( self . board [ nxt_row ] [ nxt_col ] [ 0 ] == ' r ' and self . inTrap ( nxt_row , nxt_col , ' b ' ) or self . board [ nxt_row ] [ nxt_col ] [ 0 ] == ' b ' and self . inTrap ( nxt_row , nxt_col , ' r ' ) )
return next_blank or attack or other_in_trap
# 定义移动方式
#----------------------------------
# 以下为移动方式的相关规定:
# 1.下一步的可行位置以二维数组的格式进行记录。
# 2.getValidMoves返回值为下一步可行位置构成的集合。
#----------------------------------
def getAllMoves ( self ) : #全部合法移动的集合
moves = [ ]
for row in range ( len ( self . board ) ) :
for col in range ( len ( self . board [ row ] ) ) :
player = self . board [ row ] [ col ] [ 0 ]
if ( player == ' r ' and self . red_to_move or player == ' b ' and not self . red_to_move ) :
#print('what color is the valid move? ',player)
self . moveFunctions [ self . board [ row ] [ col ] [ 1 ] ] ( row , col , moves )
valid_moves = [ ]
for move in moves : # 己方躲避17-5和7-3
# if self.seventy_three_violation(goal=move.get_goal_chess_comb(), color=self.color()) and self.seventeen_five_violation(goal=move.get_goal_chess_comb(), color=self.color()):
valid_moves . append ( move )
if len ( valid_moves ) == 0 :
print ( ' warning: no available moves at side {} ' . format ( ' b ' if not self . red_to_move else ' r ' ) )
return valid_moves
def getStdMoves ( self , row , col , moves ) : #输入当前的位置, 将可行路径输出给moves
directions = [ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ]
enemy_color = ' b ' if self . red_to_move else ' r '
for direction in directions :
new_row = row + direction [ 0 ] * 1
new_col = col + direction [ 1 ] * 1
if 0 < = new_row < = 6 and 0 < = new_col < = 8 :
nxt_piece = self . board [ new_row ] [ new_col ]
if nxt_piece == ' 00 ' and not self . inWater ( new_row , new_col ) and not self . inHome ( new_row , new_col , self . color ( ) ) : #如果下一个位置是空的,则可以移动
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
elif nxt_piece [ 0 ] == enemy_color and not self . inWater ( new_row , new_col ) and not self . inHome ( new_row , new_col , self . color ( ) ) and self . Eliminate ( row , col , new_row , new_col ) : #如果是敌方棋子,且不在水里,且可以消除,则添加到可行路径中
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
return moves
def getMseMoves ( self , row , col , moves ) :
directions = [ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ]
enemy_color = ' b ' if self . red_to_move else ' r '
for direction in directions :
new_row = row + direction [ 0 ] * 1
new_col = col + direction [ 1 ] * 1
if 0 < = new_row < = 6 and 0 < = new_col < = 8 :
nxt_piece = self . board [ new_row ] [ new_col ]
if self . inHome ( new_row , new_col , self . color ( ) ) : continue
if nxt_piece == ' 00 ' :
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
elif nxt_piece [ 0 ] == enemy_color and self . Eliminate ( row , col , new_row , new_col ) and not self . inWater ( row , col ) :
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
return moves
def getEagMoves ( self , row , col , moves ) :
#可能存在一些问题,主要是移动方式的判断以及在陷阱的判断
enemy_color = ' b ' if self . red_to_move else ' r '
new_row = row
new_col = col
#U&D direction
while new_row > = 0 :
nxt_piece = self . board [ new_row ] [ col ]
if nxt_piece == ' 00 ' and not self . inTrap ( new_row , col , enemy_color ) and not self . inTrap ( new_row , col , ' r ' if enemy_color == ' b ' else ' b ' ) :
if not self . inHome ( new_row , col , self . color ( ) ) and not self . inWater ( new_row , col ) : moves . append ( Move ( ( row , col ) , ( new_row , col ) , self . board ) )
else :
if self . Eliminate ( row , col , new_row , col ) and not self . inWater ( new_row , col ) : moves . append ( Move ( ( row , col ) , ( new_row , col ) , self . board ) )
if new_row != row : break
new_row - = 1
new_row = row
while new_row < = 6 :
nxt_piece = self . board [ new_row ] [ col ]
if nxt_piece == ' 00 ' and not self . inTrap ( new_row , new_col , enemy_color ) and not self . inTrap ( new_row , col , ' r ' if enemy_color == ' b ' else ' b ' ) :
if not self . inHome ( new_row , col , self . color ( ) ) and not self . inWater ( new_row , col ) : moves . append ( Move ( ( row , col ) , ( new_row , col ) , self . board ) )
else :
if self . Eliminate ( row , col , new_row , col ) and not self . inWater ( new_row , col ) : moves . append ( Move ( ( row , col ) , ( new_row , col ) , self . board ) )
if new_row != row : break
new_row + = 1
#L&R Direction
while new_col > = 0 :
nxt_piece = self . board [ row ] [ new_col ]
if nxt_piece == ' 00 ' and not self . inTrap ( row , new_col , enemy_color ) and not self . inTrap ( new_row , col , ' r ' if enemy_color == ' b ' else ' b ' ) :
if not self . inHome ( row , new_col , self . color ( ) ) and not self . inWater ( row , new_col ) : moves . append ( Move ( ( row , col ) , ( row , new_col ) , self . board ) )
else :
if self . Eliminate ( row , col , row , new_col ) and not self . inWater ( row , new_col ) : moves . append ( Move ( ( row , col ) , ( row , new_col ) , self . board ) )
if new_col != col : break
new_col - = 1
new_col = col
while new_col < = 8 :
nxt_piece = self . board [ row ] [ new_col ]
if nxt_piece == ' 00 ' and not self . inTrap ( row , new_col , enemy_color ) and not self . inTrap ( new_row , col , ' r ' if enemy_color == ' b ' else ' b ' ) :
if not self . inHome ( row , new_col , self . color ( ) ) and not self . inWater ( row , new_col ) : moves . append ( Move ( ( row , col ) , ( row , new_col ) , self . board ) )
else :
if self . Eliminate ( row , col , row , new_col ) and not self . inWater ( row , new_col ) : moves . append ( Move ( ( row , col ) , ( row , new_col ) , self . board ) )
if new_col != col : break
new_col + = 1
return moves
def getFoxMoves ( self , row , col , moves ) :
directions = [ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) , ( 1 , 1 ) , ( 1 , - 1 ) , ( - 1 , 1 ) , ( - 1 , - 1 ) ]
enemy_color = ' b ' if self . red_to_move else ' r '
for direction in directions :
new_row = row + direction [ 0 ] * 1
new_col = col + direction [ 1 ] * 1
if 0 < = new_row < = 6 and 0 < = new_col < = 8 :
nxt_piece = self . board [ new_row ] [ new_col ]
if nxt_piece == ' 00 ' and not self . inWater ( new_row , new_col ) and not self . inHome ( new_row , new_col , self . color ( ) ) : #如果下一个位置是空的,则可以移动
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
elif nxt_piece [ 0 ] == enemy_color and not self . inWater ( new_row , new_col ) and not self . inHome ( new_row , new_col , self . color ( ) ) and self . Eliminate ( row , col , new_row , new_col ) : #如果是敌方棋子,且不在水里,且可以消除,则添加到可行路径中
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
return moves
def getLionMoves ( self , row , col , moves ) :
directions = [ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ]
enemy_color = ' b ' if self . red_to_move else ' r '
for direction in directions :
new_row = row + direction [ 0 ] * 1
new_col = col + direction [ 1 ] * 1
if 0 < = new_row < = 6 and 0 < = new_col < = 8 :
nxt_piece = self . board [ new_row ] [ new_col ]
if nxt_piece == ' 00 ' and not self . inWater ( new_row , new_col ) and not self . inHome ( new_row , new_col , self . color ( ) ) : #如果下一个位置是空的,则可以移动
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
elif nxt_piece [ 0 ] == enemy_color and not self . inWater ( new_row , new_col ) and not self . inHome ( new_row , new_col , self . color ( ) ) and self . Eliminate ( row , col , new_row , new_col ) : #如果是敌方棋子,且不在水里,且可以消除,则添加到可行路径中
moves . append ( Move ( ( row , col ) , ( new_row , new_col ) , self . board ) )
jump_vert_loc = [ ( 0 , 3 ) , ( 0 , 4 ) , ( 0 , 5 ) , ( 3 , 3 ) , ( 3 , 4 ) , ( 3 , 5 ) , ( 6 , 3 ) , ( 6 , 4 ) , ( 6 , 5 ) ]
jump_hori_loc = [ ( 1 , 2 ) , ( 1 , 6 ) , ( 2 , 2 ) , ( 2 , 6 ) , ( 4 , 2 ) , ( 4 , 6 ) , ( 5 , 2 ) , ( 5 , 6 ) ]
enemy_mouse = enemy_color + ' 1 '
if ( row , col ) in jump_vert_loc :
if row == 0 :
if self . board [ 1 ] [ col ] != enemy_mouse and self . board [ 2 ] [ col ] != enemy_mouse :
if self . Eliminate ( row , col , 3 , col ) : moves . append ( Move ( ( row , col ) , ( 3 , col ) , self . board ) )
elif row == 3 :
if self . board [ 1 ] [ col ] != enemy_mouse and self . board [ 2 ] [ col ] != enemy_mouse :
if self . Eliminate ( row , col , 0 , col ) : moves . append ( Move ( ( row , col ) , ( 0 , col ) , self . board ) )
if self . board [ 4 ] [ col ] != enemy_mouse and self . board [ 5 ] [ col ] != enemy_mouse :
if self . Eliminate ( row , col , 6 , col ) : moves . append ( Move ( ( row , col ) , ( 6 , col ) , self . board ) )
elif row == 6 :
if self . board [ 4 ] [ col ] != enemy_mouse and self . board [ 5 ] [ col ] != enemy_mouse :
if self . Eliminate ( row , col , 3 , col ) : moves . append ( Move ( ( row , col ) , ( 3 , col ) , self . board ) )
elif ( row , col ) in jump_hori_loc :
if col == 2 :
lea = True
for i in range ( 3 , 6 ) :
if self . board [ row ] [ i ] == enemy_mouse : lea = False
if lea and self . Eliminate ( row , col , row , 6 ) : moves . append ( Move ( ( row , col ) , ( row , 6 ) , self . board ) )
elif col == 6 :
lea = True
for i in range ( 3 , 6 ) :
if self . board [ row ] [ i ] == enemy_mouse : lea = False
if lea and self . Eliminate ( row , col , row , 2 ) : moves . append ( Move ( ( row , col ) , ( row , 2 ) , self . board ) )
return moves
# 判断是否胜利
def conquer ( self ) :
if self . board [ 3 ] [ 0 ] [ 0 ] == ' r ' or self . board [ 3 ] [ 8 ] [ 0 ] == ' b ' :
self . conquered = True
if self . board [ 3 ] [ 0 ] [ 0 ] == ' r ' :
self . win_person = ' r '
else : self . win_person = ' b '
elif len ( self . blue_pieces ) == 0 :
self . conquered = True
self . win_person = ' r '
elif len ( self . red_pieces ) == 0 :
self . conquered = True
self . win_person = ' b '
elif len ( self . getAllMoves ( ) ) == 0 :
self . conquered = True
self . win_person = ' r ' if self . color ( ) == ' b ' else ' b '
return self . conquered
#移动操作
def makeMove ( self , move ) : #cur是当前位置, nxt是下一个位置,参数传入为元组
# makeMove假设这个move一定是合法的
# 为什么添加toUpload? 防止使用makeMove更新己方棋盘时, 把敌方棋盘错误上传, 导致“棋子消失”。
if self . board [ move . end_row ] [ move . end_col ] != ' 00 ' :
nxt_piece = self . board [ move . end_row ] [ move . end_col ]
if nxt_piece [ 0 ] == ' r ' :
self . red_pieces . remove ( int ( nxt_piece [ 1 ] ) )
else :
self . blue_pieces . remove ( int ( nxt_piece [ 1 ] ) )
self . board [ move . end_row ] [ move . end_col ] = self . board [ move . start_row ] [ move . start_col ]
self . board [ move . start_row ] [ move . start_col ] = ' 00 '
self . red_to_move = not self . red_to_move
self . move_log . append ( move )
#由于使用多线程, 考虑让另一个线程去更新red_to_move
def undoMove ( self ) :
if len ( self . move_log ) != 0 :
move = self . move_log . pop ( )
self . board [ move . start_row ] [ move . start_col ] = move . cur_piece
self . board [ move . end_row ] [ move . end_col ] = move . nxt_piece
if move . nxt_piece != ' 00 ' and move . nxt_piece not in ( self . blue_pieces if move . nxt_piece [ 0 ] == ' b ' else self . red_pieces ) :
( self . blue_pieces if move . nxt_piece [ 0 ] == ' b ' else self . red_pieces ) . append ( int ( move . nxt_piece [ 1 ] ) )
self . red_to_move = not self . red_to_move