mirror of
				https://github.com/evgen-app/chess_rpg_backend.git
				synced 2025-11-04 09:47:29 +03:00 
			
		
		
		
	updated movement logic and validation
This commit is contained in:
		
							parent
							
								
									79a4d75730
								
							
						
					
					
						commit
						86c35b3d02
					
				| 
						 | 
					@ -129,7 +129,7 @@ class Deck(models.Model):
 | 
				
			||||||
        return self.get_heroes()
 | 
					        return self.get_heroes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def score(self):
 | 
					    def score(self):
 | 
				
			||||||
        return sum([x.attack + x.health + x.speed for x in self.get_heroes()])
 | 
					        return sum([x.hero.attack + x.hero.health + x.hero.speed for x in self.get_heroes()])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        db_table = "deck"
 | 
					        db_table = "deck"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,8 @@ import django
 | 
				
			||||||
from asgiref.sync import sync_to_async
 | 
					from asgiref.sync import sync_to_async
 | 
				
			||||||
from channels.generic.websocket import AsyncWebsocketConsumer
 | 
					from channels.generic.websocket import AsyncWebsocketConsumer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from room.services.game_logic import move_handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chess_backend.settings")
 | 
					os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chess_backend.settings")
 | 
				
			||||||
django.setup()
 | 
					django.setup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -286,9 +288,16 @@ class RoomConsumer(BaseConsumer):
 | 
				
			||||||
            await self.send_message("ERROR", message="data is not JSON serializable")
 | 
					            await self.send_message("ERROR", message="data is not JSON serializable")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if data:
 | 
					        if data:
 | 
				
			||||||
            if data["type"] == "start":
 | 
					            if "type" not in data:
 | 
				
			||||||
 | 
					                await self.send_message("ERROR", message="incorrect data typing")
 | 
				
			||||||
 | 
					            elif data["type"] == "start":
 | 
				
			||||||
                if not await self.start(data):
 | 
					                if not await self.start(data):
 | 
				
			||||||
                    await self.send_message("ERROR", message="opponent is offline")
 | 
					                    await self.send_message("ERROR", message="opponent is offline")
 | 
				
			||||||
 | 
					            elif data["type"] == "move":
 | 
				
			||||||
 | 
					                if all(x in data for x in ["x", "y", "px", "py"]):
 | 
				
			||||||
 | 
					                    await self.perform_move(data)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                await self.send_message("ERROR", message="incorrect data typing")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def start(self, data):
 | 
					    async def start(self, data):
 | 
				
			||||||
        if self.scope["opponent_channel"] and self.scope["opponent_online"]:
 | 
					        if self.scope["opponent_channel"] and self.scope["opponent_online"]:
 | 
				
			||||||
| 
						 | 
					@ -302,6 +311,22 @@ class RoomConsumer(BaseConsumer):
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def perform_move(self, data):
 | 
				
			||||||
 | 
					        await move_handler(data["px"], data["py"], data["x"], data["y"], self.room_name, self.scope["player_in_room"])
 | 
				
			||||||
 | 
					        if self.scope["opponent_channel"] and self.scope["opponent_online"]:
 | 
				
			||||||
 | 
					            await self.channel_layer.send(
 | 
				
			||||||
 | 
					                self.scope["opponent_channel"],
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "type": "move",
 | 
				
			||||||
 | 
					                    "x": data["x"],
 | 
				
			||||||
 | 
					                    "y": data["y"],
 | 
				
			||||||
 | 
					                    "px": data["px"],
 | 
				
			||||||
 | 
					                    "py": data["py"],
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # info type group message handler
 | 
					    # info type group message handler
 | 
				
			||||||
    async def info(self, event):
 | 
					    async def info(self, event):
 | 
				
			||||||
        message = event["message"]
 | 
					        message = event["message"]
 | 
				
			||||||
| 
						 | 
					@ -327,13 +352,6 @@ class RoomConsumer(BaseConsumer):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await self.send(text_data=json.dumps(msg))
 | 
					        await self.send(text_data=json.dumps(msg))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Receive message from room group
 | 
					 | 
				
			||||||
    async def chat_message(self, event):
 | 
					 | 
				
			||||||
        message = event["message"]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Send message to WebSocket
 | 
					 | 
				
			||||||
        await self.send(text_data=json.dumps({"lot": message}))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async def channel(self, event):
 | 
					    async def channel(self, event):
 | 
				
			||||||
        channel = event["channel"]
 | 
					        channel = event["channel"]
 | 
				
			||||||
        self.scope["opponent_channel"] = channel
 | 
					        self.scope["opponent_channel"] = channel
 | 
				
			||||||
| 
						 | 
					@ -352,6 +370,19 @@ class RoomConsumer(BaseConsumer):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        self.scope["opponent_online"] = status
 | 
					        self.scope["opponent_online"] = status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def move(self, event):
 | 
				
			||||||
 | 
					        await self.send(
 | 
				
			||||||
 | 
					            text_data=json.dumps(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "type": "MOVE",
 | 
				
			||||||
 | 
					                    "x": event["x"],
 | 
				
			||||||
 | 
					                    "y": event["y"],
 | 
				
			||||||
 | 
					                    "px": event["px"],
 | 
				
			||||||
 | 
					                    "py": event["py"]
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def check_origin(self):
 | 
					    async def check_origin(self):
 | 
				
			||||||
        if not self.scope["player"]:
 | 
					        if not self.scope["player"]:
 | 
				
			||||||
            await self.send(
 | 
					            await self.send(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +1,111 @@
 | 
				
			||||||
 | 
					from asgiref.sync import sync_to_async
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from room.models import HeroInGame, Room, PlayerInRoom
 | 
					from room.models import HeroInGame, Room, PlayerInRoom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _check_move_position(x: int, y: int, room: Room, p_first: bool):
 | 
					def _check_path(f_x: int, f_y: int, x: int, y: int, room: Room, move_type: str):
 | 
				
			||||||
    hero = HeroInGame.objects.filter(x=x, y=y, room=room)
 | 
					    if move_type == "DIAGONAL":
 | 
				
			||||||
    if not hero.exists():
 | 
					        return HeroInGame.objects.filter(room=room, x__range=(f_x, x), y__range=(f_y, y)).count() == 0
 | 
				
			||||||
 | 
					    elif move_type == "HORIZONTAL":
 | 
				
			||||||
 | 
					        return HeroInGame.objects.filter(room=room, x=x, y__range=(f_y, y)).count() == 0
 | 
				
			||||||
 | 
					    elif move_type == "VERTICAL":
 | 
				
			||||||
 | 
					        return HeroInGame.objects.filter(room=room, x__range=(f_x, x), y=y).count() == 0
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _validate_hero_movement(
 | 
				
			||||||
 | 
					        hero_type: str,
 | 
				
			||||||
 | 
					        prev_x: int,
 | 
				
			||||||
 | 
					        prev_y: int,
 | 
				
			||||||
 | 
					        x: int,
 | 
				
			||||||
 | 
					        y: int,
 | 
				
			||||||
 | 
					        room: Room,
 | 
				
			||||||
 | 
					        first: bool = False,  # needed for warrior
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    if hero_type == "KING":
 | 
				
			||||||
 | 
					        if abs(x - prev_x) > 1 or abs(y - prev_y) > 1:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					    elif hero_type == "WIZARD":
 | 
				
			||||||
 | 
					        if abs(x - prev_x) == abs(y - prev_y):
 | 
				
			||||||
 | 
					            return _check_path(prev_x, prev_y, x, y, room, "DIAGONAL")
 | 
				
			||||||
 | 
					        elif x == prev_x and y != prev_y:
 | 
				
			||||||
 | 
					            return _check_path(prev_x, prev_y, x, y, room, "HORIZONTAL")
 | 
				
			||||||
 | 
					        elif x != prev_x and y == prev_y:
 | 
				
			||||||
 | 
					            return _check_path(prev_x, prev_y, x, y, room, "VERTICAL")
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
    elif hero.first()
 | 
					    elif hero_type == "ARCHER":
 | 
				
			||||||
 | 
					        if abs(x - prev_x) == abs(y - prev_y):
 | 
				
			||||||
 | 
					            return _check_path(prev_x, prev_y, x, y, room, "DIAGONAL")
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					    elif hero_type == "WARRIOR":
 | 
				
			||||||
 | 
					        if first:
 | 
				
			||||||
 | 
					            if x == prev_x and y - prev_y == 1:
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					            elif abs(x - prev_x) == 1 and y - prev_y == 1:
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            if x == prev_x and prev_y - y == 1:
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def move_handler(prev_x: int, prev_y: int, x: int, y: int, room: Room, player: PlayerInRoom):
 | 
					def _print_board(room: Room):
 | 
				
			||||||
 | 
					    class color:
 | 
				
			||||||
 | 
					        PURPLE = '\033[95m'
 | 
				
			||||||
 | 
					        CYAN = '\033[96m'
 | 
				
			||||||
 | 
					        DARKCYAN = '\033[36m'
 | 
				
			||||||
 | 
					        BLUE = '\033[94m'
 | 
				
			||||||
 | 
					        GREEN = '\033[92m'
 | 
				
			||||||
 | 
					        YELLOW = '\033[93m'
 | 
				
			||||||
 | 
					        RED = '\033[91m'
 | 
				
			||||||
 | 
					        BOLD = '\033[1m'
 | 
				
			||||||
 | 
					        UNDERLINE = '\033[4m'
 | 
				
			||||||
 | 
					        END = '\033[0m'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for y in range(1, 8):
 | 
				
			||||||
 | 
					        for x in range(1, 9):
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                hero = HeroInGame.objects.get(x=x, y=y, room=room)
 | 
				
			||||||
 | 
					                if hero.hero.type == "KING":
 | 
				
			||||||
 | 
					                    if hero.player.first:
 | 
				
			||||||
 | 
					                        print("♔", end="")
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        print("♚", end="")
 | 
				
			||||||
 | 
					                elif hero.hero.type == "WIZARD":
 | 
				
			||||||
 | 
					                    if hero.player.first:
 | 
				
			||||||
 | 
					                        print("♕", end="")
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        print("♛", end="")
 | 
				
			||||||
 | 
					                elif hero.hero.type == "ARCHER":
 | 
				
			||||||
 | 
					                    if hero.player.first:
 | 
				
			||||||
 | 
					                        print("♗", end="")
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        print("♝", end="")
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    if hero.player.first:
 | 
				
			||||||
 | 
					                        print("♙", end="")
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        print("♟", end="")
 | 
				
			||||||
 | 
					            except HeroInGame.DoesNotExist:
 | 
				
			||||||
 | 
					                print("*", end="")
 | 
				
			||||||
 | 
					        print()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@sync_to_async
 | 
				
			||||||
 | 
					def move_handler(
 | 
				
			||||||
 | 
					        prev_x: int, prev_y: int, x: int, y: int, room_slug: str, player: PlayerInRoom
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    room = Room.objects.get(slug=room_slug)
 | 
				
			||||||
 | 
					    _print_board(room)  # TODO: Remove in production
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        hero = HeroInGame.objects.get(x=prev_x, y=prev_y, room=room, player=player)
 | 
					        hero = HeroInGame.objects.get(x=prev_x, y=prev_y, room=room, player=player)
 | 
				
			||||||
    except HeroInGame.DoesNotExist:
 | 
					    except HeroInGame.DoesNotExist:
 | 
				
			||||||
        return False
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    h_t = hero.hero.type
 | 
					    if x == prev_x and y == prev_y:
 | 
				
			||||||
    if h_t == "KING":
 | 
					        return False
 | 
				
			||||||
        if abs(prev_x - x) != 1 or abs(prev_y - y) != 1:
 | 
					
 | 
				
			||||||
            return False
 | 
					    h_t = hero.hero.type
 | 
				
			||||||
    elif h_t == "WARRIOR":
 | 
					
 | 
				
			||||||
        if player.first:
 | 
					    _print_board(room)  # TODO: Remove in production
 | 
				
			||||||
            if x - prev_x == 1 and y - prev_y == 0:
 | 
					 | 
				
			||||||
                _check_move_position(x, y, room, True)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,14 +37,24 @@ def create_room(
 | 
				
			||||||
        first=first_player == 2,
 | 
					        first=first_player == 2,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    for p, d_id in [(p1, deck_id_1), (p2, deck_id_2)]:
 | 
					    for p, d_id in [(p1, deck_id_1), (p2, deck_id_2)]:
 | 
				
			||||||
        GameState.objects.create(room=room, player=p, round=0, message="Game started")
 | 
					        GameState.objects.create(
 | 
				
			||||||
        for hero in Deck.objects.get(id=d_id).heroes.all():
 | 
					            room=room, player=p.player, round=0, message="Game started"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        for hero_in_deck in Deck.objects.get(id=d_id).heroes():
 | 
				
			||||||
            if p.first:
 | 
					            if p.first:
 | 
				
			||||||
                HeroInGame.objects.create(
 | 
					                HeroInGame.objects.create(
 | 
				
			||||||
                    hero=hero, player=p, room=room, x=hero.x, y=hero.y
 | 
					                    hero=hero_in_deck.hero,
 | 
				
			||||||
 | 
					                    player=p,
 | 
				
			||||||
 | 
					                    room=room,
 | 
				
			||||||
 | 
					                    x=hero_in_deck.x,
 | 
				
			||||||
 | 
					                    y=hero_in_deck.y,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                HeroInGame.objects.create(
 | 
					                HeroInGame.objects.create(
 | 
				
			||||||
                    hero=hero, player=p, room=room, x=hero.x, y=8 - hero.y
 | 
					                    hero=hero_in_deck.hero,
 | 
				
			||||||
 | 
					                    player=p,
 | 
				
			||||||
 | 
					                    room=room,
 | 
				
			||||||
 | 
					                    x=hero_in_deck.x,
 | 
				
			||||||
 | 
					                    y=8 - hero_in_deck.y,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
    return room.slug
 | 
					    return room.slug
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user