mirror of
				https://github.com/evgen-app/chess_rpg_backend.git
				synced 2025-11-04 01:37:30 +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()
 | 
			
		||||
 | 
			
		||||
    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:
 | 
			
		||||
        db_table = "deck"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,8 @@ import django
 | 
			
		|||
from asgiref.sync import sync_to_async
 | 
			
		||||
from channels.generic.websocket import AsyncWebsocketConsumer
 | 
			
		||||
 | 
			
		||||
from room.services.game_logic import move_handler
 | 
			
		||||
 | 
			
		||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chess_backend.settings")
 | 
			
		||||
django.setup()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -286,9 +288,16 @@ class RoomConsumer(BaseConsumer):
 | 
			
		|||
            await self.send_message("ERROR", message="data is not JSON serializable")
 | 
			
		||||
 | 
			
		||||
        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):
 | 
			
		||||
                    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):
 | 
			
		||||
        if self.scope["opponent_channel"] and self.scope["opponent_online"]:
 | 
			
		||||
| 
						 | 
				
			
			@ -302,6 +311,22 @@ class RoomConsumer(BaseConsumer):
 | 
			
		|||
            return True
 | 
			
		||||
        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
 | 
			
		||||
    async def info(self, event):
 | 
			
		||||
        message = event["message"]
 | 
			
		||||
| 
						 | 
				
			
			@ -327,13 +352,6 @@ class RoomConsumer(BaseConsumer):
 | 
			
		|||
 | 
			
		||||
        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):
 | 
			
		||||
        channel = event["channel"]
 | 
			
		||||
        self.scope["opponent_channel"] = channel
 | 
			
		||||
| 
						 | 
				
			
			@ -352,6 +370,19 @@ class RoomConsumer(BaseConsumer):
 | 
			
		|||
        )
 | 
			
		||||
        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):
 | 
			
		||||
        if not self.scope["player"]:
 | 
			
		||||
            await self.send(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,25 +1,111 @@
 | 
			
		|||
from asgiref.sync import sync_to_async
 | 
			
		||||
 | 
			
		||||
from room.models import HeroInGame, Room, PlayerInRoom
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _check_move_position(x: int, y: int, room: Room, p_first: bool):
 | 
			
		||||
    hero = HeroInGame.objects.filter(x=x, y=y, room=room)
 | 
			
		||||
    if not hero.exists():
 | 
			
		||||
def _check_path(f_x: int, f_y: int, x: int, y: int, room: Room, move_type: str):
 | 
			
		||||
    if move_type == "DIAGONAL":
 | 
			
		||||
        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
 | 
			
		||||
    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:
 | 
			
		||||
        hero = HeroInGame.objects.get(x=prev_x, y=prev_y, room=room, player=player)
 | 
			
		||||
    except HeroInGame.DoesNotExist:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    h_t = hero.hero.type
 | 
			
		||||
    if h_t == "KING":
 | 
			
		||||
        if abs(prev_x - x) != 1 or abs(prev_y - y) != 1:
 | 
			
		||||
            return False
 | 
			
		||||
    elif h_t == "WARRIOR":
 | 
			
		||||
        if player.first:
 | 
			
		||||
            if x - prev_x == 1 and y - prev_y == 0:
 | 
			
		||||
                _check_move_position(x, y, room, True)
 | 
			
		||||
    if x == prev_x and y == prev_y:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    h_t = hero.hero.type
 | 
			
		||||
 | 
			
		||||
    _print_board(room)  # TODO: Remove in production
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,14 +37,24 @@ def create_room(
 | 
			
		|||
        first=first_player == 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")
 | 
			
		||||
        for hero in Deck.objects.get(id=d_id).heroes.all():
 | 
			
		||||
        GameState.objects.create(
 | 
			
		||||
            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:
 | 
			
		||||
                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:
 | 
			
		||||
                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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user