kelompok06-2048/Bot_2048.py
Evelyn Sucitro 1736e2f4ab Update
2025-12-04 22:46:04 +07:00

192 lines
6.8 KiB
Python

import time
import random
import numpy as np
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
URL_LOGIN = "http://localhost/Kelompok06_2048/Homepage.html"
SEARCH_DEPTH = 4
DELAY_ANIMATION = 0.1
class GameAI:
def __init__(self, url):
print(">>> Menyiapkan Browser Mode HARDCORE (Depth 4)...")
chrome_options = Options()
chrome_options.add_argument("--log-level=3")
chrome_options.add_experimental_option("detach", True)
self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
self.driver.set_window_size(1000, 1000)
self.driver.get(url)
print("\n" + "="*50)
print(" SILAKAN LOGIN MANUAL -> KLIK PLAY ")
print(" Bot Depth 4 siap menunggu di arena...")
print("="*50 + "\n")
try:
WebDriverWait(self.driver, 3600).until(
EC.presence_of_element_located((By.ID, "board"))
)
print(">>> GAME START! Mengaktifkan Otak Jenius...")
time.sleep(1)
except:
print("Gagal deteksi game, tapi browser tetap terbuka.")
self.body = self.driver.find_element(By.TAG_NAME, 'body')
def get_grid(self):
matrix = np.zeros((4, 4), dtype=int)
try:
for r in range(4):
for c in range(4):
element_id = f"{r}-{c}"
try:
tile = self.driver.find_element(By.ID, element_id)
text = tile.text.strip()
if text.isdigit():
matrix[r][c] = int(text)
else:
matrix[r][c] = 0
except:
matrix[r][c] = 0
except:
pass
return matrix
def heuristic(self, grid):
weights = np.array([
[0, 1, 10, 30],
[150, 100, 80, 50],
[200, 300, 500, 800],
[20000, 8000, 3000, 1500]
])
score = np.sum(grid * weights)
empty_count = len(np.where(grid == 0)[0])
score += empty_count * 30000
penalty = 0
for x in range(4):
# Baris
current = 0
next_val = 0
for y in range(3):
current = grid[x][y]
next_val = grid[x][y+1]
if current > next_val:
score += current - next_val
else:
score -= (next_val - current) * 5
for y in range(3):
current = grid[y][x]
next_val = grid[y+1][x]
if current > next_val:
score += current - next_val
else:
score -= (next_val - current) * 5
return score
def simulate_move(self, grid, direction):
temp_grid = grid.copy()
if direction == 'UP': temp_grid = np.rot90(temp_grid, 1)
elif direction == 'RIGHT': temp_grid = np.rot90(temp_grid, 2)
elif direction == 'DOWN': temp_grid = np.rot90(temp_grid, 3)
changed = False
new_grid_vals = []
for row in temp_grid:
new_row = [x for x in row if x != 0]
for i in range(len(new_row)-1):
if new_row[i] == new_row[i+1] and new_row[i] != 0:
new_row[i] *= 2
new_row[i+1] = 0
new_row = [x for x in new_row if x != 0]
new_row += [0] * (4 - len(new_row))
new_grid_vals.append(new_row)
if new_row != list(row): changed = True
temp_grid = np.array(new_grid_vals)
if direction == 'UP': temp_grid = np.rot90(temp_grid, 3)
elif direction == 'RIGHT': temp_grid = np.rot90(temp_grid, 2)
elif direction == 'DOWN': temp_grid = np.rot90(temp_grid, 1)
return temp_grid, changed
def expectimax(self, grid, depth, is_player_turn):
if depth == 0: return self.heuristic(grid)
if is_player_turn:
best_score = -float('inf')
for move in ['DOWN', 'RIGHT', 'LEFT', 'UP']:
new_grid, changed = self.simulate_move(grid, move)
if changed:
score = self.expectimax(new_grid, depth - 1, False)
best_score = max(best_score, score)
return best_score if best_score != -float('inf') else -10000000
else:
empty_cells = list(zip(*np.where(grid == 0)))
if not empty_cells: return self.heuristic(grid)
sample_size = 4
if len(empty_cells) > sample_size:
empty_cells = random.sample(empty_cells, sample_size)
total_score = 0
for r, c in empty_cells:
grid[r][c] = 2
total_score += self.expectimax(grid, depth - 1, True)
grid[r][c] = 0
return total_score / len(empty_cells)
def run(self):
print(">>> Bot Mulai! (Mode: FULL DEPTH 4)")
print(">>> Tips: Jangan minimize window browser biar lancar.")
while True:
try:
grid = self.get_grid()
if np.sum(grid) == 0:
time.sleep(0.5)
continue
best_move = None
max_val = -float('inf')
valid_found = False
empty = len(np.where(grid == 0)[0])
print(f"\rMikir... (Kosong: {empty})", end="")
for move in ['DOWN', 'RIGHT', 'LEFT', 'UP']:
sim_grid, changed = self.simulate_move(grid, move)
if changed:
valid_found = True
val = self.expectimax(sim_grid, SEARCH_DEPTH, False)
if val > max_val: max_val = val; best_move = move
if best_move:
self.body.send_keys(getattr(Keys, best_move))
time.sleep(DELAY_ANIMATION)
else:
if not valid_found:
print("\nGAME OVER!")
break
else:
self.body.send_keys(Keys.DOWN)
except KeyboardInterrupt:
break
except Exception:
time.sleep(1)
if __name__ == "__main__":
ai = GameAI(URL_LOGIN)
ai.run()