Gerakan Langkah Bidak Catur_Nine Dengan 2 Pilihan Formasi Bidak (2 Kuda, 1 Garuda Atau 2 Garuda, 1 Kuda) Pada Papan 9x9 Petak

GERAKAN LANGKAH BIDAK CATUR_NINE DENGAN 2 PILIHAN FORMASI BIDAK (2 KUDA, 1 GARUDA Atau 2 GARUDA, 1 KUDA) PADA PAPAN 9x9 PETAK

(Oleh: SR.Pakpahan,SST)


Kita lanjutkan game catur_nine 9x9 petak ini dengan implementasi pergerakan bidak atau penambahan fitur lain, fokus kita pada  bagian utama yaitu menjalankan permainan (game loop). Selain itu, juga menambahkan mekanisme interaksi, seperti pergerakan bidak, aturan permainan, atau validasi langkah, maka ada banyak hal yang perlu dikembangkan lebih lanjut untuk perbaikan atau penyempurnaan yang bisa kita dilakukan, yaitu:

  1. Optimasi Timer:

    • Gunakan metode pygame.time.set_timer() untuk mengatur interval pengurangan waktu.
    • Tambahkan fungsi agar waktu berhenti saat permainan selesai.
  2. Interaksi Pemain:

    • Tambahkan mekanisme klik untuk memilih dan memindahkan bidak.
    • Buat fungsi untuk validasi langkah bidak sesuai aturan catur Nine 9x9.
  3. AI atau Multiplayer (Opsional):

    • Jika ingin bermain melawan AI, bisa menambahkan algoritma minimax atau rule-based AI.
    • Jika ingin multiplayer online, bisa menggunakan pygame.networking atau socket programming.
  4. Simpan dan Muat Permainan (Opsional):

    • Tambahkan fitur untuk menyimpan dan melanjutkan permainan.
    • Gunakan format JSON atau SQLite untuk menyimpan status permainan.

Perbaikan dan Pengembangan Kode

1. Perbaikan Timer pada Permainan
Untuk mengoptimalkan timer permainan pada kode catur Anda, berikut beberapa perbaikan yang bisa dilakukan:
  • Gunakan pygame.time.get_ticks()
Alih-alih mengandalkan perhitungan manual, gunakan pygame.time.get_ticks() untuk mendapatkan waktu dalam milidetik sejak permainan dimulai.
  • Kurangi Pembaruan Berlebihan
Pastikan timer hanya diperbarui jika ada perubahan signifikan, bukan setiap frame.
  • Optimalkan Loop Timer
Gunakan interval pembaruan yang efisien, misalnya dengan pygame.time.delay(100).

Dari kode sebelumnya, ada beberapa masalah yang mungkin menyebabkan timer tidak berjalan dengan baik:

  1. Timer berjalan terus tanpa memperhitungkan giliran pemain.
  2. switch_turn() tidak memperbarui current_player secara global.
  3. update_timer() tetap berjalan setiap frame, bahkan ketika pemain belum bergerak.

Solusi

  1. Gunakan pygame.time.get_ticks() untuk menghitung waktu dengan lebih akurat.
  2. Pastikan timer hanya berkurang saat giliran pemain yang bersangkutan.
  3. Modifikasi switch_turn() agar memperbarui last_time.

Perbaikan Kode:

# === WAKTU PERMAINAN ===
WHITE_TIME = 3600  # 60 menit dalam detik
BLACK_TIME = 3600
current_player = "white"
last_time = pygame.time.get_ticks()  # Gunakan get_ticks()

def update_timer():
    """Mengupdate timer berdasarkan giliran pemain"""
    global WHITE_TIME, BLACK_TIME, last_time

    current_time = pygame.time.get_ticks()
    elapsed_time = (current_time - last_time) // 1000  # Konversi ms ke detik

    if elapsed_time > 0:
        if current_player == "white":
            WHITE_TIME -= elapsed_time
            if WHITE_TIME <= 0:
                print("Waktu Habis! Hitam Menang!")
                pygame.quit()
                sys.exit()
        else:
            BLACK_TIME -= elapsed_time
            if BLACK_TIME <= 0:
                print("Waktu Habis! Putih Menang!")
                pygame.quit()
                sys.exit()

        last_time = current_time  # Perbarui last_time setelah mengurangi waktu

def switch_turn():
    """Beralih giliran pemain"""
    global current_player, last_time
    current_player = "black" if current_player == "white" else "white"
    last_time = pygame.time.get_ticks()  # Reset last_time saat pergantian giliran

Perubahan yang Dilakukan:

✅ Menggunakan pygame.time.get_ticks() untuk memastikan timer tetap akurat.

Pada kode sebelumnya:

# === WAKTU PERMAINAN ===

WHITE_TIME = 3600  # 60 menit dalam detik

BLACK_TIME = 3600

current_player = "white"

last_time = time.time()

Gantikan dengan kode yang ini:

# === WAKTU PERMAINAN ===

WHITE_TIME = 3600  # 60 menit dalam detik

BLACK_TIME = 3600

current_player = "white"

last_time = pygame.time.get_ticks()  # Gunakan get_ticks()

✅ Fungsi update_timer(). Timer hanya berjalan saat giliran pemain berlangsung.

Pada kode sebelumnya:

def update_timer():

    """Mengupdate timer berdasarkan giliran pemain"""

    global WHITE_TIME, BLACK_TIME, last_time


    current_time = time.time()

    elapsed_time = current_time - last_time

    last_time = current_time


    if current_player == "white":

        WHITE_TIME -= int(elapsed_time)

        if WHITE_TIME <= 0:

            print("Waktu Habis! Hitam Menang!")

            pygame.quit()

            sys.exit()

    else:

        BLACK_TIME -= int(elapsed_time)

        if BLACK_TIME <= 0:

            print("Waktu Habis! Putih Menang!")

            pygame.quit()

            sys.exit()

Gantikan dengan kode yang ini:

def update_timer():

    """Mengupdate timer berdasarkan giliran pemain"""

    global WHITE_TIME, BLACK_TIME, last_time


    current_time = pygame.time.get_ticks()

    elapsed_time = (current_time - last_time) // 1000  # Konversi ms ke detik


    if elapsed_time > 0:

        if current_player == "white":

            WHITE_TIME -= elapsed_time

            if WHITE_TIME <= 0:

                print("Waktu Habis! Hitam Menang!")

                pygame.quit()

                sys.exit()

        else:

            BLACK_TIME -= elapsed_time

            if BLACK_TIME <= 0:

                print("Waktu Habis! Putih Menang!")

                pygame.quit()

                sys.exit()


        last_time = current_time  # Perbarui last_time setelah mengurangi waktu

switch_turn() memperbarui last_time agar timer tidak langsung berkurang drastis.

Pada kode sebelumnya:

# === FUNGSI GILIRAN ===

def switch_turn():

    """Mengubah giliran pemain"""

    global current_player

    if current_player == "white":

        current_player = "black"

    else:

        current_player = "white"

Gantikan dengan kode yang ini:

def switch_turn():

    """Beralih giliran pemain"""

    global current_player, last_time

    current_player = "black" if current_player == "white" else "white"

    last_time = pygame.time.get_ticks()  # Reset last_time saat pergantian giliran

Dengan perubahan ini, timer seharusnya berjalan optimal dan tidak berkurang saat giliran belum berpindah.

Namun, masih terlihat bahwa kode ini belum memiliki bagian utama untuk menjalankan permainan (game loop). Selain itu, juga perlu menambahkan mekanisme interaksi, seperti pergerakan bidak, aturan permainan, atau validasi langkah, maka masih ada banyak hal yang perlu dikembangkan lebih lanjut, seperti:

- Implementasi pergerakan bidak:

 Tambahkan mekanisme klik untuk memilih dan memindahkan bidak. 

Buat fungsi untuk validasi langkah bidak sesuai aturan catur Nine 9x9.

- AI atau Multiplayer (Opsional):

Jika ingin bermain melawan AI, bisa menambahkan algoritma minimax atau rule-based AI.

- Jika ingin multiplayer online, bisa menggunakan pygame.networking atau socket programming.

- Simpan dan Muat Permainan (Opsional):

Tambahkan fitur untuk menyimpan dan melanjutkan permainan.

Gunakan format JSON atau SQLite untuk menyimpan status permainan.


2a. Aturan Gerakan Langkah Bidak Pada Permainan Catur_Nine 9x9 Petak

Dalam Catur Nine 9x9, gerakan bidak umumnya mengikuti aturan dasar catur standar tetapi dapat mengalami penyesuaian karena papan yang lebih besar dan tambahan bidak Garuda. Berikut adalah gerakan untuk masing-masing bidak:

1. Bidak Standar

Pion (Pawn)

  • Langkah awal: Bisa maju 1 atau 2 petak ke depan.
  • Langkah biasa: Maju 1 petak ke depan.
  • Menyerang: Secara diagonal 1 petak ke depan kiri/kanan.
  • Promosi: Jika mencapai baris terakhir lawan, bisa berubah menjadi Menteri (Queen), Benteng (Rook), Kuda (Knight), Gajah (Bishop), atau Garuda (jika aturan memungkinkan).

Benteng (Rook)

  • Dapat bergerak sejauh mungkin secara horizontal atau vertikal, selama tidak terhalang bidak lain.
  • Dapat digunakan dalam rokade dengan raja.

Kuda (Knight)

  • Bergerak dalam pola L (2 petak satu arah, lalu 1 petak ke samping).
  • Dapat melompati bidak lain.

Gajah (Bishop)

  • Bergerak diagonal sejauh mungkin.
  • Tidak bisa melompati bidak lain.

Menteri (Queen)

  • Bisa bergerak horizontal, vertikal, dan diagonal sejauh mungkin.
  • Tidak bisa melompati bidak lain.

Raja (King)

  • Bergerak 1 petak ke segala arah.
  • Bisa melakukan rokade jika belum pernah bergerak dan benteng juga belum bergerak.

2. Bidak Khusus: Garuda

Garuda adalah bidak tambahan dalam Catur Nine. Gerakannya dapat berbeda tergantung aturan yang diterapkan, tetapi beberapa kemungkinan gerakannya adalah:

  • Kombinasi Kuda dan Benteng: Bisa bergerak seperti Kuda (L-shape) atau Benteng (lurus vertikal & horizontal).
  • Kombinasi Kuda dan Gajah: Bisa bergerak seperti Kuda (L-shape) atau Gajah (diagonal sejauh mungkin).
  • Melompati bidak lain seperti Kuda jika dalam mode hybrid.

Aturan Tambahan Untuk Pion dan Garuda

Aturan tambahan (spesifik) yang diterapkan untuk Pion jalur e dan untuk Garuda  memberikan variasi strategis dalam Catur Nine 9x9. Berikut adalah penjelasan lebih lanjut tentang bagaimana aturan ini memengaruhi permainan:


1. Aturan Pion dengan Petak F2P (Forboden For Pawn) di e5

  • Pion memiliki gerakan standar seperti dalam catur 8x8:

    • Langkah awal: 1 atau 2 petak ke depan.
    • Langkah biasa: 1 petak ke depan.
    • Menyerang: Diagonal 1 petak ke kiri/kanan depan.
    • Promosi: Jika mencapai baris terakhir lawan.
  • Batasan di petak e5:

    • Pion di lajur e tidak dapat melewati petak e5. Jika sudah mencapai e5, pion ini tidak bisa maju lagi.
    • Pion dari lajur d atau f dapat menyerang (memakan) buah catur lawan yang berada di petak e5 atau sepanjang kolom e.
    • Jika pion d/f menangkap bidak lawan di e5, pion tersebut sekarang berpindah ke jalur e dan bergerak di lajur e menuju promosi.

πŸ’‘ Implikasi Strategis

  • Lajur e menjadi jalur konflik utama karena pion dari lajur d/f dapat berpindah ke jalur e setelah menangkap bidak lawan di sana.
  • Pemain harus memanfaatkan pion d/f untuk menyerang ke e5 agar mendapatkan kontrol jalur e.

2. Aturan Gerakan Perwira Garuda

  • Garuda bergerak lurus 2 petak ke segala arah (vertikal & horizontal).
  • Bisa melompati bidak lain saat bergerak.
  • Contoh langkah:
    • Dari g1 ke g3
    • Dari g3 ke g5, atau ke i3, atau ke e3, atau kembali ke g1

πŸ’‘ Implikasi Strategis

  • Mobilitas tinggi: Garuda bisa melompati bidak, menjadikannya ancaman cepat.
  • Bisa menghindari hambatan pion atau perwira lain lebih mudah dibandingkan dengan benteng atau gajah.
  • Posisi awal dan jalur pergerakan Garuda perlu direncanakan dengan baik agar tidak terjebak.

3. Promosi Garuda Jika Menangkap Pion di Jalur e

  • Jika Garuda menangkap pion lawan yang bergerak di sepanjang lajur/kolom e, maka Garuda langsung mendapat promosi.
  • Garuda bisa dipromosikan menjadi:
    • Ratu (Queen)
    • Benteng (Rook)
    • Gajah (Bishop)
    • Promosi khusus lainnya sesuai aturan tambahan

πŸ’‘ Implikasi Strategis

  • Garuda dapat menjadi bidak yang lebih kuat jika berhasil menangkap pion lawan di jalur e.
  • Pemain dapat mendorong lawan untuk menggerakkan pion di jalur e sebagai umpan, lalu menangkapnya dengan Garuda untuk mendapatkan promosi.
  • Lajur e menjadi pusat strategi, baik untuk pion maupun Garuda.

Kesimpulan & Strategi dalam Catur Nine

  1. Jalur e adalah jalur kritis karena pion tidak bisa melewatinya kecuali menangkap di sana. Ini menciptakan peluang jebakan & strategi baru.
  2. Garuda menjadi bidak unik dengan kekuatan lompat 2 petak dan bisa mendapat promosi jika menangkap pion lawan di jalur e.
  3. Pemain harus merencanakan posisi pion & Garuda secara strategis, karena aturan tambahan ini membuat pion dan Garuda lebih penting daripada catur biasa.


2bImplementasi Aturan Lengkap Game Catur_Nine pada Kode Python

Berikut aturan lengkap langkah setiap bidak dalam permainan catur, termasuk bidak Garuda, yang merupakan variasi dalam beberapa aturan catur khusus:


1. PION (Pawn)

  • Langkah:
    • Melangkah ke depan satu petak.
    • Jika masih di baris awalnya, bisa melangkah dua petak ke depan.
  • Makan Bidak Lawan:
    • Makan secara diagonal satu petak ke depan.
  • Promosi Pion:
    • Jika mencapai baris terakhir, dapat dipromosikan menjadi Ratu, Benteng, Gajah, atau Kuda.
  • En Passant:
    • Jika lawan memindahkan pion dua petak ke depan dan berada di samping pion kita, kita bisa menangkapnya secara diagonal pada langkah berikutnya.

2. KUDA (Knight)

  • Langkah:
    • Melangkah dalam pola “L”: dua petak ke satu arah lalu satu petak ke samping, atau sebaliknya (1+2 atau 2+1).
  • Melewati Bidak Lain:
    • Kuda dapat melompati bidak lain, satu-satunya bidak yang memiliki kemampuan ini.

3. GAJAH (Bishop)

  • Langkah:
    • Bergerak diagonal sejauh yang diinginkan tanpa melewati bidak lain.
  • Bidak Tetap pada Warna Asalnya:
    • Jika awalnya di petak hitam, ia akan selalu berada di petak hitam, dan sebaliknya.

4. BENTENG (Rook)

  • Langkah:
    • Bergerak lurus ke depan, belakang, kiri, atau kanan sejauh yang diinginkan tanpa melewati bidak lain.
  • Kombinasi dengan Raja (Rokade):
    • Bisa melakukan rokade dengan Raja jika belum pernah bergerak sebelumnya dan tidak ada bidak di antara mereka.

5. RATU (Queen)

  • Langkah:
    • Kombinasi Bishop dan Rook, dapat bergerak lurus atau diagonal sejauh yang diinginkan tanpa melewati bidak lain.

6. RAJA (King)

  • Langkah:
    • Bergerak satu petak ke segala arah.
  • Rokade:
    • Jika belum pernah bergerak dan Benteng di baris yang sama juga belum bergerak, serta tidak ada bidak di antara mereka, Raja bisa berpindah dua petak ke arah Benteng, dan Benteng melompat ke sisi lain Raja.
  • Skakmat:
    • Raja tidak boleh melangkah ke petak yang terkena serangan lawan. Jika tidak ada langkah tersisa yang sah, permainan berakhir dalam skakmat.

7. GARUDA (Bidak Variasi)

Bidak Garuda adalah bidak tambahan yang digunakan dalam beberapa varian catur (misalnya, dalam catur Nusantara). Aturannya bisa berbeda tergantung variasi yang digunakan, tetapi biasanya memiliki karakteristik sebagai berikut:

  • Langkah Umum:
    • Bisa melompat seperti kuda (L-shape).
    • Bisa melangkah lurus satu petak seperti raja.
    • Bisa melangkah diagonal satu petak seperti ratu.
  • Kemampuan Khusus:
    • Bisa menyerang seperti ratu, tetapi hanya dalam satu langkah.
    • Dalam beberapa aturan, Garuda dapat melompati satu bidak dan mendarat di petak di belakangnya.

Itulah aturan lengkap pergerakan semua bidak dalam permainan catur, termasuk variasi Garuda. Jika ada aturan khusus yang ingin diterapkan, bisa disesuaikan dengan versi catur yang digunakan!

Awalnya adalah kode isi file __main__.py:


import pygame


import sys


import os


import time


import catur_nine_move


# === KONFIGURASI PYGAME ===


pygame.init()


# Ukuran layar


SCREEN_WIDTH, SCREEN_HEIGHT = 900, 700


screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))


pygame.display.set_caption("Chess Nine with Timer")


# Ukuran papan catur


BOARD_SIZE = 635


TILE_SIZE = BOARD_SIZE // 9


BOARD_X = (SCREEN_WIDTH - BOARD_SIZE) // 2 - 90


BOARD_Y = (SCREEN_HEIGHT - BOARD_SIZE) // 2 - (-170)


# Warna


WHITE = (255, 255, 255)


BLACK = (0, 0, 0)


LIGHT_BROWN = (240, 217, 181)


DARK_BROWN = (181, 136, 99)


RED = (200, 50, 50)


GREEN = (50, 200, 50)


# Font


font = pygame.font.Font(None, 40)


# Direktori gambar bidak


IMAGE_DIR = "/storage/emulated/0/AppJadi/Catur/Catur_9x9/images"


# === MEMUAT GAMBAR BIDAK ===


pieces_images = {}


def load_pieces():


    """Memuat gambar bidak dari direktori"""


    piece_names = ["pawn", "rook", "knight", "bishop", "queen", "king", "garuda"]


    colors = ["white", "black"]


    for color in colors:


        for piece in piece_names:


            path = os.path.join(IMAGE_DIR, f"{color}_{piece}.png")


            if os.path.exists(path):


                img = pygame.image.load(path)


                img = pygame.transform.scale(img, (TILE_SIZE, TILE_SIZE))


                pieces_images[f"{color}_{piece}"] = img

               

# === FORMASI AWAL BIDAK PUTIH ===


formasi_1_white = {  # 2 Kuda, 1 Garuda (Menambahkan gajah di c1)


    "white_knight": [(7, 8), (1, 8)],


    "white_garuda": [(6, 8)],


    "white_bishop": [(2, 8), (5, 8)]  # Gajah putih di c1 dan f1


}


formasi_2_white = {  # 2 Garuda, 1 Kuda (Menambahkan gajah di c1 dan h1)


    "white_knight": [(5, 8)],


    "white_garuda": [(1, 8), (6, 8)],


    "white_bishop": [(2, 8), (7, 8)]  # Gajah putih di c1 dan h1


}


# === FORMASI AWAL BIDAK HITAM === (Disesuaikan dengan formasi putih)


formasi_1_black = {  # 2 Kuda, 1 Garuda (Menambahkan gajah di c9)


    "black_knight": [(7, 0), (1, 0)],


    "black_garuda": [(6, 0)],


    "black_bishop": [(2, 0), (5, 0)]  # Gajah hitam di c9 dan f9


}


formasi_2_black = {  # 2 Garuda, 1 Kuda (Menambahkan gajah di c9 dan h9)


    "black_knight": [(5, 0)],


    "black_garuda": [(1, 0), (6, 0)],


    "black_bishop": [(2, 0), (7, 0)]  # Gajah hitam di c9 dan h9


}


# === POSISI DEFAULT (TIDAK BERUBAH) ===


default_position = {


    "white_rook": [(0, 8), (8, 8)],


    "white_queen": [(3, 8)],


    "white_king": [(4, 8)],


    "white_pawn": [(i, 7) for i in range(9)],


    "black_rook": [(0, 0), (8, 0)],


    "black_queen": [(3, 0)],


    "black_king": [(4, 0)],


    "black_pawn": [(i, 1) for i in range(9)],


}


# === WAKTU PERMAINAN ===


WHITE_TIME = 3600  # 60 menit dalam detik


BLACK_TIME = 3600


current_player = "white"


last_time = pygame.time.get_ticks()  # Gunakan get_ticks()                

                                              

def draw_timer():


    """Menampilkan timer di layar dengan kotak pembungkus"""


    white_timer_text = font.render(f"{WHITE_TIME // 60}:{WHITE_TIME % 60:02d}", True, BLACK)


    black_timer_text = font.render(f"{BLACK_TIME // 60}:{BLACK_TIME % 60:02d}", True, BLACK)


    # Ukuran kotak pembungkus


    box_width, box_height = 140, 50


    # Posisi kotak untuk white_timer


    white_box_x = BOARD_X + BOARD_SIZE - 100


    white_box_y = BOARD_Y + BOARD_SIZE - box_height + 60


    # Posisi kotak untuk black_timer


    black_box_x = BOARD_X + BOARD_SIZE - 100


    black_box_y = BOARD_Y - 60


    # Gambar kotak untuk white_timer


    pygame.draw.rect(screen, LIGHT_BROWN, (white_box_x, white_box_y, box_width, box_height), border_radius=10)


    pygame.draw.rect(screen, BLACK, (white_box_x, white_box_y, box_width, box_height), 2, border_radius=10)


    screen.blit(white_timer_text, (white_box_x + 40, white_box_y + 10))


    # Gambar kotak untuk black_timer


    pygame.draw.rect(screen, LIGHT_BROWN, (black_box_x, black_box_y, box_width, box_height), border_radius=10)


    pygame.draw.rect(screen, BLACK, (black_box_x, black_box_y, box_width, box_height), 2, border_radius=10)


    screen.blit(black_timer_text, (black_box_x + 40, black_box_y + 10))


def update_timer():


    """Mengupdate timer berdasarkan giliran pemain"""


    global WHITE_TIME, BLACK_TIME, last_time


    current_time = pygame.time.get_ticks()


    elapsed_time = (current_time - last_time) // 1000  # Konversi ms ke detik


    if elapsed_time > 0:


        if current_player == "white":


            WHITE_TIME -= elapsed_time


            if WHITE_TIME <= 0:


                print("Waktu Habis! Hitam Menang!")


                pygame.quit()


                sys.exit()


        else:


            BLACK_TIME -= elapsed_time


            if BLACK_TIME <= 0:


                print("Waktu Habis! Putih Menang!")


                pygame.quit()


                sys.exit()


        last_time = current_time  # Perbarui last_time setelah mengurangi waktu


# === FUNGSI GAMBAR PAPAN DAN BIDAK ===


def draw_board():


    for row in range(9):


        for col in range(9):


             # Petak e5 (indeks array: 4,4) diwarnai putih


            if row == 4 and col == 4:


                color = WHITE


            else:


                # Warna petak papan catur normal                      

                color = DARK_BROWN if (row + col) % 2 == 0 else LIGHT_BROWN


                pygame.draw.rect(screen, color, 


                             (BOARD_X + col * TILE_SIZE, BOARD_Y + row * TILE_SIZE, TILE_SIZE, TILE_SIZE))


def draw_pieces(starting_position):


    """Menggambar semua bidak di posisi awal"""


    for piece, positions in starting_position.items():


        if piece in pieces_images:


            for pos in positions:


                x, y = pos


                screen.blit(pieces_images[piece], 


                            (BOARD_X + x * TILE_SIZE, BOARD_Y + y * TILE_SIZE))

                                                

# === FUNGSI GILIRAN ===


def switch_turn():


    """Beralih giliran pemain"""


    global current_player, last_time


    current_player = "black" if current_player == "white" else "white"


    last_time = pygame.time.get_ticks()  # Reset last_time saat pergantian giliran       


# === FUNGSI TOMBOL FORMASI ===


def draw_button(text, x, y, width, height, color):


    pygame.draw.rect(screen, color, (x, y, width, height), border_radius=5)


    button_text = font.render(text, True, WHITE)


    screen.blit(button_text, (x + 10, y + 10))


    return pygame.Rect(x, y, width, height)


def choose_white_formation():


    """Menampilkan tombol pilihan formasi untuk bidak putih sebelum permainan dimulai dengan latar papan catur."""


    selected_formation = None


    while selected_formation is None:


        screen.fill(WHITE)  # Membersihkan layar sebelum menggambar ulang

        

        # **Gambar papan catur 9x9 sebagai latar belakang**


        draw_board()

        

        label_text = font.render("GAME CATUR_NINE 9x9 PETAK", True, BLACK)


        screen.blit(label_text, (SCREEN_WIDTH // 2 - 300,  SCREEN_HEIGHT // 3 - 220))


        # **Tambahkan label pemilihan formasi**


        title_text = font.render("Pilih Formasi Bidak Putih:", True, BLACK)


        screen.blit(title_text, (SCREEN_WIDTH // 2 - 270,  SCREEN_HEIGHT // 3  + 605))


        # **Gambar tombol pilihan formasi**


        btn_1 = draw_button("2 Kuda, 1 Garuda", SCREEN_WIDTH // 2 - 230, SCREEN_HEIGHT // 3+638, 280, 50, RED)


        btn_2 = draw_button("2 Garuda, 1 Kuda", SCREEN_WIDTH // 2 - 230, SCREEN_HEIGHT // 3 + 700, 280, 50, GREEN)


        # **Perbarui tampilan**


        pygame.display.flip()


        # **Tangani event klik tombol**


        for event in pygame.event.get():


            if event.type == pygame.QUIT:


                pygame.quit()


                sys.exit()


            elif event.type == pygame.MOUSEBUTTONDOWN:


                mouse_pos = pygame.mouse.get_pos()


                if btn_1.collidepoint(mouse_pos):


                    selected_formation = formasi_1_white


                elif btn_2.collidepoint(mouse_pos):


                    selected_formation = formasi_2_white


    return selected_formation


def choose_black_formation():


    """Menampilkan tombol pilihan formasi untuk bidak hitam sebelum permainan dimulai."""


    selected_formation = None


    while selected_formation is None:


        screen.fill(WHITE)     


        # **Gambar papan catur 9x9 sebagai latar belakang**


        draw_board()      

       

        label_text = font.render("GAME CATUR_NINE 9x9 PETAK", True, BLACK)


        screen.blit(label_text, (SCREEN_WIDTH // 2 - 300,  SCREEN_HEIGHT // 3 - 220))    


        ltitle_text = font.render("Pilih Formasi Bidak Hitam:", True, BLACK)


        screen.blit(ltitle_text, (SCREEN_WIDTH // 2 - 270, SCREEN_HEIGHT // 10 - 20))


        btn_1 = draw_button("2 Kuda, 1 Garuda", SCREEN_WIDTH // 2 - 230, SCREEN_HEIGHT // 12 + 28, 280, 50, RED)


        btn_2 = draw_button("2 Garuda, 1 Kuda", SCREEN_WIDTH // 2 - 230, SCREEN_HEIGHT // 13 + 95, 280, 50, GREEN)


        pygame.display.flip()


        for event in pygame.event.get():


            if event.type == pygame.QUIT:


                pygame.quit()


                sys.exit()


            elif event.type == pygame.MOUSEBUTTONDOWN:


                mouse_pos = pygame.mouse.get_pos()


                if btn_1.collidepoint(mouse_pos):


                    selected_formation = formasi_1_black


                elif btn_2.collidepoint(mouse_pos):


                    selected_formation = formasi_2_black


    return selected_formation


def choose_formation():


    """Menampilkan tombol pilihan formasi sebelum permainan dimulai."""


    selected_formation = None


    while selected_formation is None:


        screen.fill(WHITE)

       

        label_text = font.render("GAME CATUR_NINE 9x9 PETAK", True, BLACK)


        screen.blit(label_text, (SCREEN_WIDTH // 2 - 300, SCREEN_HEIGHT // 5 - 50))

       

        title_text = font.render("Pilih Formasi Bidak:", True, BLACK)


        screen.blit(title_text, (SCREEN_WIDTH // 2 - 135, SCREEN_HEIGHT // 3 - 50))


        btn_1 = draw_button("2 Kuda, 1 Garuda", SCREEN_WIDTH // 2 - 140, SCREEN_HEIGHT // 3, 280, 50, RED)


        btn_2 = draw_button("2 Garuda, 1 Kuda", SCREEN_WIDTH // 2 - 140, SCREEN_HEIGHT // 3 + 70, 280, 50, GREEN)


        pygame.display.flip()


        for event in pygame.event.get():


            if event.type == pygame.QUIT:


                pygame.quit()


                sys.exit()


            elif event.type == pygame.MOUSEBUTTONDOWN:


                mouse_pos = pygame.mouse.get_pos()


                if btn_1.collidepoint(mouse_pos):


                    selected_formation = (formasi_1_white, formasi_1_black)


                elif btn_2.collidepoint(mouse_pos):


                    selected_formation = (formasi_2_white, formasi_2_black)


    return selected_formation


# === MULAI GAME ===


clock = pygame.time.Clock()


# Muat gambar bidak


load_pieces()


# Pemain memilih formasi awal


chosen_white = choose_white_formation()


chosen_black = choose_black_formation()


# Gabungkan posisi default dengan formasi yang dipilih


starting_position = {**default_position, **chosen_white, **chosen_black}


running = True


while running:


    screen.fill(WHITE)


    # Update timer sebelum menggambar papan


    update_timer()


    draw_board()


    draw_pieces(starting_position)


    draw_timer()


    for event in pygame.event.get():


        if event.type == pygame.QUIT:


            running = False


        elif event.type == pygame.MOUSEBUTTONDOWN:


            switch_turn()  # Simulasi pergantian giliran jika ada klik mouse


    pygame.display.flip()


    clock.tick(30)


pygame.quit()

sys.exit()


Selanjutnya membuat kode isi file: catur_nine_move.py yang mengatur fungsi gerakan langkah sah dari setiap bidak catur_nine, agar supaya ketika kode dieksekusi dari __main__.py maka catur_nine bisa dimainkan dengan benar dan tanpa error.

Implementasi Gerakan Bidak

Untuk mengimplementasikan gerakan bidak (logika pergerakan bidak) dalam permainan Catur Nine 9x9, kita perlu:

  1. Menyimpan status papan (posisi semua bidak).
  2. Menangani klik pemain untuk memilih dan memindahkan bidak.
  3. Mengecek apakah langkah valid berdasarkan aturan gerakan tiap bidak.
  4. Memperbarui tampilan setelah bidak bergerak.
  5. Menjalankan Loop Utama

Langkah 1: Menyimpan Status Papan

Buat dictionary board_state untuk menyimpan posisi setiap bidak:

# Status awal papan (gabungan default_position dan formasi pilihan)
board_state = {}

def initialize_board():
    """Mengisi papan dengan posisi awal bidak"""
    global board_state
    board_state = default_position.copy()  # Mulai dengan posisi default
    
    # Tambahkan formasi yang dipilih
    white_formation = choose_white_formation()
    black_formation = choose_black_formation()

    for piece, positions in white_formation.items():
        board_state[piece] = positions

    for piece, positions in black_formation.items():
        board_state[piece] = positions

Kode ini lebih cocok dimasukkan ke dalam file catur_nine_move.py, karena berfungsi untuk:

✅ Mengelola status papan (posisi bidak)
✅ Menginisialisasi papan dengan formasi default dan formasi pilihan

File catur_nine_move.py berisi logika permainan, seperti:

  • Gerakan bidak
  • Validasi langkah
  • Perubahan status papan

Sementara itu, file __main__.py biasanya digunakan untuk:

  • Menjalankan permainan (game loop)
  • Menampilkan UI/Tampilan papan dengan Pygame
  • Memanggil fungsi dari catur_nine_move.py untuk menangani gerakan

Jadi, dalam __main__.py, Anda cukup memanggil initialize_board() saat memulai game:

from catur_nine_move import initialize_board

initialize_board()

Sehingga, kode logika permainan tetap terpisah dari kode tampilan dan eksekusi utama.

Langkah 2: Menangani Klik Pemain

Pemain akan klik bidak untuk memilihnya, lalu klik petak tujuan untuk memindahkannya.

Tambahkan variabel untuk menyimpan bidak yang sedang dipilih:

selected_piece = None
selected_position = None

Kode ini lebih cocok ditempatkan di catur_nine_move.py, karena variabel ini digunakan untuk menyimpan bidak yang dipilih dan posisinya, yang berkaitan dengan logika permainan.

File catur_nine_move.py menangani:
✅ Pemilihan bidak
✅ Validasi gerakan
✅ Eksekusi perpindahan

Namun, jika file __main__.py menangani interaksi pengguna (misalnya dengan Pygame), ada kemungkinan variabel ini perlu dideklarasikan di __main__.py.

Misalnya, jika selected_piece dan selected_position digunakan untuk menyimpan input dari pemain saat mengklik papan catur, maka lebih cocok di __main__.py.

Solusi Terbaik:

  • Jika digunakan untuk logika gerakancatur_nine_move.py
  • Jika digunakan untuk menyimpan input pengguna dari UI__main__.py
  • Jika diperlukan di kedua file, gunakan global state atau objek game untuk menyimpannya secara terpusat.

Selanjutnya Tambahkan fungsi untuk menangani klik pengguna:

def handle_click(position):
    """Menangani klik pemain untuk memilih dan memindahkan bidak"""
    global selected_piece, selected_position, current_player
    
    col = (position[0] - BOARD_X) // TILE_SIZE
    row = (position[1] - BOARD_Y) // TILE_SIZE
    
    if 0 <= col < 9 and 0 <= row < 9:
        clicked_piece = None
        clicked_position = (col, row)

        # Cek apakah ada bidak di petak yang diklik
        for piece, positions in board_state.items():
            if clicked_position in positions:
                clicked_piece = piece
                break

        if selected_piece is None:
            # Pemain memilih bidak miliknya
            if clicked_piece and clicked_piece.startswith(current_player):
                selected_piece = clicked_piece
                selected_position = clicked_position
        else:
            # Pemain mencoba memindahkan bidak yang telah dipilih
            if is_valid_move(selected_piece, selected_position, clicked_position):
                move_piece(selected_piece, selected_position, clicked_position)
                switch_turn()  # Ganti giliran
            selected_piece = None  # Reset pilihan bidak

Kode ini lebih cocok ditempatkan di __main__.py, karena fungsi handle_click(position) menangani input pemain saat mengklik papan catur.

Alasan:

__main__.py biasanya menangani event input dari pengguna, seperti klik mouse.
✅ Fungsi ini bergantung pada koordinat tampilan (position[0] - BOARD_X), yang berarti berhubungan dengan UI atau rendering.
Fungsi ini tidak menentukan aturan gerakan (itu tugas catur_nine_move.py), tetapi hanya menangani pemilihan dan eksekusi gerakan berdasarkan klik pemain.

Struktur yang Disarankan:

  • Di __main__.py
    • handle_click(position) → Menangani klik pemain
    • Menghubungkan input dengan logika permainan
  • Di catur_nine_move.py
    • is_valid_move(piece, start, end) → Mengecek apakah langkah sah
    • move_piece(piece, start, end) → Menggerakkan bidak di board_state
    • Aturan pergerakan dan validasi bidak

Jadi, kode ini lebih cocok berada di __main__.py karena fungsinya menangani event klik dari pemain. 

Langkah 3: Validasi Gerakan Bidak

Tambahkan fungsi is_valid_move() untuk mengecek apakah langkah valid.

def is_valid_move(piece, start_pos, end_pos):
    """Memeriksa apakah gerakan bidak sesuai aturan"""
    x1, y1 = start_pos
    x2, y2 = end_pos

    # Pastikan tujuan tidak ditempati bidak sendiri
    for p, positions in board_state.items():
        if end_pos in positions and p.startswith(current_player):
            return False

    # Aturan gerakan tiap bidak
    if "pawn" in piece:  # Pion
        direction = -1 if "white" in piece else 1
        if x1 == x2 and (y2 - y1) == direction:  # Maju 1 langkah
            return True
        elif abs(x2 - x1) == 1 and (y2 - y1) == direction:  # Makan bidak
            return end_pos in [pos for p, pos_list in board_state.items() if p.startswith(opponent())]
    
    elif "rook" in piece:  # Benteng
        return (x1 == x2 or y1 == y2) and is_path_clear(start_pos, end_pos)

    elif "knight" in piece:  # Kuda (L-shape)
        return (abs(x2 - x1), abs(y2 - y1)) in [(1, 2), (2, 1)]

    elif "bishop" in piece:  # Gajah
        return abs(x2 - x1) == abs(y2 - y1) and is_path_clear(start_pos, end_pos)

    elif "queen" in piece:  # Ratu (Gabungan Benteng + Gajah)
        return (x1 == x2 or y1 == y2 or abs(x2 - x1) == abs(y2 - y1)) and is_path_clear(start_pos, end_pos)

    elif "king" in piece:  # Raja
        return max(abs(x2 - x1), abs(y2 - y1)) == 1

    elif "garuda" in piece:  # Garuda (Gerakan khusus)
        return (abs(x2 - x1) <= 2 and abs(y2 - y1) <= 2)  # Bisa maju 2 langkah di segala arah

    return False

Kode ini lebih cocok berada di catur_nine_move.py.

Alasan:

✅ Fungsi is_valid_move() menangani logika gerakan bidak berdasarkan aturan permainan.
catur_nine_move.py adalah tempat yang tepat untuk menyimpan aturan pergerakan bidak, agar terpisah dari event handling di __main__.py.
__main__.py lebih fokus menangani interaksi pengguna, sementara aturan catur dan validasi gerakan lebih cocok dipisahkan ke dalam catur_nine_move.py.

Struktur yang Disarankan:

  • Di __main__.py
    • handle_click(position) → Menangani input klik dari pemain
    • Memanggil is_valid_move() saat pemain mencoba bergerak
  • Di catur_nine_move.py
    • is_valid_move(piece, start_pos, end_pos) → Mengecek apakah langkah bidak sah
    • move_piece(piece, start_pos, end_pos) → Memindahkan bidak jika langkah valid
    • Fungsi-fungsi tambahan seperti is_path_clear()

Jadi, kode ini lebih baik ditempatkan di catur_nine_move.py karena berisi aturan validasi gerakan bidak.

Selanjutnya, Fungsi is_path_clear() untuk memastikan tidak ada bidak yang menghalangi:

def is_path_clear(start, end):
    """Memeriksa apakah jalur antara dua titik bersih dari bidak lain"""
    x1, y1 = start
    x2, y2 = end

    if x1 == x2:  # Vertikal
        step = 1 if y2 > y1 else -1
        for y in range(y1 + step, y2, step):
            if (x1, y) in [pos for positions in board_state.values() for pos in positions]:
                return False

    elif y1 == y2:  # Horizontal
        step = 1 if x2 > x1 else -1
        for x in range(x1 + step, x2, step):
            if (x, y1) in [pos for positions in board_state.values() for pos in positions]:
                return False

    elif abs(x2 - x1) == abs(y2 - y1):  # Diagonal
        step_x = 1 if x2 > x1 else -1
        step_y = 1 if y2 > y1 else -1
        for i in range(1, abs(x2 - x1)):
            if (x1 + i * step_x, y1 + i * step_y) in [pos for positions in board_state.values() for pos in positions]:
                return False

    return True

Kode ini lebih cocok berada di catur_nine_move.py.

Alasan:

Fungsi is_path_clear() bertugas untuk mengecek apakah jalur gerakan bidak tidak terhalang oleh bidak lain.
✅ Fungsi ini terkait dengan aturan pergerakan bidak, bukan interaksi pengguna, sehingga lebih cocok ditempatkan di catur_nine_move.py.
✅ Fungsi ini dipanggil di dalam is_valid_move(), yang juga berada di catur_nine_move.py.

Struktur yang Disarankan:

  • Di __main__.py
    • Menangani input klik pemain (handle_click()).
    • Memanggil is_valid_move() untuk mengecek apakah gerakan sah.
  • Di catur_nine_move.py
    • is_valid_move(piece, start_pos, end_pos) → Memeriksa validitas gerakan.
    • is_path_clear(start, end) → Memeriksa apakah jalur gerakan bersih.
    • move_piece(piece, start_pos, end_pos) → Memindahkan bidak jika gerakan valid.

Jadi, kode ini lebih baik ditempatkan di catur_nine_move.py, karena merupakan bagian dari logika aturan pergerakan bidak. 

Langkah 4: Memindahkan Bidak

Jika langkah valid, pindahkan bidak ke petak tujuan dan hapus bidak lawan jika ada:

def move_piece(piece, start_pos, end_pos):
    """Memindahkan bidak ke posisi baru"""
    board_state[piece].remove(start_pos)
    board_state[piece].append(end_pos)

    # Hapus bidak lawan jika ada
    for p, positions in board_state.items():
        if p.startswith(opponent()) and end_pos in positions:
            positions.remove(end_pos)
            break

Kode ini lebih cocok berada di catur_nine_move.py.

Alasan:

Fungsi move_piece() menangani pemindahan bidak, yang merupakan bagian dari aturan permainan, bukan interaksi pengguna.
Fungsi ini berhubungan langsung dengan is_valid_move(), yang sebelumnya juga ditempatkan di catur_nine_move.py.
Bagian utama __main__.py biasanya menangani input dan tampilan (seperti menangani klik), sedangkan catur_nine_move.py menangani aturan permainan dan logika pemindahan bidak.

Struktur yang Disarankan:

  • Di __main__.py
    • Fungsi handle_click(position) → Menangani klik pemain dan memanggil is_valid_move().
  • Di catur_nine_move.py
    • Fungsi is_valid_move(piece, start_pos, end_pos) → Mengecek apakah gerakan valid.
    • Fungsi is_path_clear(start, end) → Mengecek jalur gerakan.
    • Fungsi move_piece(piece, start_pos, end_pos) → Memindahkan bidak jika gerakan valid.

Jadi, kode ini lebih baik ditempatkan di catur_nine_move.py, karena berfungsi sebagai bagian dari aturan permainan untuk menggerakkan bidak.

Selanjutnya, tambahkan fungsi untuk menentukan giliran lawan:

def opponent():
    return "white" if current_player == "black" else "black"

Kode ini lebih cocok berada di catur_nine_move.py.

Alasan:

Fungsi ini bersifat logis dan digunakan dalam aturan permainan, bukan dalam interaksi langsung dengan pengguna.
Fungsi ini diperlukan dalam is_valid_move() dan move_piece(), yang sebelumnya juga ditempatkan di catur_nine_move.py.
__main__.py lebih berfokus pada event handling dan UI, sedangkan aturan permainan lebih cocok ditempatkan di catur_nine_move.py.

Struktur yang Disarankan:

  • Di __main__.py
    • Menangani input pemain dan memanggil fungsi yang ada di catur_nine_move.py.
  • Di catur_nine_move.py
    • opponent()
    • is_valid_move()
    • move_piece()
    • is_path_clear()

Jadi, kode ini lebih baik ditempatkan di catur_nine_move.py, karena berkaitan dengan logika permainan.

Langkah 5: Menjalankan Game Loop

Tambahkan dalam loop utama Pygame untuk menangani klik pemain:

running = True
initialize_board()
load_pieces()

while running:
    screen.fill(WHITE)
    draw_board()
    draw_pieces(board_state)
    draw_timer()
    
    pygame.display.flip()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            handle_click(event.pos)

pygame.quit()
sys.exit()

Kode ini lebih cocok berada di __main__.py.

Alasan:

Kode ini berisi loop utama (game loop), yang bertanggung jawab atas tampilan dan event handling, seperti klik pemain dan perintah keluar dari permainan.
Fungsi pygame.event.get() digunakan untuk menangani input pemain, yang biasanya ditempatkan di __main__.py karena mengontrol jalannya program.
Fungsi draw_board(), draw_pieces(), dan draw_timer() berhubungan dengan rendering tampilan, yang lebih cocok di __main__.py daripada catur_nine_move.py.

Struktur yang Disarankan:

  • Di __main__.py
    • Game loop (seperti kode ini)
    • Menangani input pemain (handle_click() dipanggil di sini)
    • Mengontrol tampilan dengan pygame
  • Di catur_nine_move.py
    • Aturan permainan (is_valid_move(), move_piece(), dll.)
    • Logika pemrosesan gerakan bidak

Jadi, kode ini lebih baik ditempatkan di __main__.py, karena bertanggung jawab untuk menjalankan loop utama dan menampilkan permainan.

Kesimpulan

Dengan implementasi ini, game Chess Nine 9x9 dapat:
✅ Menyimpan status papan
✅ Memilih bidak dengan klik
✅ Validasi gerakan bidak
✅ Memindahkan bidak & menghapus lawan
✅ Berganti giliran otomatis

Silakan dicoba, 


Langkah Valid Setiap Gerakan Bidak

Berikut adalah kode Python dalam file catur_nine_move.py, yang mengimplementasikan aturan langkah semua bidak dalam Catur Nine, termasuk Pion, Kuda, Gajah, Benteng, Ratu, Raja, dan Garuda.

Kode ini mendefinisikan kelas untuk setiap bidak, dengan metode untuk menghitung langkah-langkah yang sah.


Kode: catur_nine_move.py

class Bidak:
    def __init__(self, warna):
        self.warna = warna  # "Putih" atau "Hitam"

    def langkah_sah(self, posisi_awal):
        """Metode ini akan diimplementasikan oleh setiap bidak secara khusus."""
        pass


class Pion(Bidak):
    def langkah_sah(self, posisi_awal):
        baris, kolom = posisi_awal
        langkah = []

        # Pion Putih naik, Pion Hitam turun
        arah = 1 if self.warna == "Putih" else -1  

        # Langkah normal
        langkah.append((baris + arah, kolom))

        # Langkah awal dua petak
        if (self.warna == "Putih" and baris == 1) or (self.warna == "Hitam" and baris == 6):
            langkah.append((baris + 2 * arah, kolom))

        # Langkah makan secara diagonal
        langkah.append((baris + arah, kolom - 1))
        langkah.append((baris + arah, kolom + 1))

        return langkah


class Kuda(Bidak):
    def langkah_sah(self, posisi_awal):
        baris, kolom = posisi_awal
        langkah = [
            (baris + 2, kolom + 1), (baris + 2, kolom - 1),
            (baris - 2, kolom + 1), (baris - 2, kolom - 1),
            (baris + 1, kolom + 2), (baris + 1, kolom - 2),
            (baris - 1, kolom + 2), (baris - 1, kolom - 2)
        ]
        return langkah


class Gajah(Bidak):
    def langkah_sah(self, posisi_awal):
        baris, kolom = posisi_awal
        langkah = []

        for i in range(1, 8):
            langkah.extend([(baris + i, kolom + i), (baris + i, kolom - i),
                            (baris - i, kolom + i), (baris - i, kolom - i)])

        return langkah


class Benteng(Bidak):
    def langkah_sah(self, posisi_awal):
        baris, kolom = posisi_awal
        langkah = []

        for i in range(1, 8):
            langkah.extend([(baris + i, kolom), (baris - i, kolom),
                            (baris, kolom + i), (baris, kolom - i)])

        return langkah


class Ratu(Bidak):
    def langkah_sah(self, posisi_awal):
        langkah_gajah = Gajah(self.warna).langkah_sah(posisi_awal)
        langkah_benteng = Benteng(self.warna).langkah_sah(posisi_awal)
        return langkah_gajah + langkah_benteng


class Raja(Bidak):
    def langkah_sah(self, posisi_awal):
        baris, kolom = posisi_awal
        langkah = [
            (baris + 1, kolom), (baris - 1, kolom),
            (baris, kolom + 1), (baris, kolom - 1),
            (baris + 1, kolom + 1), (baris + 1, kolom - 1),
            (baris - 1, kolom + 1), (baris - 1, kolom - 1)
        ]
        return langkah


class Garuda(Bidak):
    def langkah_sah(self, posisi_awal):
        baris, kolom = posisi_awal
        langkah_kuda = Kuda(self.warna).langkah_sah(posisi_awal)
        langkah_raja = Raja(self.warna).langkah_sah(posisi_awal)
        return langkah_kuda + langkah_raja


# Contoh penggunaan
if __name__ == "__main__":
    pion_putih = Pion("Putih")
    kuda_hitam = Kuda("Hitam")
    garuda_putih = Garuda("Putih")

    print("Langkah Pion Putih dari (1, 3):", pion_putih.langkah_sah((1, 3)))
    print("Langkah Kuda Hitam dari (4, 4):", kuda_hitam.langkah_sah((4, 4)))
    print("Langkah Garuda Putih dari (5, 5):", garuda_putih.langkah_sah((5, 5)))

Penjelasan Kode:

  1. Setiap bidak dibuat sebagai kelas dengan metode langkah_sah(), yang mengembalikan daftar koordinat langkah yang diizinkan.
  2. Implementasi langkah sesuai aturan:
    • Pion: Langkah lurus ke depan, dua langkah saat pertama kali, makan secara diagonal.
    • Kuda: Melangkah dalam pola "L".
    • Gajah: Melangkah diagonal sejauh mungkin.
    • Benteng: Bergerak vertikal atau horizontal sejauh mungkin.
    • Ratu: Gabungan dari Gajah dan Benteng.
    • Raja: Bergerak satu petak ke segala arah.
    • Garuda: Gabungan langkah Kuda dan Raja.
  3. Kode contoh pemanggilan di bagian if __name__ == "__main__":, yang mencetak langkah sah dari beberapa bidak.

Kode ini dapat digunakan dalam permainan Catur Nine, memungkinkan pengembangan lebih lanjut seperti validasi langkah dan implementasi GUI dengan tkinter atau pygame.


Aturan Promosi Perwira (Garuda/Kuda) yang Memakan Pion di Lajur e:

Aturan tambahan berupa Promosi Perwira Tunggal Terkecil pada catur_nine, bahwa bila pemain memilih formasi 2 Garuda, 1 Kuda, maka perwira yang dapat promosi adalah Kuda (bukan garuda) bila saja Kuda dapat memakan pion lawan yang bergerak di sepanjang lajur e maka Kuda ini akan mendapat promosi bertukar menjadi ratu/benteng atau promosi lainnya yang ditentukan. Sedangkan bila pemain memilih formasi 2 Kuda 1 Garuda pada catur_nine, maka perwira yang dapat promosi adalah Garuda (bukan kuda) bila saja Garuda dapat memakan pion lawan yang bergerak di sepanjang lajur e maka Garuda ini akan mendapat promosi bertukar menjadi ratu/benteng atau promosi lainnya yang ditentukan

Berikut implementasi aturan tambahan pada Chess Nine sesuai dengan ketentuan Promosi Perwira (Garuda/Kuda) ini:

  1. Jika pemain memilih formasi "2 Garuda, 1 Kuda", maka satu-satunya perwira yang dapat promosi adalah Kuda.

    • Kuda hanya bisa promosi jika berhasil memakan pion lawan yang bergerak di sepanjang lajur e.
    • Kuda dapat dipromosikan menjadi Ratu, Benteng, atau bidak lainnya yang dipilih pemain.
  2. Jika pemain memilih formasi "2 Kuda, 1 Garuda", maka satu-satunya perwira yang dapat promosi adalah Garuda.

    • Garuda hanya bisa promosi jika berhasil memakan pion lawan yang bergerak di sepanjang lajur e.
    • Garuda dapat dipromosikan menjadi Ratu, Benteng, atau bidak lainnya yang dipilih pemain.

Aturan menyesuaikan kode untuk:

  • Menyimpan informasi formasi pemain.
  • Menentukan apakah Kuda atau Garuda berhasil memakan pion lawan di lajur e.
  • Jika memenuhi syarat promosi, munculkan menu pemilihan bidak promosi.

Perbaikan kode

# === ATURAN PROMOSI KHUSUS ===
def check_promotion(piece, old_pos, new_pos, formasi):
    """Cek apakah bidak memenuhi syarat promosi berdasarkan formasi"""
    old_x, old_y = old_pos
    new_x, new_y = new_pos

    if new_x == 4 and (old_y - new_y) == 1:  # Lajur e = kolom 4
        if formasi == "2 Garuda, 1 Kuda" and piece.endswith("knight"):
            return True  # Kuda bisa promosi
        elif formasi == "2 Kuda, 1 Garuda" and piece.endswith("garuda"):
            return True  # Garuda bisa promosi
    return False

def promote_piece(piece):
    """Menampilkan pilihan promosi untuk Kuda atau Garuda"""
    color, piece_type = piece.split("_")
    promo_options = [f"{color}_queen", f"{color}_rook", f"{color}_bishop"]

    while True:
        screen.fill(WHITE)
        draw_board()

        # Tampilkan opsi promosi
        text = font.render(f"Pilih Promosi untuk {piece_type.capitalize()}:", True, BLACK)
        screen.blit(text, (SCREEN_WIDTH // 2 - 120, SCREEN_HEIGHT // 3 - 50))

        btns = []
        x_offset = SCREEN_WIDTH // 2 - 150
        for i, option in enumerate(promo_options):
            btn = draw_button(option.split("_")[1].capitalize(), x_offset + i * 120, SCREEN_HEIGHT // 3 + 50, 100, 50, RED)
            btns.append((btn, option))

        pygame.display.flip()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                for btn, option in btns:
                    if btn.collidepoint(mouse_pos):
                        return option  # Kembalikan jenis bidak promosi

# === HANDLE PERGERAKAN BIDAK ===
def move_piece(mouse_pos):
    """Menangani pergerakan bidak"""
    global selected_piece, selected_position

    col = (mouse_pos[0] - BOARD_X) // TILE_SIZE
    row = (mouse_pos[1] - BOARD_Y) // TILE_SIZE

    if selected_piece and 0 <= row < 9 and 0 <= col < 9:
        if check_promotion(selected_piece, selected_position, (col, row), player_formation):
            promoted_piece = promote_piece(selected_piece)
            pieces_positions.pop(selected_piece)
            pieces_positions[promoted_piece] = [(col, row)]
        else:
            pieces_positions[selected_piece].remove(selected_position)
            pieces_positions[selected_piece].append((col, row))

        selected_piece = None
        selected_position = None

Kode program yang telah dibuat:

Membuat satu fungsi check_promotion() untuk menentukan apakah Kuda atau Garuda memenuhi syarat promosi.
Menyesuaikan menu promote_piece() agar dapat mempromosikan baik Kuda maupun Garuda.
Mengubah move_piece() agar sistem hanya mengizinkan promosi untuk perwira yang benar yaitu Perwira Tunggal Terkecil  berdasarkan formasi yang dipilih pemain.

Dengan perbaikan ini, aturan tambahan pada Chess Nine sekarang sudah diterapkan dengan benar. 


Masalah Bidak Catur_Nine Tidak Bisa Digerakkan

Setelah membuat kode tapi bidak catur_nine tidak bisa digerakkan, lihat kode pada 3 file di URL Link sini: Kode Isi 3 File,

maka masalah ini kita mengidentifikasi beberapa potensi penyebab mengapa bidak dalam permainan Catur Nine belum dapat digerakkan:

  1. Inisialisasi Papan dan Posisi Bidak:

    • Pastikan bahwa fungsi initialize_board() telah dipanggil dengan benar dan bahwa variabel board_state telah diinisialisasi dengan posisi bidak yang sesuai.
  2. Penanganan Klik dan Pemilihan Bidak:

    • Fungsi handle_click(position)
    • Pastikan bahwa logika untuk memilih dan memindahkan bidak telah diimplementasikan dengan benar, termasuk validasi giliran pemain dan jenis bidak yang dipilih.
  3. Validasi Gerakan:

    • Fungsi is_valid_move(selected_piece, from_position, to_position) harus mengembalikan nilai True untuk gerakan yang sah dan False
    • Pastikan bahwa aturan gerakan untuk setiap jenis bidak, termasuk bidak khusus seperti "garuda", telah diimplementasikan dengan benar.
  4. Pembaruan Status Papan:

    • Setelah gerakan divalidasi, fungsi move_piece(piece, from_position, to_position) harus memperbarui board_state dengan posisi baru bidak yang dipindahkan.
  5. Penggantian Giliran Pemain:

    • Fungsi switch_turn() harus memastikan bahwa giliran pemain berganti setelah setiap gerakan yang valid.
  6. Pemilihan Formasi:

    • Pastikan bahwa formasi yang dipilih oleh pemain (misalnya, 2 Garuda, 1 Kuda) telah diimplementasikan dengan benar dan bidak ditempatkan sesuai dengan formasi yang dipilih.
  7. Pemrosesan Acara Pygame:

    • Pastikan bahwa loop utama permainan memproses acara Pygame dengan benar, termasuk acara MOUSEBUTTONDOWN untuk mendeteksi klik mouse.

Jika setelah memeriksa poin-poin di atas bidak masih belum dapat digerakkan, pertimbangkan untuk menambahkan pernyataan debug (seperti print()) di berbagai bagian kode untuk melacak alur eksekusi dan memastikan bahwa setiap fungsi bekerja sesuai yang diharapkan.

Selain itu, pastikan bahwa semua gambar bidak telah dimuat dengan benar dan ditampilkan di posisi yang sesuai pada papan catur.

... selected_formation

MEMANGGIL PILIHAN FORMASI

---

load_pieces() # Memuat gambar bidak

# **Memilih formasi bidak putih sebelum memulai permainan**

chosen_white_formation = choose_white_formation()

# **Menentukan formasi bidak hitam sesuai pilihan putih**

if chosen_white_formation == formasi_1_white:

    chosen_black_formation = formasi_1_black

else:

    chosen_black_formation = formasi_2_black

# **Menggabungkan formasi dengan posisi default**

STARTING_POSITIONS = {**default_position, **chosen_white_formation, **chosen_black_formation}

---

Kode ini akan menampilkan layar pemilihan formasi sebelum permainan dimulai, lalu memulai permainan dengan formasi yang dipilih oleh pemain putih dan hitam.

Kode ini merupakan bagian dari inisialisasi permainan catur dengan Pygame. Kode ini sebaiknya diletakkan di bagian main loop permainan, tepat sebelum loop while running.

Tempat yang Tepat dalam File

  1. Di dalam file utama permainan
    Jika Anda memiliki file utama seperti main.py, kode ini sebaiknya diletakkan setelah semua import, inisialisasi pygame, dan fungsi yang diperlukan.

  2. Sebelum loop utama permainan (while running:)
    Kode ini berfungsi untuk memilih formasi bidak sebelum permainan dimulai, sehingga harus ditempatkan di atas loop utama agar variabel STARTING_POSITIONS sudah siap digunakan.


Contoh Penempatan dalam File main.py

Misalnya, jika file utama Anda bernama main.py, letakkan kode ini setelah mendefinisikan semua variabel dan fungsi utama:

import pygame
import sys
from formations import choose_white_formation, formasi_1_white, formasi_1_black, formasi_2_black
from board import draw_board, draw_pieces
from timer import draw_timer

pygame.init()
screen = pygame.display.set_mode((800, 800))
WHITE = (255, 255, 255)

# **Memilih formasi bidak putih sebelum memulai permainan**
chosen_white_formation = choose_white_formation()

# **Menentukan formasi bidak hitam sesuai pilihan putih**
if chosen_white_formation == formasi_1_white:
    chosen_black_formation = formasi_1_black
else:
    chosen_black_formation = formasi_2_black

# **Menggabungkan formasi dengan posisi default**
default_position = {}  # Pastikan ini sudah didefinisikan sebelumnya
STARTING_POSITIONS = {**default_position, **chosen_white_formation, **chosen_black_formation}

# **Loop utama permainan**
running = True
while running:
    screen.fill(WHITE)  # Bersihkan layar
    draw_board()  # Gambar papan
    draw_pieces(STARTING_POSITIONS)  # Gambar bidak
    draw_timer()  # Gambar timer
    
    pygame.display.flip()  # Perbarui layar
    
    # **Event handler**
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

pygame.quit()
sys.exit()

Kesimpulan

  • Letakkan kode ini sebelum loop utama permainan (while running:).
  • Pastikan semua variabel yang digunakan sudah didefinisikan.
  • Jika menggunakan file terpisah untuk formasi (formations.py), pastikan sudah di-import di awal file.




Comments

Popular posts from this blog

MOVE (LANGKAH) CATUR TERBAIK SAYA DI TURNAMEN KEJUARAAN CATUR HARIAN CHESS.COM 2025

π”»π•š π•‹π”Έβ„π•Œβ„• π•Šπ•€π•Šπ”Έ 9, β„‚β„π”Όπ•Šπ•Š.ℂ𝕆𝕄 𝕄𝔼ℕ𝔾𝔸𝔻𝔸𝕂𝔸ℕℕ π•‹π•Œβ„β„•π”Έπ•„π”Όβ„• π•‚π”Όπ•π•Œπ”Έβ„π”Έπ”Έβ„• β„‚π”Έπ•‹π•Œβ„ ℍ𝔸ℝ𝕀𝔸ℕ β„‚β„π”Όπ•Šπ•Š.ℂ𝕆𝕄 2025

Kecerdasan Manusia Dan Kecerdasan Buatan/Ai (Artificial Intelligence)