Search
None
is
if (not obstacle is None) …
player.py
from obstacle import *
MyGreatObstacle
make_move
opponent_move
numpy
scipy
matplotlib
stat
statistics
pyclbr
Kdy nelze umístit překážku:
Kdy lze překážku umístit:
class Obstacle: """ Simple class to represent one part of each obstacle. The obstacle is defined by coordinates of cells between which the player cannot move """ def __init__(self,fromx, fromy, tox, toy): self.fromx = fromx self.fromy = fromy self.tox = tox self.toy = toy def __str__(self): return "(" + str(self.fromx) + "," + str(self.fromy) + ")->(" + str(self.tox) + "," + str(self.toy) + ")" def can_player_move(self, fromx, fromy, tox, toy): """ return True, if a player can move from [fromx,fromy] to [tox,toy]. This only checks if THIS obstacle prevents the move or not. """ if (self.fromx == fromx and self.fromy == fromy and self.tox == tox and self.toy == toy) or \ (self.fromx == tox and self.fromy == toy and self.tox == fromx and self.toy == fromy): return False return True def is_valid_obstacle(self, sizex, sizey): """ return True, if the given obstacle is valid (is inside the board). Size of the board is sizex, sizey """ return (self.fromx >= 0 and self.fromx < sizex and \ self.fromy >= 0 and self.fromy < sizey and \ self.tox >= 0 and self.tox < sizex and \ self.toy >=0 and self.toy < sizey) def __eq__(self, other): return type(self) == type(other) and self.fromx == other.fromx and self.fromy == other.fromy and self.tox == other.tox and self.toy == other.toy;
Příklad vytvoření validní překážky z obrázku:
#horizontalni p1 = Obstacle(5,0, 5,1) p2 = Obstacle(6,0, 6,1) #vertikalni p3 = Obstacle(3,5, 4,5) p4 = Obstacle(3,6, 4,6)
Takové překážky bude vracet metoda Player.makeMove a Player.expandObstacles jako pole, tedy:
#.. somewhere in player.expandObstacles() pa = Obstacle(3,5, 4,5) pb = Obstacle(3,6, 4,6) myObstacles = [] myObstacles.append(pa) myObstacles.append(pb) return myObstacles
initialization
all_player_moves
all_obstacles
class Player: def __init__(self, name): self.name = name; #student's name, will be filled by BRUTE self.version = "version 3" #student' debug info, e.g. version, name of algorithm.. self.myx = -1 #my position self.myy = -1 self.opponentx = -1 #position of the oponent self.opponenty = -1 self.sizex = -1 #size of the board. Will be filled using initialization self.sizey = -1 self.obstacles = [] #I have no self.max_obstacles = -1 self.my_goal_row = -1 #index of row, where is my goal zone self.my_obstacles = 0 def initialization(self, sizex, sizey, myx, myy, opponentx, opponenty, max_obstacles, list_of_obstacles): """ This method is called by the game Manager to tell the player where it is, where is the oponent, where are obstacles and how many obstacle the player can use. sizex, sizey - dimensions of the board startx, starty - my initial position at the board ostartx, ostarty - initial position of the oponent max_obstacles - how many obstacles I can use list_of_obstacles - array of initial obstacles (objects Obstacles). """ self.sizex = sizex self.sizey = sizey self.myx = myx self.myy = myy self.opponentx = opponentx self.opponenty = opponenty self.max_obstacles = max_obstacles self.obstacles = list_of_obstacles self.my_obstacles = 0 #number of my obstacles if (self.myy == 0): self.my_goal_row = sizey -1 else: self.my_goal_row = 0 def is_in_board(self, x,y): """ return True if position (x,y) is in the board TODO: implement in class """ return True def can_player_move(self, x,y): """ return True, if this player can move from (self.myx, self.myx) to the cell (x, y) TODO: implement in class """ return True #this is called by the manager. this function should return either new position of this paper (0, (x,y)) or #position of new obstacles (1, x1,y1,x2,y2); def make_move(self): """ this function is called by the game Manager to get the move of this player. The move is either new position of the player or newly placed obstacle. Return always TWO variables: the first is integer, the second is LIST if value is 1: the list is [x, y] - new position of the player if value is 2: the list is [o1, o2] - list of two Obstacles - this means that the player placed new obstacle if value is None: the list is ignored - this means that player cannot move TODO: implement by yourself #the following code is just example to show how to return new postion, new obstacle or None. #example of returning a position, try first go to down, then left, then right, then up #return 1, [self.myx, self.myy]; #move up toward the goal zone o1 = Obstacle(x1,y1, x2, y2); o2 = Obstacle(xx1,yy1, xx2, yy2); if (o1.is_valid_obstacle(self.sizex, self.sizey) and o2.is_valid_obstacle(self.sizex, self.sizey)): self.obstacles.append(o1) self.obstacles.append(o2) self.my_obstacles+=1 return 2, [ o1, o2 ] """ return None def opponent_move(self, moveType, result): """ this is called by the Manager to pass result of oponent's move. moveType and result has the same meaning as in the self.move method """ if (moveType == 1): #the other player moved itself, let's update its position self.opponentx = result[0] self.opponenty = result[1] elif (moveType == 2): #the other player placed a new obstacle. if (len(result) == 2): self.obstacles.append(result[0]) self.obstacles.append(result[1]) else: #this shouldn't happen, it will be checked by the manager print("Error, oponent returned wrong move!!") else: print("Oponent return None") def expand_player(self): """ returns LIST of [x,y] positions where this player can move. It can be empty. TODO: implement by yourself """ my_moves = [] return my_moves def expand_obstacles(self): """ return LIST of [o1,o2] of all possible pairs of obstacles. can be empty if the player cannot place any obstacle anymore TODO: implement by yourself """ my_obstacles = [] return my_obstacles
Příklad práce s hráčem (doporučujeme začínat takto):
p = Player("pepa") p.initialization(10,10, 0,0 9,9, 5, []); #board 10x10, first player at (0,0), second at (9,9), max 5 obstacles, empty list of obstacles my_moves = p.expand_player() #or my_obstacles = p.expand_obstacles()
from obstacle import * class Manager: """ Example of game Manager. This class is responsible to call methods of both players. This is simple version of the manager (e.g., we do not control validiy of obstacles returned by players etc..). """ def __init__(self, p1, p2, sizex, sizey): """ p1,p2 are objects of class Player sizex,sizey is dimension of the board """ self.p1 = p1 self.p2 = p2 self.sizex = sizex self.sizey = sizey def init(self): """ Example of game initialization. We create positions of both players (x1,y1) and (x2,y2) and call initialization on each player. """ self.x1 = self.sizex//2; self.y1 = 0; self.x2 = self.sizex//2; self.y2 = self.sizey -1; #create an initial obstacle. As each obstacle has to have length 2, we have to create TWO objects obstacles = [] obstacles.append( Obstacle(2,self.sizex//2,2,self.sizey//2 + 1) ) #horizontal obstacle at column 1 obstacles.append( Obstacle(3,self.sizex//2,3,self.sizey//2 + 1) ) #horizontal obstacle at column 2 self.p1.initialization(self.sizex, self.sizey, self.x1, self.y1, self.x2, self.y2, 4, obstacles) self.p2.initialization(self.sizex, self.sizey, self.x2, self.y2, self.x1, self.y1, 4, obstacles) def check_result(self, player, moveType, result): """ return True, of result of player.move is valid """ if (moveType == 1 and len(result) == 2): if (player == 1): self.x1,self.y1 = result[0], result[1] else: self.x2,self.y2 = result[0], result[1] return True; if (moveType == 2 and len(result) == 2 and type(result[0]) == Obstacle and type(result[1]) == Obstacle): obstacles.append(result[0]) obstacles.append(result[1]) return True; if (moveType == None): return True; print("Upps, player1 returned invalid output from move()"); quit() def is_winner(self): """ return true if one of player is at goal zone """ return self.y1 == self.sizey-1 or self.y2 == 0 def game(self): """ Example how the game will be handled during the tournament. The player p1 will always start first. The game is organized this way: 1. tell p1 where is p2 (p1.oppositeMove()) 2. ask p1 to move (i.e., to move itself or place new obstacles) 3. tell p2 what move p1 did 4. ask p2 to move """ moveType2 = 1; result2 = [ self.x2, self.y2 ] cnt = 0; while(True): self.p1.opponent_move( moveType2, result2 ) moveType1, result1 = self.p1.make_move() print("p1 returned: ", moveType1, result1[0], result1[1]); self.check_result(1, moveType1, result1) if (self.is_winner()): print("P1 wins"); return self.p2.opponent_move(moveType1, result1) moveType2, result2 = self.p2.make_move() print("p2 returned: ", moveType2, result2[0], result2[1]); self.check_result(2, moveType2, result2) if (self.is_winner()): print("p2 wins!"); return; print("p1=(",self.x1, self.y1,"), p2=(",self.x2,self.y2,")") print("end of the game");
from manager import * from player import * p1 = Player("pepa") p2 = Player("franta") m = Manager(p1,p2, 15, 15); m.init() m.game()
from manger import impor randomPlayer as RP import player as P p1 = P.Player("pepa") p2 = RP.Player("franta") #zbytek je stejný jako výše.
.
Výchozí stav:
Vytvoření hry. Hráči v 0. sloupci. Jedna dvou-buňková překážka na začátku
p = Player("pepa") o1 = Obstacle(0,1, 0,2) #horizontal obstacle (black in the following images) o1 = Obstacle(1,1, 1,2) p.initialization(4,4, 0,0 0,3, 5, [o1, o2]); ob = p.expand_obstacles() #in this case, the list 'ob' should have 11 items. The order of the returned obstacles does not matter
Validní tahy:
Situaci vlevo-nahoře odpovídá tento fragment kódu:
def expand_player(self): my_moves = [] o1 = Obstacle(0,0, 0,1) o1 = Obstacle(1,0, 1,1) my_moves.append( [ o1, o2 ] ); ... code for other obstacles ... return my_moves
Příklad předání 2 překážek.
#vertical obstacle o1 = Obstacle(0,0, 1, 0; o2 = Obstacle(0,1, 1, 1; #horizontal one o3 = Obstacle(1,1,1,2); o4 = Obstacle(2,1,2,2); player.initialization(5,5, 0,0, 4,4, [ o1, o2, o3, o4 ] );
expand_player()
expand_obstacles()
expand_player
expand_obstacles