


class GameState:
    def __init__(self):
        '''
        有关信息：
        1. 棋盘尺寸为7*9（横向）
        2. 按照以下命名格式对棋盘中的棋子进行标注：
            (b|r)(1|2|3|4|5|6|7)
        3. 
        '''
        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.red_to_move=False
        self.conquered=False
        self.MASSACRE=False
        
        self.color = 'r' if self.red_to_move else 'b'
        
        
    # 判断特殊位置
    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):
        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):
        return self.board[nxt_row][nxt_col] == '00' or 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])
    
    # 定义移动方式    
    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<=8 and 0<=new_col<=6 :
                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((new_row,new_col))
                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((new_row,new_col))
        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[0]*1
            if 0<=new_row<=8 and 0<=new_col<=6 :
                nxt_piece = self.board[new_row][new_col]
                if nxt_piece == '00' and not self.inHome(new_row,new_col,self.color):
                    moves.append((new_row,new_col))
                elif nxt_piece[0]==enemy_color and self.Eliminate(row,col,new_row,new_col):
                    moves.append((new_row,new_col))
        return moves
    
    def getEagMoves(self,row,col,moves):
        #可能存在一些问题，主要是移动方式的判断以及在陷阱的判断
        enemy_color = 'b' if self.red_to_move else 'r'
        moveNum_row = -6
        moveNum_col = -8
        new_row = row
        new_col = col
        
        while(moveNum_row <= 6 ):
            new_row = row + moveNum_row          
            if 0<=new_row<=6:
                nxt_piece = self.board[new_row][col]
                if nxt_piece == '00':
                    moves.append((new_row,col))
                elif nxt_piece[0]==enemy_color and not self.inWater(new_row,col) and not self.inHome(row,new_col,self.color) and self.Eliminate(row,col,new_row,new_col):
                    moves.append((new_row,col))
                else :
                    break
            moveNum_row += 1
        
        while(moveNum_row <= 8):
            new_col = col + moveNum_col
            if 0 <= new_col <= 8:
                nxt_piece = self.board[row][new_col]
                if nxt_piece == '00' and not self.inWater(row,new_col) and not self.inHome(row,new_col,self.color):
                    moves.append((row,new_col))
                elif nxt_piece[0]==enemy_color and self.Eliminate(row,col,new_row,new_col):
                    moves.append((row,new_col))
                else :
                    break
            moveNum_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<=8 and 0<=new_col<=6 :
                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((new_row,new_col))
                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((new_row,new_col))
        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:
            for i in range(1, 2):
                end_row = row + direction[0] * 1
                end_col = col + direction[1] * 1
                if 0 <= end_row <= 8 and 0 <= end_col <= 6:  # check for possible moves only in boundaries of the board
                    end_piece = self.board[end_row][end_col]

                    if end_piece == "--" and not self.inWater(end_row,end_col) and self.moveNotOwnDen(end_row,end_col,enemy_color):  # empty space is valid and Not in Water
                        moves.append(Move((row, col), (end_row, end_col), self.board))

                    elif end_piece == "--" and self.inWater(end_row,end_col):
                        jump_row = end_row - row  #Vertical jump
                        jump_col = end_col - col  #Horizontal jump

                        if jump_row != 0 and self.jumpConditions(row,col,end_row,end_col,jump_row,jump_col,enemy_color):
                            moves.append(Move((row, col), (end_row+(3*jump_row), end_col), self.board))

                        elif jump_col != 0 and self.jumpConditions(row,col,end_row,end_col,jump_row,jump_col,enemy_color):
                            moves.append(Move((row, col), (end_row, end_col+(2*jump_col)), self.board))

                    elif end_piece[0] == enemy_color and not self.inWater(end_row,end_col) and self.canAttack(row, col, end_row, end_col):  # capture enemy piece
                        moves.append(Move((row, col), (end_row, end_col), self.board))
                        break
                    else:  # friendly piece
                        break
                else:  # off board
                    break
    
    # 判断是否胜利
    def conquer(self):
        if self.board[3][0][0] == 'r' or self.board[3][8][0] == 'b':
            self.conquered = True
        return self.conquered
    