from polycal4 import get_infos, KEY_NONE, KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_ENTER, KEY_ESC screen_w, screen_h, poly_has_color, poly_set_pixel, draw_line, fill_rect, show_screen, init_clean_screen, wait_key, wait_release, esc_key, HAS_KEYS, poly_pause, sleep = get_infos(["w","h","hc","sp","dl","fr","sh","cli","wk","wr","ek","hk","p","s"], 256, 128, 4) get_infos = None SCALE = min(screen_w // 128, screen_h // 64) YELLOW, RED, BLUE, GREEN, ALL = 0, 1, 2, 3, 4 VOID, WALL, SPIKES, MONSTER, TRAP, EXIT = 100, 101, 102, 107, 112, 117 GO_UP, GO_RIGHT, GO_DOWN, GO_LEFT, ATTACK, QUIT = 10, 11, 12, 13, 14, 15 NEW_GAME, TRAP_APPEARED, SPIKES_APPEARED = 20, 21, 22 JAUNE, ROUGE, BLEU, VERT, TOUS = 0, 1, 2, 3, 4 VIDE, MUR, PICS, MONSTRE, PIEGE, SORTIE = 100, 101, 102, 107, 112, 117 ALLER_HAUT, ALLER_DROITE, ALLER_BAS, ALLER_GAUCHE, ATTAQUER, QUITTER = 10, 11, 12, 13, 14, 15 NOUVELLE_PARTIE, PIEGE_APPARU, PICS_APPARUS = 20, 21, 22 def ri(rs,a,b): rs[0] = (rs[0] * 214013 + 2531011) % 4294967296 r = (rs[0] // 65536) & 0x7fff return r % (b-a) + a ### Rendering def px(x, y, c): for sx in range(SCALE): for sy in range(SCALE): poly_set_pixel(x*SCALE+sx, y*SCALE+sy, c) if poly_has_color: colors = [(77,71,63), (210,217,217), (241,233,103), (234,96,88), (97,156,236), (111,226,126), (178,126,206)] s=0x002a2a55005454aa00 m=0x00005ae7bd18000000 t=0x00182c4a5234180000 e=0xf080e0c080e0c0f000 f=0x0f0107030107030f00 p=0x386565396dd7ff7d00 tiles = [0,0xff818181818181ff01,s+2,s+3,s+4,s+5,s+6,m+2,m+3,m+4,m+5,m+6,t+2,t+3,t+4,t+5,t+6,f+2,e+3,f+4,e+5] sprites = [p+2,p+3,p+4,p+5] def render_image(tile, x0, y0): fg, bg = colors[tile & 0xff], colors[0] tile >>= 8 if tile: for y in range(8): for x in range(8): px(x0*8+7-x, y0*8+7-y, fg if tile & 1 else bg) tile >>= 1 else: fill_rect(x0*8*SCALE, y0*8*SCALE, 8*SCALE, 8*SCALE, colors[0]) else: colors = [(255,255,255),(0,0,0)] p1=0x040a00<<40 p2=0x040a06<<40 p3=0x040a0e<<40 p4=0x040e04<<40 s=0x5454aa00 m=0x00005ae7bd18 t=0x1028542810 e=0xe080e0c080e0c0f0 tiles = [0,0xff818181818181ff,s+p1,s+p2,s+p3,s+p4,(s<<31)+s,m+p1,m+p2,m+p3,m+p4,m<<16,t+p1,t+p2,t+p3,t+p4,t<<8,0x275107030107030f,e+p2,0x275177030107030f,e+p4] sprites = [0x386565396dd7ff7d,0x386565396dd7e77d,0x386565396dd7c77d,0x386565396dc7ef7d] def render_image(tile, x0, y0): if tile: for y in range(8): for x in range(8): px(x0*8+7-x, y0*8+7-y, colors[tile & 1]) tile >>= 1 else: fill_rect(x0*8*SCALE, y0*8*SCALE, 8*SCALE, 8*SCALE, colors[0]) def render_game(board, players, old_players, update): for xy in update: if xy == -1: for y in range(8): for x in range(16): render_image(tiles[board[16*y+x]-VOID], x, y) else: render_image(tiles[board[xy]-VOID], xy%16, xy//16) for xy in old_players: render_image(tiles[board[xy]-VOID], xy%16, xy//16) for i in range(4): render_image(sprites[i], players[i]%16, players[i]//16) ### API for submissions if HAS_KEYS: interactive_actions = {KEY_UP:GO_UP, KEY_RIGHT:GO_RIGHT, KEY_DOWN:GO_DOWN, KEY_LEFT:GO_LEFT, KEY_ENTER:ATTACK, KEY_ESC:QUIT} else: interactive_actions = {"8":GO_UP, "6":GO_RIGHT, "2":GO_DOWN, "4":GO_LEFT, "5":ATTACK, "9":QUIT} def input_action(): if HAS_KEYS: wait_release() i = KEY_NONE while not i in interactive_actions.keys(): i = wait_key() else: print("Déplacement:") print(" 8") print(" 4 6") print(" 2") print("Attaquer: 5") print("Voir plateau: 0") print("Quitter: 9") i = input("Que faire ?> ") return interactive_actions.get(i) def is_a(obj, kind): if kind == VOID or kind == WALL: return obj == kind return kind <= obj <= kind + 4 def affects(obj, player): return (is_a(obj, SPIKES) or is_a(obj, MONSTER) or is_a(obj, TRAP)) and obj != SPIKES+player and obj != MONSTER+player and obj != TRAP+player pathfind_d = [-16, +16, -1, +1, GO_UP, GO_DOWN, GO_LEFT, GO_RIGHT] def pathfind(board, start, end): n = len(board) parent = [-1]*n directions = [-1]*n queue = [start] parent[start] = start cell = -1 while queue: cell = queue.pop(0) if cell == end: break for i in range(4): d = cell+pathfind_d[i] if board[d] != WALL and parent[d] < 0: parent[d] = cell directions[d] = pathfind_d[i+4] queue.append(d) if cell == end: path = [] while cell != start: path = [directions[cell]] + path cell = parent[cell] return path demander_action, est_un, affecte, calculer_chemin = input_action, is_a, affects, pathfind ### Board generator def ufc(): return [i for i in range(128)] def ufr(uf,i): if uf[i] == i: return i rep = ufr(uf, uf[i]) uf[i] = rep return rep def ufm(uf,i,j): uf[ufr(uf,i)]=ufr(uf,j) def gb(rs): board = [WALL] * 128 pp = [17,30,97,110] pe = [47,80,95,32] for i in range(4): board[pp[i]] = VOID board[pe[i]] = EXIT+i uf = [i for i in range(128)] while any(ufr(uf,pp[i]) != ufr(uf,pe[i]) for i in range(4)): i = ri(rs,1,7)*16 + ri(rs,1,15) if board[i] == WALL and any(board[n] != VOID for n in (i-16,i+16,i-1,i+1)): board[i] = VOID for n in (i-16,i+16,i-1,i+1): if board[n] != WALL: ufm(uf,i,n) for i in range(128): if board[i] == VOID and ri(rs,0,16)<2: board[i]=[MONSTER, MONSTER, SPIKES, TRAP][ri(rs,0,4)]+ri(rs,0,5) return board ### Game logic def play_board(rs, turn_function, blind): board = gb(rs) players = [17,30,97,110] old_players = [] ev = [(-1,-1,NEW_GAME,-1)] update = [-1] turns = 0 penalty = 0 while True: if not blind: render_game(board, players, old_players, update) show_screen() if not HAS_KEYS: poly_pause() action = turn_function(board, players, ev) ev = [] update = [] old_players = players[:] if action is None: continue if action == QUIT: return None turns += 1 traps_activated = 0 for p in range(4): coord = players[p] if coord < 0: continue if action == ATTACK: for direction in range(4): dx = (direction == 1) - (direction == 3) dy = (direction == 2) - (direction == 0) i = coord + dx + 16*dy dest = board[i] if is_a(dest, MONSTER): board[i] = VOID update.append(i) elif is_a(dest, TRAP) and affects(dest, p): traps_activated += 1 board[i] = VOID update.append(i) else: dx = (action == GO_RIGHT) - (action == GO_LEFT) dy = (action == GO_DOWN) - (action == GO_UP) i = coord + dx + 16*dy dest = board[i] if dest == EXIT+p: players[p] = -1 continue if dest == WALL or is_a(dest, EXIT): continue players[p] = i if not affects(dest, p): continue if is_a(dest, SPIKES): penalty += 10 elif is_a(dest, MONSTER): penalty += 10 board[i] = VOID update.append(i) elif is_a(dest, TRAP): traps_activated += 1 board[i] = VOID update.append(i) while traps_activated > 0: effect = ri(rs,0,3) if effect == 0: penalty += 10 x = ri(rs,1,15) y = ri(rs,1,7) if board[y*16+x] == VOID and y*16+x not in players: board[y*16+x] = (TRAP if effect==1 else SPIKES) + ri(rs,0,4) ev.append((x, y, TRAP_APPEARED if effect==1 else SPIKES_APPEARED, p)) update.append(y*16+x) traps_activated -= 1 if all(p < 0 for p in players): score = 150 - penalty - turns print("Bravo! "+str(turns)+"T "+str(penalty)+"D -> "+str(score)) return score def play_game(turn_function, blind=False, seed=0xc0ffee, maxgames=100): if not blind: init_clean_screen() rs = [seed] games = 0 score = 0 while games != maxgames: print("#"+str(games)+": "+str(rs[0])) board_score = play_board(rs, turn_function, blind) if board_score is None: print("") print("Quit!") return else: score += max(board_score, 0) games += 1 print("Games solved:", games) print("Score:", score) if __name__ == "__main__": def turn(board, player, ev): return input_action() play_game(turn)