from machine import Pin, I2C
import framebuf, time, urandom
from ssd1306 import SSD1306_I2C

# === Display Setup ===
i2c = I2C(1, scl=Pin(11), sda=Pin(10), freq=400_000)
oled = SSD1306_I2C(128, 64, i2c)

# === Tile Definitions ===
def tile(b): return framebuf.FrameBuffer(bytearray(b), 8, 8, framebuf.MONO_HLSB)

TILES = {
    '☺': tile([0x3C,0x42,0xA5,0x81,0xA5,0x99,0x42,0x3C]), # Hero
    'W': tile([0xFF,0x81,0xBD,0xA5,0xBD,0x81,0xFF,0x00]), # Wall
    'F': tile([0]*8),                                     # Floor
    'C': tile([0x18,0x3C,0x7E,0xDB,0xFF,0x7E,0x3C,0x18]), # Coin
    'T': tile([0x3C,0x66,0x5A,0xA5,0xA5,0x5A,0x66,0x3C]), # Treasure
    'H': tile([0x00,0x6C,0xFE,0xFE,0x7C,0x38,0x10,0x00]), # Heart
    'E': tile([0x18,0x3C,0x7E,0xDB,0xFF,0x7E,0x24,0x42]), # Enemy
    'S': tile([0x00,0x3C,0x42,0x99,0xA5,0x42,0x3C,0x00])  # Stairs
}

# === World Setup ===
WIDTH, HEIGHT = 32, 16
CAM_W, CAM_H = 16, 8
player = {'x': 2, 'y': 2, 'hp': 10, 'coins': 0, 'deaths': 0}

# Create map
world = [['F' for _ in range(WIDTH)] for _ in range(HEIGHT)]
for x in range(WIDTH): world[0][x] = world[HEIGHT-1][x] = 'W'
for y in range(HEIGHT): world[y][0] = world[y][WIDTH-1] = 'W'

# Add inner structure
for y in range(4,12):
    world[y][10] = 'W'
    world[y][15] = 'W'
    world[8][y-2] = 'W'

# Sprinkle objects
world[3][5] = 'C'
world[4][7] = 'H'
world[5][13] = 'T'
world[7][6] = 'E'
world[9][9] = 'E'
world[10][14] = 'S'

# === Draw World ===
def draw_world(cam_x, cam_y):
    for row in range(CAM_H):
        for col in range(CAM_W):
            wx, wy = cam_x + col, cam_y + row
            tile_id = world[wy][wx] if 0 <= wx < WIDTH and 0 <= wy < HEIGHT else 'W'
            oled.blit(TILES.get(tile_id, TILES['F']), col*8, row*8)
    # Draw hero
    px = (player['x'] - cam_x) * 8
    py = (player['y'] - cam_y) * 8
    oled.blit(TILES['☺'], px, py)
    # HUD
    oled.text("HP:%d" % player['hp'], 0, 56)
    oled.text("$:%d" % player['coins'], 60, 56)

# === Roll Dice ===
def roll_die():
    return urandom.getrandbits(3) % 6 + 1  # 1–6

# === Get directions ===
DIRS_ORTHO = [(0,-1),(0,1),(-1,0),(1,0)]
DIRS_DIAG  = [(-1,-1),(1,-1),(-1,1),(1,1)]

# === Movement ===
def move_player():
    roll = roll_die()
    dirs = DIRS_DIAG if roll % 2 == 1 else DIRS_ORTHO
    dir_idx = urandom.getrandbits(2) % len(dirs)
    dx, dy = dirs[dir_idx]
    steps = roll
    for _ in range(steps):
        nx, ny = player['x'] + dx, player['y'] + dy
        if world[ny][nx] == 'W':
            # Bounce: pick a new direction
            for try_dir in dirs:
                tx, ty = player['x'] + try_dir[0], player['y'] + try_dir[1]
                if world[ty][tx] != 'W':
                    dx, dy = try_dir
                    break
            nx, ny = player['x'] + dx, player['y'] + dy
        # Move
        if 0 <= nx < WIDTH and 0 <= ny < HEIGHT:
            player['x'], player['y'] = nx, ny
            interact(world[ny][nx])
            world[ny][nx] = 'F'

# === Interact ===
def interact(tile):
    if tile == 'C':
        player['coins'] += 1
    elif tile == 'T':
        player['coins'] += roll_die()
    elif tile == 'H':
        player['hp'] = min(10, player['hp'] + 2)
    elif tile == 'E':
        player['hp'] -= 3
        if player['hp'] <= 0:
            player['deaths'] += 1
            player['hp'] = 10
            player['x'], player['y'] = 2, 2
    elif tile == 'S':
        # Reached stairs – reset world (demo)
        oled.fill(0)
        oled.text("Next Floor!", 20, 30)
        oled.show()
        time.sleep(1)
        generate_new_floor()

# === New Floor ===
def generate_new_floor():
    global world
    world = [['F' for _ in range(WIDTH)] for _ in range(HEIGHT)]
    for x in range(WIDTH): world[0][x] = world[HEIGHT-1][x] = 'W'
    for y in range(HEIGHT): world[y][0] = world[y][WIDTH-1] = 'W'
    # Random decorations
    for _ in range(15):
        x, y = urandom.getrandbits(5) % WIDTH, urandom.getrandbits(4) % HEIGHT
        world[y][x] = urandom.choice(['W','C','T','H','E'])
    world[urandom.getrandbits(4)%HEIGHT][urandom.getrandbits(5)%WIDTH] = 'S'
    player['x'], player['y'] = 2, 2

# === Main Game Loop ===
while True:
    move_player()
    cam_x = max(0, min(WIDTH - CAM_W, player['x'] - CAM_W//2))
    cam_y = max(0, min(HEIGHT - CAM_H, player['y'] - CAM_H//2))
    oled.fill(0)
    draw_world(cam_x, cam_y)
    oled.show()
    time.sleep(1.0)  # 1 turn per second
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT