# les scripts d'IA ne doivent en aucun cas acceder au contenu de ce script from kblibpub import * try: from random import choice, randint, seed except: from urandom import choice, randint, seed from pc7 import PC_sw, PC_sh, PC_hcol, PC_init, PC_dirt, PC_clrevnts, PC_show, PC_clr, PC_spx, PC_drect, PC_frect, PC_dstr, \ PC_fw, PC_wstr, PC_fh, PC_hgkey, PC_wkey, PC_gkey, PC_wnokey, K_LEFT, K_UP, K_DOWN, K_RIGHT, K_ENTER, K_ENTER2, \ K_ESC, K_DEL, K_ON, K_0, K_2, K_4, K_5, K_6, K_8, K_ADD, K_SUB, K_SUB2, K_MUL, K_DIV, K_DIV2, K_SHIFT, K_ALPHA, K_ON, \ K_APPS, PC_click, PC_wnoclick, PC_nkeys keybreak_mode = PC_nkeys() == 0 keys2_mode = PC_nkeys() == 2 _print = print def print(*ls): if not PC_dirt: _print(*ls) #------------------------- # fonctions de coordonnees #------------------------- def pos_box(pos_x, pos_y, x0, y0, w, h, nx, ny): wb, hb = w // nx, h // ny return int(x0 + (w - nx*wb)/nx + wb*pos_x), int(y0 + (h - ny*hb)/ny + hb*pos_y), wb, hb def pos_sabot(pos_x): x, y, w, h = pos_box(pos_x, 0, xsep, ysep, PC_sw - xsep, PC_sh - ysep, 2, 1) if not PC_hcol: x += 1 return x, y, w, h def pos_jeu(pos_x, pos_y, num_joueur): x, y, w, h = pos_box(pos_x, pos_y, num_joueur*col_w, 0, col_w-(num_joueur and not PC_hcol), ysep, n_cartes_lgn, n_cartes_col) if not PC_hcol and num_joueur: x += 2 return x, y, w, h def pos_main(pos_x): return pos_box(pos_x, 0, 0, ysep, xsep, PC_sh - ysep, TAILLE_MAIN, 1) #--------- # couleurs #--------- C_BLACK = (0, 0, 0) C_WHITE = (255, 255, 255) C_RED = (255, 32, 32) C_GREEN_LIGHT = (0, 255, 0) C_GREEN_DARK = (0, 191, 0) C_CYAN = (0, 255, 255) C_MAGENTA = (255, 0, 255) C_BLUE = (32,32,255) C_GRAY_LIGHT = (223, 223, 223) C_GRAY_DARK = (127, 127, 127) # palette monochrome P_WHITE_BLACK = (C_WHITE, C_BLACK) def rgb2hsv(r, g, b): ''' convertit une couleur donnee en coordonnees Rouge-Vert-Bleu (RGB) vers des coordonnees Teinte-Saturation-Valeur (HSV), avec : - r, g, b : les coordonnees rouge/vert/bleu (entier de 0 a 255) ''' cmax = max(r, g, b) d = cmax - min(r, g, b) h = d and (cmax == b and (r-g)/d+4 or cmax==g and (b-r)/d+2 or cmax==r and ((g -b)/d)%6) return h/6, cmax and d/cmax, cmax/255 def hsv2rgb(h, s=1, v=1): ''' convertit une couleur donnee en coordonnees Teinte-Saturation-Valeur (HSV) vers des coordonnees Rouge-Vert-Bleu (RGB), avec : - h : la teinte (sur l'intervalle [0;1[) - s et v : les saturation et valeur (sur l'intervalle [0;1]) ''' h = (h % 1) * 6 c = v * s x = c * (1 - abs((h % 2) - 1)) r, g, b = h < 1 and (c,x,0) or h < 2 and (x,c,0) or h < 3 and (0,c,x) or h < 4 and (0,x,c) or h < 5 and (x,0,c) or (c,0,x) return [round((k + v - c) * 255) for k in (r, g, b)] def couleur_joueur(num_joueur): return not PC_hcol and C_WHITE or num_joueur == SABOT and C_GRAY_LIGHT or joueurs_col[num_joueur] #--------- # sprites #--------- HMIN_ICON = PC_hcol and 24 or 15 WMAX_ICON = PC_hcol and 32 or 10 SPRITES = PC_hcol and { I_50_BORNES: (24, 24, 0, (C_WHITE, C_RED, C_BLACK), ( b"\20\25\0\25$\25\0!\30\25\0)\20\25\x001\b\25\09\4\25\09\0\25\0Y\0A\2\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2" b"<\6\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2<\6\20\2\0\5\0" b"\35\0\5\0>\4\1\0\35\0\1\b\32\4\17\f\a\24\17\b\32\0\3\f\3\0\37\0\3\f\3\4\6\0\16\3\24'\24\3\0\6\0\16\3\4\a\4'\4\a\4\3\0\32" b"\3\4\a\4\3\34\3\4\a\4\3\b\22\3\24\3\34\3\24\3 \3\f\3$\3\f\3(\17,\17\4" )), I_CREVAISON: (27, 20, 0, (C_WHITE, C_GREEN_LIGHT, C_BLACK), ( b'$\31H!D\1\30\1@\1 \1<\1 \18\1(\x014\1\34\1\4\5,\1\4\1\20\5\0\25 \5\4\1\f%\24\25\0\1\4-\fY\b]\4\r\4\16$\21\4\r\0\2\f\2\4' b'\26\0\21\0\21\2\24"\31\0\t\2\4\6\4\6\24\2\r\0\5\0\t\2\4\6\4\6\4\6\4\2\r\0\r\4\2\24\n\0\6\0\6\b\t\24\2\f\2\0\6\f\x060\16' b'\4\36\24' )), I_ROUE_SECOURS: (24, 24, 0, P_WHITE_BLACK, ( b"\20\v\36\23\30\27\22\37\f#\n#\b\17\6\17\4\r\2\a\2\r\2\v\0\3\6\3\0\v\0\r\0\1\n\1\0\31\0\1\4\3\4\1\0\27\0\1\2\1\2\1\2\1\0" b"\27\0\1\2\1\2\1\2\1\0\27\0\1\4\3\4\1\0\31\0\1\n\1\0\r\0\v\0\3\6\3\0\v\2\r\2\a\2\r\4\17\6\17\b#\n#\f\37\22\27\30\23\36\v" b"\20" )), I_VEHICULE_INCREVABLE: (27, 20, 0, (C_WHITE, C_MAGENTA, C_BLACK), ( b"$\31H!D\1\30\1@\1 \1<\1 \18\1(\x014\1\34\1\4\5,\1\4\1\20\5\0\25 \5\4\1\f%\24\25\0\1\4-\fY\b]\4\2\b\n\0\n\0\n\0\n\0\2\b\2" b"\0\6\4\6\20\2\f\2\20\2\4\n\4\16\b\n\4\n\4\2\4\2\20\26\b\2\f\2\4\n \n\4\2\f\2\b\26\20\2\4\2\4\n\4\n\b\16\30\2\20\2\f\2\20" b"\6 \2\0\n\0\n\0\n\0\n\24" )), I_ACCIDENT: (27, 29, 0, (C_WHITE, C_BLACK, C_BLUE), ( b" \5\\\1\4\1T\1\b\1P\1\f\1L\1\20\1P\1\f\1T\1\b\1T\5\4\1P\1\0\r\4\168\5\20\228\5\20\x120\t\24\2\f\2,\5\30\2\f\2(\5\30\2\20" b"\2(\5\4\2\f\2\24\2$\5\b\2\4\6\b\2\4\6 \5\b\2\0\6\b\6\0\26\20\5\f\6\0\2\b&\f\5\f\2\b\2\0.\4\5\20F\4\5\bN\0\5\20\r\f\r\4" b"\22\0\5\f\25\4\1\f\1\0\22\0\5\b\5\f\t\24\1\26\5\b\1\24\5\4\5\4\1\16\0\2\0\5\4\1\4\5\4\5\4\5\4\1\16\0\2\0\5\4\5\0\5\0\t" b"\24\1\b\n\4\21\f\5\0\1\f\1$%\4\r\34" )), I_REPARATIONS: (29, 27, 0, (C_WHITE, C_MAGENTA, C_BLACK), ( b",\31P!L\1\30\1H\1 \1$\1\30\1 \1(\1\20\1(\1$\1\20\1\34\1\4\5$\1\b\1\4\1\20\5\0\25\30\1\b\5\4\1\f%\30\1\0\21\0\1\4-\24Y\30" b"U\4\2\0\2\0\6\4\16\f\16\4\21\4\26\0\2\f\2\4\2\f\2\0\21\4\32\24\6\24\2\25\36\4\6\4\6\4\6\4\2\r\0\1\0\32\4\6\4\6\4\6\4\2\r" b"\0\1\0\2\0\2\4\6\24\6\24\2\b\t\f\n\0\2\f\2\4\2\f\2<\16\f\16(^\f\6 \2\0\6 \6\4\6$\2\0\6$\6\0\2(\2\0\6(\2,\26X\26D>\24" )), I_AS_VOLANT: (28, 21, 0, (C_WHITE, C_RED, C_BLACK), ( b"4\t\\\25\4\32,\31L!\4\22,!<\1\4\1\f\r8\1\b\1\f\r\4\1\4\1 \1\b\35\0\5\0\1\4\5\24\1\0\1\b\25\4\t\0\1\34\5\4\1\b\r\0\25\0\1" b"\24\r\4\1\30\31\24Y\f]\b\r\16\f\16\f\21\4\21\2\b\6\4\2\b\6\4\r\0\31\2\20\2\0\2\20\2\0\t\0\1\b\r\2\4\2\b\6\4\2\b\2\5\0\1" b"\20\t\2\b\2\4\6\b\2\4\2\1\0\1\30\5\6\20\n\20\2\5,\6\b\2\4\6\b\2<\n\20\n\34" )), } or { I_50_BORNES : (12, 16, 0, P_WHITE_BLACK, b"\6\a\n\3\6\3\4\1\16\1\0\1\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\22\31"), I_FEU_VERT : (6, 16, 0, P_WHITE_BLACK, b"\2\3\4\1\2\1\2\1\2\1\4\3\22\3\4\1\2\1\2\1\2\1\4\3\22\3\4\a\0\27\0\a\4\3\2"), I_FEU_ROUGE : (6, 16, 0, P_WHITE_BLACK, b"\2\3\4\a\0\27\0\a\4\3\22\3\4\1\2\1\2\1\2\1\4\3\22\3\4\1\2\1\2\1\2\1\4\3\2"), I_VEHICULE_PRIORITAIRE: (10, 7, 1, (C_BLACK, C_WHITE), b"\0\3\6\3\0\1\0\1\6\1\0\a\0\3\0\5\2\1\0\3\0\1\2\5\0\3\0\v\6\5\22"), I_LIMITATION: (10, 10, 0, P_WHITE_BLACK, b"\4\a\b\1\6\1\4\1\n\1\0\1\0\3\2\1\2\3\0\1\2\1\0\1\0\3\2\1\0\1\0\1\0\3\0\1\4\1\2\1\0\1\n\1\4\1\6\1\b\a\4"), I_FIN_LIMITATION: (10, 10, 0, P_WHITE_BLACK, b"\4\a\b\1\6\1\4\1\6\5\0\1\6\5\0\3\4\5\2\3\2\5\4\3\0\5\6\1\0\5\6\1\4\1\6\1\b\a\4"), I_PANNE_ESSENCE: (10, 13, 0, P_WHITE_BLACK, b"\0\1\f\3\0\1\n\3\0\1\n\1\0\1\f\1\4\a\6\3\6\3\0\1\16\1\2\1\22\1\20\1\22\1\20\1\22\1\6"), I_POMPE_ESSENCE: (8, 14, 0, P_WHITE_BLACK, b"\n\1\n\1\2\a\0\1\2\1\4\5\0\1\n\3\0\1\2\1\0\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\0\1\2\1\0\3\n\21"), I_CAMION_CITERNE: (10, 9, 0, P_WHITE_BLACK, b"\6\3\b\17\0;\0\17\30\3\2\3\6\3\2\3\2"), I_CREVAISON: (10, 10, 0, P_WHITE_BLACK, b"\4\a\b\1\6\1\4\1\0\1\2\1\0\1\0\3\n\a\n\a\0\1\2\1\0\t\6\5\0\5\0\a\b\1\20\1\b"), I_ROUE_SECOURS: (10, 10, 0, P_WHITE_BLACK, b"\4\a\b\v\4\3\6\3\0\3\0\1\2\1\0\a\n\a\n\a\0\1\2\1\0\3\0\3\6\3\4\v\b\a\4"), I_VEHICULE_INCREVABLE: (10, 13, 0, P_WHITE_BLACK, b"\2\v\4\17\0\5\6\t\0\1\2\1\0\a\n\a\n\a\0\1\2\1\0\t\6\5\0\17\4\v\26\1\0\1\0\1\0\1\0\1\0\1\0\1\0\1\0\1\0\1\0"), I_ACCIDENT: (10, 14, 0, P_WHITE_BLACK, b"\6\3\f\a\n\a\n\1\2\1\b\3\2\3\6\3\2\3\6\3\2\3\4\5\2\5\2\5\2\5\2\17\0\a\2\17\2/"), I_REPARATIONS: (10, 16, 0, P_WHITE_BLACK, b"\0\1\2\3\2\1\0\3\0\a\0\a\0\a\0\a\2\3\2\t\6-\0\17\4\v\b\a\n\a\n\a\n\a\n\a\n\a\n\a\4"), I_AS_VOLANT: (10, 10, 0, P_WHITE_BLACK, b"\4\a\b\1\6\1\4\1\n\1\0\1\16\3\0\3\2\3\0\3\4\3\4\3\2\1\2\1\2\1\0\1\n\1\4\1\6\1\b\a\4"), } #the image drawing function #- rle : image RLE-compressed data #- w : width of image #- pal : palette of colors to use with image #- itransp : index of 1 transparent color in palette or -1 if none def draw_image(rle, x0, y0, w, h, pal, itransp=-1): i, x = 0, 0 x0, y0 = int(x0), int(y0) nvals = len(pal) nbits = 0 nvals -= 1 while(nvals): nvals >>= 1 nbits += 1 maskval = (1 << nbits) - 1 maskcnt = (0xFF >> nbits >> 1) << nbits while i> nbits if (v & 0b10000000 or nbits == 8): i += 1 c |= rle[i] << (7 - nbits + (nbits == 8)) c = c + 1 while c: cw = min(c, w - x) if mv != itransp: col = pal[mv] PC_frect(x0 + x, y0, cw, 1, col) c -= cw x = (x + cw) % w y0 += x == 0 h -= x == 0 i += 1 #----------------- # classe jeujoueur #----------------- class c_jeujoueur(c_infos_jeu_et_main): def nouvelle_manche(self, nbr_cartes, taille_main, bornes_arrivee): self.main_affichable = [None] * taille_main super().nouvelle_manche(nbr_cartes, taille_main, bornes_arrivee) def main_append(self, carte): for k in range(TAILLE_MAIN): if self.main_affichable[k] == None: self.main_affichable[k] = carte return k def main_remove(self, carte): for pos in range(TAILLE_MAIN): if self.main_affichable[pos] == carte: self.main_affichable[pos] = None return pos def traite_coup(self, coup, redraw=1, posaff=-1): points_old = self.points cf = len(self.coups_fourres_autorises) and coup.destination == self.num_joueur and coup.origine != SABOT \ and coup.carte in self.coups_fourres_autorises super().traite_coup(coup) if coup.origine == SABOT and coup.destination == self.num_joueur: pos = self.main_append(coup.carte) if redraw and self.num_joueur == show_main_joueur: redraw_main(coup.carte, pos, self.num_joueur) redraw_sabot() elif coup.origine == self.num_joueur: pos = self.main_remove(coup.carte) if posaff >= 0 and pos != posaff and self.main_affichable[posaff] == coup.carte: self.main_affichable[posaff], self.main_affichable[pos] = self.main_affichable[pos], self.main_affichable[posaff] pos = posaff if redraw and self.num_joueur == show_main_joueur: redraw_main(None, pos, self.num_joueur) if coup.destination == SABOT: draw_carte_defausse(coup.carte) if coup.destination == self.num_joueur and coup.origine != SABOT: if coup.carte in (I_LIMITATION, I_FIN_LIMITATION): draw_carte_in_vitesse(coup.carte, self.num_joueur) elif est_carte_bornes(coup.carte): draw_bornes_val(self.bornes, self.num_joueur) elif est_carte_botte(coup.carte): draw_carte_in_bottes(coup.carte, self.num_joueur, len(self.bottes) - 1, cf and C_RED or None) if coup.carte == I_VEHICULE_PRIORITAIRE or cf: draw_carte_in_bataille(self.carte_bataille(), self.num_joueur) if coup.carte == I_VEHICULE_PRIORITAIRE: draw_carte_in_vitesse(self.carte_vitesse(), self.num_joueur) else: draw_carte_in_bataille(coup.carte, self.num_joueur) if self.points != points_old: draw_points_val(self.points, self.num_joueur) #-------------------------------- # fonctions d'affichage de textes #-------------------------------- def draw_text_in_box(s, xb, yb, wb, hb, c, cf=None, line=0, lines=1): PC_dstr(s, int(xb + (wb - PC_wstr(s))/2), int(yb + (hb - lines*PC_fh)/2 + line*PC_fh), c, cf) def draw_pioche_val(c, cf=None): xb, yb, wb, hb = pos_sabot(0) draw_text_in_box(str(pioche_len), xb, yb, wb, hb, c, cf) def draw_text_jeu(s, num_joueur, pos_x, pos_y, pos_l): xb, yb, wb, hb = pos_jeu(pos_x, pos_y, num_joueur) draw_text_in_box(s, xb, yb, wb, hb, C_BLACK, couleur_joueur(num_joueur), pos_l, 2) def draw_bornes_val(val, num_joueur): draw_text_jeu(str(val), num_joueur, 0, n_cartes_lgn >= 4 or n_cartes_lgn == 2 and 3 or 6, 0) def draw_points_val(val, num_joueur): draw_text_jeu(str(val), num_joueur, n_cartes_lgn == 4 and 3 or n_cartes_lgn == 2, n_cartes_lgn >= 4 or n_cartes_lgn == 2 and 3 or 7, 0) def draw_bornes_tag(num_joueur): draw_text_jeu("km", num_joueur, 0, n_cartes_lgn >= 4 or n_cartes_lgn == 2 and 3 or 6, 1) def draw_points_tag(num_joueur): draw_text_jeu("pts", num_joueur, n_cartes_lgn == 4 and 3 or n_cartes_lgn == 2, n_cartes_lgn >= 4 or n_cartes_lgn == 2 and 3 or 7, 1) #-------------------------------- # fonctions d'affichage de cartes #-------------------------------- def draw_carte(carte, x, y, c=C_WHITE): if carte != None: sprite = SPRITES[est_carte_bornes(carte) and I_50_BORNES or PC_hcol and carte == I_FEU_ROUGE and I_FEU_VERT or carte] if carte == None or sprite[2] >= 0: PC_frect(x, y, carte_w, carte_h, c) if carte != None: if not PC_hcol: PC_drect(x, y, carte_w, carte_h, C_BLACK) code = CODES_CARTES[carte] if est_carte_botte(carte) and PC_wstr("*" + code + "*") <= carte_w: code = "*" + code + "*" y1, y2 = y, y + carte_h show_icon = carte_w >= sprite[0] and carte_h >= sprite[1] if est_carte_bornes(carte): top = PC_hcol and 8 PC_dstr(code, max(0, int(x + (carte_w - sprite[0])/2) + (sprite[0] - PC_wstr(code))//2), y + top + (carte_h - top - PC_fh) // 2, C_BLACK) else: if est_carte_botte(carte): x1 = int(x + (carte_w - round(PC_wstr(code)))/2) x2 = x1 c = C_GREEN_DARK else: x1, x2 = x + (not PC_hcol and 2), x + carte_w - PC_wstr(code) c = est_carte_attaque(carte) and C_RED or C_CYAN hstr = carte_h if PC_hcol: y1 += 1 hstr -= 1 if show_icon: hstr -= HMIN_ICON if hstr >= PC_fh + 1: y1 += 1 hstr -= 1 if hstr >= PC_fh: PC_dstr(code, x1, y1, c) y1 += PC_fh hstr -= PC_fh if hstr >= PC_fh + 1: y2 -= 1 hstr -= 1 if hstr > PC_fh: y2 -= PC_fh hstr -= PC_fh PC_dstr(code, x2, y2, c) if PC_hcol: if carte == I_FEU_VERT: sprite[3][1], sprite[3][3] = C_WHITE, C_GREEN_LIGHT elif carte == I_FEU_ROUGE: sprite[3][1], sprite[3][3] = C_RED, C_WHITE if HMIN_ICON < sprite[1] and sprite[0] > carte_w - 2*PC_fw: y1 = y if show_icon: draw_image(sprite[4], int(x + (carte_w - sprite[0])/2), int(y1 + (y2 - y1 - sprite[1])/2), sprite[0], sprite[1], sprite[3], itransp = sprite[2]) M_CARTE, M_BORD = 1, 2 def draw_carte_in_box(carte, xb, yb, wb, hb, cclear=None, cbord=None, mode=M_CARTE|M_BORD, xm=0): x, y = int(xb + (wb - carte_w)/2), int(yb + (hb - carte_h)/2) if mode & M_CARTE: if carte != None: draw_carte(carte, x, y, C_WHITE) elif cclear: PC_frect(x, y, carte_w, carte_h, cclear) if mode & M_BORD and cbord: xmargin = PC_hcol and min(2, xm) or min(1, xm) ymargin = PC_hcol and 2 or xmargin and 1 PC_drect(x - xmargin, y - ymargin, carte_w + 2*xmargin, carte_h + 2*ymargin, cbord) def draw_carte_defausse(carte): xb, yb, wb, hb = pos_sabot(1) draw_carte_in_box(carte, xb, yb, wb, hb) def draw_carte_in_main(carte, pos, num_joueur, cbord=None, mode=M_CARTE|M_BORD): xb, yb, wb, hb = pos_main(pos) draw_carte_in_box(carte, xb, yb, wb, hb, couleur_joueur(num_joueur), cbord, mode, main_xm) def draw_carte_in_pioche(cf): xb, yb, wb, hb = pos_sabot(0) draw_carte_in_box(None, xb, yb, wb, hb, cf) def draw_carte_in_jeu(carte, num_joueur, pos_x, pos_y, cbord=None): xb, yb, wb, hb = pos_jeu(pos_x, pos_y, num_joueur) draw_carte_in_box(carte, xb, yb, wb, hb, couleur_joueur(num_joueur), cbord, M_CARTE|M_BORD, jeu_xm) def draw_carte_in_bottes(carte, num_joueur, pos, cbord=None): draw_carte_in_jeu(carte, num_joueur, pos % n_cartes_lgn, pos // n_cartes_lgn, cbord) def draw_carte_in_bataille(carte, num_joueur): draw_carte_in_jeu(carte, num_joueur, n_cartes_lgn == 4, n_cartes_lgn >= 4 or n_cartes_lgn == 2 and 2 or 5) def draw_carte_in_vitesse(carte, num_joueur): draw_carte_in_jeu(carte, num_joueur, n_cartes_lgn == 4 and 2 or n_cartes_lgn == 2, n_cartes_lgn >= 4 or n_cartes_lgn == 2 and 2 or 4) #---------------------------------------------- # fonctions d'affichage de zones de l'interface #---------------------------------------------- # * la main : #------------ def redraw_cadre_zone(xb, yb, wb, hb, c): PC_drect(xb, yb, wb, hb, c) PC_show() def draw_cadre_zone(i, num_joueur): if i >= 0: xb, yb, wb, hb = i * col_w + 1, 1, col_w - 2, ysep - 2 elif i == SABOT: xb, yb, wb, hb = xsep + 1, ysep + 1, PC_sw - xsep - 2, PC_sh - ysep - 2 else: xb, yb, wb, hb = 1, ysep + 1, xsep - 2, PC_sh - ysep - 2 redraw_cadre_zone(xb, yb, wb, hb, C_BLACK) return xb, yb, wb, hb def draw_main_init(num_joueur): if PC_hcol: clear_main(num_joueur) else: PC_frect(0, ysep, xsep, 1, C_BLACK) PC_frect(num_joueur * col_w, ysep, col_w, 1, C_WHITE) PC_frect(xsep, ysep, PC_sw - xsep, 1, C_BLACK) def clear_main(num_joueur): PC_frect(0, ysep, xsep, PC_sh - ysep, couleur_joueur(num_joueur)) def redraw_main(carte, pos, num_joueur): if num_joueur == show_main_joueur: draw_carte_in_main(carte, pos, num_joueur) def draw_main(main, num_joueur): if PC_hcol: clear_main(num_joueur) for i in range(len(main)): carte = main[i] if carte != None: redraw_main(carte, i, num_joueur) def redraw_allonge_question_in_main(y, c): PC_dstr("Allonge / Extension ?", 0, y, c) PC_show() def milieu(x1, x2): return int((x1 + x2) / 2) def draw_allonge_question_in_main(num_joueur, infos_joueur): global show_main_joueur show_main_joueur = num_joueur cb = couleur_joueur(num_joueur) it = PC_sh - ysep - carte_h >= 2*PC_fh if it == 0: clear_main(num_joueur) y = milieu(ysep, PC_sh - PC_fh) else : y = ysep + milieu(0, (PC_sh - ysep - carte_h - PC_fh) / 2) PC_frect(0, y, xsep, PC_fh, cb) redraw_allonge_question_in_main(y, C_BLACK) return it, y def clear_allonge_question(num_joueur, infos_joueur, it, y): if it: clear_main(num_joueur) else : PC_frect(0, y, xsep, PC_fh, couleur_joueur(infos_joueur.num_joueur)) draw_main(infos_joueur.main_affichable, num_joueur) PC_show() # * les zones de jeu : #--------------------- def show(infos_joueurs): if not PC_hcol: PC_clr() for k in range(nbr_joueurs): infos_joueur = infos_joueurs[k] if PC_hcol: PC_frect(round(k * col_w), 0, round(col_w), ysep, couleur_joueur(k)) elif k: PC_frect(round(k * col_w), 0, 1, ysep, C_BLACK) draw_bornes_val(infos_joueur.bornes, k) draw_bornes_tag(k) draw_points_val(infos_joueur.points, k) draw_points_tag(k) if not PC_hcol: PC_frect(xsep, ysep, 1, PC_sh - ysep, C_BLACK) else: PC_frect(xsep, ysep, PC_sw - xsep, PC_sh - ysep, C_GRAY_LIGHT) draw_carte_in_pioche(C_GRAY_DARK) draw_pioche_val(C_WHITE) PC_show() # * le sabot : #------------- def redraw_sabot(): if not pioche_len or pioche_len % 10 == 9: draw_carte_in_pioche(pioche_len and C_GRAY_DARK or (PC_hcol and C_GRAY_LIGHT or C_WHITE)) cf = None else: cf = C_GRAY_DARK draw_pioche_val(pioche_len and C_WHITE or C_BLACK, cf) #---------------------------------------------- # fonctions d'affichage des touches de controle #---------------------------------------------- def draw_help_title(c): PC_dstr("CONTROLES CLAVIER - KEYBOARD CONTROLS", 0, 0, c) def draw_help_lines(y, hentry, key=None, descr=None, help_fr=None, help_en=None): if key and hentry >= PC_fh: PC_dstr(key + " " + descr, 0, y, C_BLACK) y += PC_fh hentry -= PC_fh if help_fr and hentry >= PC_fh: PC_dstr(help_fr, 0, y, PC_hcol and C_GREEN_DARK or C_BLACK) y += PC_fh hentry -= PC_fh if help_en and hentry >= PC_fh: PC_dstr(help_en, 0, y, PC_hcol and C_MAGENTA or C_BLACK) y += PC_fh hentry -= PC_fh return y + hentry def draw_help(): global casio_delay draw_help_title(C_BLACK) casio_key = "[AC/ON]" casio_2keys = casio_key + casio_key hentry = (PC_sh - PC_fh) // (keybreak_mode and 3 or 6) lentry = min(3, hentry // PC_fh) y = draw_help_lines(PC_fh + hentry - lentry*PC_fh, hentry, keybreak_mode and casio_key or keys2_mode and "[annul]" or "[>]", "Suivant-Next", "carte/zone suivante", "next card/destination") if not keybreak_mode and not keys2_mode: y = draw_help_lines(y, hentry, "[<]", "Precedent-Previous", "carte/zone precedente", "previous card/destination") y = draw_help_lines(y, hentry, keybreak_mode and casio_2keys or keys2_mode and "[entrer]" or "[^]", "Valider-Validate", "valide carte/zone", "validate card/zone") if not keybreak_mode and not keys2_mode: y = draw_help_lines(y, hentry, "[v]", "Defausser-Discard / Annuler-Cancel", "defausse carte / annule coup", "discard card / cancel move") y = draw_help_lines(y, hentry, "[esc]", "Quitter-Quit") y = draw_help_lines(y, hentry, None, None, "Tape " + (keybreak_mode and casio_2keys or "une touche") + " ...", "Type " + (keybreak_mode and casio_2keys or "a key") + " ...") PC_show() if keybreak_mode: try: while 1: pass except KeyboardInterrupt: try: draw_help_title(C_RED) PC_show() casio_delay = 0 while 1: casio_delay += 1 except KeyboardInterrupt: casio_delay = int(casio_delay * 1.1) else: key, click = None, None while not (key or click): key, click = PC_gwkey(), PC_click() if key: PC_wnokey() if click: PC_wnoclick() #--------------------------------------------- # fonctions de gestion des touches de controle #--------------------------------------------- pos_choix = 0 def PC_gwkey(): if PC_hgkey: return PC_gkey() else: return PC_wkey() if keybreak_mode: def choix_allonge(num_joueur, infos_joueur): it, y = draw_allonge_question_in_main(num_joueur, infos_joueur) try: pass except KeyboardInterrupt: try: k = 0 redraw_allonge_question_in_main(y, C_RED) while 1: k += 1 if k == casio_delay: break except KeyboardInterrupt: return 1 return 0 def choix_clavier_destination(num_joueur, adversaire=0): if adversaire: destinations = list(range(nbr_joueurs)) destinations.remove(num_joueur) else: destinations = [num_joueur] destinations.extend((SABOT, MAIN)) i_pos = 0 while 1: try: pos = destinations[i_pos] xb, yb, wb, hb = draw_cadre_zone(pos, num_joueur) c = couleur_joueur((pos, num_joueur)[pos == MAIN]) while 1: pass except KeyboardInterrupt: try: k = 0 redraw_cadre_zone(xb, yb, wb, hb, C_RED) PC_drect(xb, yb, wb, hb, c) while 1: k += 1 if k >= casio_delay: break except: return pos redraw_cadre_zone(xb, yb, wb, hb, c) i_pos = (i_pos + 1) % len(destinations) def choix_clavier_carte(main, num_joueur, infos_joueurs): global pos_choix infos_joueur, c = infos_joueurs[num_joueur], couleur_joueur(num_joueur) while 1: try: draw_carte_in_main(None, pos_choix, num_joueur, C_BLACK, M_BORD) PC_show() while 1: pass except KeyboardInterrupt: try: k = 0 draw_carte_in_main(None, pos_choix, num_joueur, C_RED, M_BORD) PC_show() draw_carte_in_main(None, pos_choix, num_joueur, c, M_BORD) while 1: k += 1 if k == casio_delay: break except: carte = main[pos_choix] if carte != None and len(infos_joueur.main) >= TAILLE_MAIN: destination = choix_clavier_destination(num_joueur, est_carte_attaque(carte)) else: destination = num_joueur origine = carte == None and SABOT or num_joueur coup = c_coup(origine, carte, destination) if not coup.invalide(nbr_joueurs) and not infos_joueur.coup_invalide(coup) \ and (destination == SABOT or destination == num_joueur or not infos_joueurs[destination].coup_invalide(coup)): return coup draw_carte_in_main(None, pos_choix, num_joueur, c, M_BORD) pos_choix = (pos_choix + 1) % TAILLE_MAIN else: def is_previous_key(key): return key in (K_LEFT, K_4) def is_next_key(key): return key in (keys2_mode and (K_ESC,) or (K_RIGHT, K_6)) def is_validation_key(key): return key in (K_UP, K_ENTER, K_ENTER2, K_5, K_SHIFT) def is_more_key(key): return key in (K_ADD, K_MUL) def is_defausse_cancel_key(key): return key in (K_DOWN, K_DEL, K_SUB, K_SUB2, K_DIV, K_DIV2, K_2, K_ALPHA) def is_exit_key(key): return not keys2_mode and key in (K_ESC, K_0, K_ON, K_APPS) def get_zone(x, y): if y >= ysep: return x >= xsep and SABOT or MAIN else: return int(x / col_w) def get_main_pos(x, y): for pos in range(TAILLE_MAIN): xb, yb, wb, hb = pos_main(pos) if xb <= x and x <= xb + wb - 1 and yb <= y and y <= yb + hb - 1: return pos return None def choix_allonge(num_joueur, infos_joueur): it, y = draw_allonge_question_in_main(num_joueur, infos_joueur) key, click = None, None while not is_validation_key(key) and not is_defausse_cancel_key(key) and not is_exit_key(key) and click == None: key, click = PC_gwkey(), PC_click() clear_allonge_question(num_joueur, infos_joueur, it, y) if is_exit_key(key): return None if is_validation_key(key) or is_defausse_cancel_key(key) or is_next_key(key): return is_validation_key(key) return get_zone(*click) in (MAIN, num_joueur) def choix_clavier_destination(num_joueur, adversaire=0, defausse=0, showkeypos=1): if adversaire: destinations = list(range(nbr_joueurs)) destinations.remove(num_joueur) else: destinations = [num_joueur] if defausse: destinations += [SABOT, MAIN] key, i_joueur, delta = None, num_joueur, 1 i_pos = 0 pos_click, click, pos_old = None, None, None while 1: pos = destinations[i_pos] if showkeypos: xb, yb, wb, hb = draw_cadre_zone(pos, num_joueur) if key: PC_wnokey() if click: PC_wnoclick() key, click = PC_gwkey(), PC_click() if showkeypos: PC_drect(xb, yb, wb, hb, couleur_joueur(pos)) if key: showkeypos=1 if click: pos_click = get_zone(click[0], click[1]) if pos_click in destinations: pos, i_pos = pos_click, destinations.index(pos_click) else: return MAIN if is_validation_key(key) or pos_click != None: return pos elif is_defausse_cancel_key(key): return MAIN elif is_exit_key(key): return None i_pos = (i_pos + is_next_key(key) - is_previous_key(key)) % len(destinations) def choix_clavier_carte(main, num_joueur, infos_joueurs): global pos_choix key, infos_joueur = None, infos_joueurs[num_joueur] c = couleur_joueur(num_joueur) pos_click, click, pos_old = None, None, None while 1: draw_carte_in_main(None, pos_choix, num_joueur, C_BLACK, M_BORD) PC_show() if key: PC_wnokey() if click: PC_wnoclick() key, click = PC_gwkey(), PC_click() if click: pos_click = get_main_pos(click[0], click[1]) if pos_click != None: pos_choix = pos_click else: pos_click = None if is_exit_key(key): return None carte, coup = main[pos_choix], None action_validation = is_validation_key(key) or pos_click != None if is_more_key(key) and len(infos_joueur.main) < TAILLE_MAIN or action_validation \ or is_defausse_cancel_key(key) and carte != None: origine, destination = num_joueur, num_joueur if is_more_key(key): origine, carte = SABOT, None elif is_defausse_cancel_key(key): destination = SABOT if carte != None : if action_validation and len(infos_joueur.main) >= TAILLE_MAIN: if not keys2_mode and est_carte_attaque(carte) and nbr_joueurs == 2 and pos_click == None: destination = 1 - num_joueur elif est_carte_attaque(carte) or pos_click != None or keys2_mode: if pos_click != None and pos_click != pos_old and pos_old != None: draw_carte_in_main(None, pos_old, num_joueur, main_xm > 0 and c or C_WHITE, M_BORD) draw_carte_in_main(None, pos_choix, num_joueur, C_RED, M_BORD) PC_show() PC_wnokey() PC_wnoclick() destination = choix_clavier_destination(num_joueur, est_carte_attaque(carte), pos_click != None or keys2_mode, pos_click == None) if destination == None: return None else: origine = SABOT coup = c_coup(origine, carte, destination) if coup and not coup.invalide(nbr_joueurs) and not infos_joueur.coup_invalide(coup) \ and (destination == SABOT or destination == num_joueur or not infos_joueurs[destination].coup_invalide(coup)): print(coup.to_str()) return coup pos_old, pos_choix = pos_choix, (pos_choix + is_next_key(key) - is_previous_key(key)) % TAILLE_MAIN if pos_old != None and pos_old != pos_choix: draw_carte_in_main(None, pos_old, num_joueur, main_xm > 0 and c or C_WHITE, M_BORD) #------------------------- # fonctions pour la pioche #------------------------- def melange_liste(lst): n = len(lst) for i in range(n - 1): j = randint(i, n - 1) lst[i], lst[j] = lst[j], lst[i] def permute_liste(lst, d): n = len(lst) for istart in range(0, n, d): iend = min(istart + d, n) lst[istart:iend] = [lst[iend - 1]] + lst[istart:iend - 1] #---------------------- # fonctions pour les IA #---------------------- def traite_coup_all(coup, num_joueur, joueurs, infos_joueurs, pos = -1): for i in range(nbr_joueurs): # censure de la carte tiree pour les autres IAs tcoup = coup.origine == SABOT and coup.destination != i and c_coup(coup.origine, None, coup.destination) or coup joueurs[i].traite_coup(tcoup) infos_joueurs[i].traite_coup(tcoup, 1, pos) #-------------------- # fonction principale #-------------------- def kb_partie(classes_joueurs, show_help=0): global col_w, y1, n_cartes_lgn, n_cartes_col, carte_w, carte_h, cartebox_w, cartebox_h, i_display_mode, ysep, xsep global joueurs_col, show_main_joueur, pioche_len global main_xm, jeu_xm, pioche_xm, TAILLE_MAIN, nbr_joueurs TAILLE_MAIN = 7 POINTS_OBJECTIF = 9000 sep1, sep2 = "=" * 21, "-" * 20 if show_help: PC_init() draw_help() nbr_joueurs = len(classes_joueurs) show_main_joueur = 0 if PC_hcol: joueurs_col = tuple([hsv2rgb(2/3 - k / nbr_joueurs, .4, 1) for k in range(nbr_joueurs)]) carte_w = WMAX_ICON col_w = PC_sw / nbr_joueurs if not PC_hcol: col_w -= nbr_joueurs - 1 n_cartes_lgn = max(1, (col_w - (PC_hcol and 1 or 2)) // (carte_w + 1)) n_cartes_lgn = (n_cartes_lgn == 3) and 2 or min(n_cartes_lgn, 4) if col_w - 1 - n_cartes_lgn*carte_w >= 2*n_cartes_lgn: carte_w += 2 cartebox_w = (col_w - 1) // n_cartes_lgn carte_w = min(carte_w, cartebox_w) n_cartes_col = 2 if n_cartes_lgn <= 2: n_cartes_col += 2 if n_cartes_lgn <= 1: n_cartes_col += 4 ysep = round(n_cartes_col * (PC_sh - (PC_hcol and 2 or 3)) / (n_cartes_col + 1)) xsep = round(TAILLE_MAIN * (PC_sw - 2) / (TAILLE_MAIN + 2)) + 1 main_xm = (xsep - TAILLE_MAIN*carte_w) // (TAILLE_MAIN+1) pioche_xm = (PC_sw - xsep - 2*carte_w) // 3 jeu_xm = (col_w - n_cartes_lgn*carte_w) // (n_cartes_lgn + 1) cartebox_h = (ysep - 1) // n_cartes_col carte_h = max(PC_fh, min(HMIN_ICON + 2*PC_fh + 4, int((ysep - 1) / n_cartes_col - 1))) joueurs = [] for num_joueur in range(nbr_joueurs): c_joueur = classes_joueurs[num_joueur] joueurs.append(c_joueur(num_joueur, nbr_joueurs, POINTS_OBJECTIF)) infos_joueurs = [c_jeujoueur(num_joueur, nbr_joueurs, POINTS_OBJECTIF, not PC_dirt) for num_joueur in range(nbr_joueurs)] fin_de_partie = 0 i_manche = 0 for joueur in joueurs: if joueur.nom_groupe: for obj in joueurs + infos_joueurs: obj.rejoint_groupe(joueur.num_joueur, joueur.nom_groupe) print(sep1) print("Debut de partie a {:d}pts".format(POINTS_OBJECTIF)) print(sep2) for joueur in joueurs: print(joueur.id_str()) print(sep1) pioche_r = [I_CAMION_CITERNE, I_VEHICULE_INCREVABLE, I_AS_VOLANT, I_VEHICULE_PRIORITAIRE] # cartes bottes, 1 de chaque pioche_r += [I_PANNE_ESSENCE, I_CREVAISON, I_ACCIDENT]*3 + [I_LIMITATION,]*4 + [I_FEU_ROUGE,]*5 # cartes d'attaque pioche_r += [I_POMPE_ESSENCE, I_ROUE_SECOURS, I_REPARATIONS, I_FIN_LIMITATION]*6 + [I_FEU_VERT,]*14 # cartes de parade pioche_r += [I_25_BORNES, I_50_BORNES, I_75_BORNES]*10 + [I_100_BORNES,]*12 + [I_200_BORNES,]*4 while not fin_de_partie: # nouvelle partie i_manche += 1 bornes_arrivee_allonge = 1000 bornes_arrivee = nbr_joueurs <= 3 and 700 or bornes_arrivee_allonge allonge_demandee = 0 melange_liste(pioche_r) for i_pioche in range(nbr_joueurs): if fin_de_partie: break print("Manche {:d} Pioche {:d}".format(i_manche, i_pioche + 1)) print(sep2) permute_liste(pioche_r, nbr_joueurs) pioche = list(pioche_r) pioche_len = len(pioche) for obj in joueurs + infos_joueurs: obj.nouvelle_manche(pioche_len, TAILLE_MAIN, bornes_arrivee) show(infos_joueurs) draw_main_init(show_main_joueur) PC_show() for k in range(TAILLE_MAIN - 1): for num_joueur in range(nbr_joueurs): carte = pioche.pop() pioche_len -= 1 coup = c_coup(SABOT, carte, num_joueur) traite_coup_all(coup, num_joueur, joueurs, infos_joueurs) PC_show() fin_de_manche = 0 while pioche_len and not fin_de_manche and not fin_de_partie: # nouvelle manche for num_joueur in range(nbr_joueurs): if fin_de_manche or fin_de_partie: break PC_show() joueur = joueurs[num_joueur] infos_joueur = infos_joueurs[num_joueur] joueur_dest = None infos_joueur_dest = None tour_termine = 0 tour_commence = 0 while not tour_termine and (pioche_len or len(infos_joueur.main) >= TAILLE_MAIN): useposmain = 0 if tour_commence and len(infos_joueur.main) < TAILLE_MAIN: coup = c_coup(SABOT, None, num_joueur) else: coup = joueur.decide_coup() if coup == None: if num_joueur != show_main_joueur: show_main_joueur = num_joueur draw_main(infos_joueur.main_affichable, num_joueur) PC_show() PC_wnokey() PC_wnoclick() coup = choix_clavier_carte(infos_joueur.main_affichable, num_joueur, infos_joueurs) useposmain = 1 if coup == None: fin_de_partie = 1 break tour_commence = 1 coup_invalide = coup.invalide(nbr_joueurs) if not coup_invalide: if coup.destination != SABOT: joueur_dest = joueurs[coup.destination] infos_joueur_dest = infos_joueurs[coup.destination] coup_invalide = infos_joueur.coup_invalide(coup) if not coup_invalide and joueur_dest: coup_invalide = infos_joueur_dest.coup_invalide(coup) if coup_invalide: print("Coup invalide : ", coup.to_str()) print(infos_joueur.to_str()) if coup.destination >= 0 and coup.destination != num_joueur: print(infos_joueurs[coup.destination].to_str()) coup.destination = SABOT coup.origine = num_joueur if coup.carte == None or not coup.carte in infos_joueur.main: coup.carte = choice(infos_joueur.main) else: if coup.origine == SABOT: coup.carte = pioche.pop() pioche_len -= 1 if coup.destination != SABOT: joueur_dest = joueurs[coup.destination] infos_joueur_dest = infos_joueurs[coup.destination] if coup.destination != SABOT and est_carte_botte(coup.carte): back_vitesse = list(infos_joueur.pile_vitesse) back_bataille = list(infos_joueur.pile_bataille) # information toutes IA du dernier coup traite_coup_all(coup, num_joueur, joueurs, infos_joueurs, not useposmain and -1 or pos_choix) if coup.destination != SABOT and est_carte_botte(coup.carte): if len(infos_joueur.pile_vitesse) < len(back_vitesse): infos_joueur.traite_coup(c_coup(None, back_vitesse[-1], SABOT)) PC_show() if len(infos_joueur.pile_bataille) < len(back_bataille): infos_joueur.traite_coup(c_coup(None, back_bataille[-1], SABOT)) PC_show() PC_show() if not allonge_demandee and bornes_arrivee < bornes_arrivee_allonge and joueur_dest \ and infos_joueur_dest.bornes == bornes_arrivee: allonge_demandee = 1 pari_allonge = joueur_dest.pari_allonge(bornes_arrivee_allonge) if pari_allonge == None: if num_joueur != show_main_joueur: show_main_joueur = num_joueur draw_main(infos_joueur.main_affichable, num_joueur) PC_show() PC_wnokey() PC_wnoclick() pari_allonge = choix_allonge(num_joueur, infos_joueur) if pari_allonge == None: fin_de_partie = 1 if pari_allonge: bornes_arrivee = bornes_arrivee_allonge print(infos_joueur.id_str() + " allonge {:04d}km".format(bornes_arrivee)) for obj in joueurs + infos_joueurs: obj.allonge(joueur_dest, bornes_arrivee) else: break fin_de_manche = infos_joueur.victoire_manche() tour_termine = coup.origine != SABOT and not est_carte_botte(coup.carte) PC_clrevnts() for infos_joueur2 in infos_joueurs: if infos_joueur2.victoire_manche(): fin_de_manche = 1 break print(sep2) for infos_joueur in infos_joueurs: print(infos_joueur.id_str() + " {:04d}km".format(infos_joueur.bornes) + (infos_joueur.victoire_manche() and " Victoire" or "")) print(sep2) for obj in joueurs + infos_joueurs: obj.fin_manche([infos_joueurs[i].bornes for i in range(nbr_joueurs)], pioche_len) print(sep2) score_gagnant, n_gagnants = 0, 0 for infos_joueur in infos_joueurs: t = infos_joueur.victoire_tournoi() if t and i_pioche + 1 == nbr_joueurs: fin_de_partie = 1 if infos_joueur.points > score_gagnant: score_gagnant = infos_joueur.points n_gagnants = 1 elif infos_joueur.points == score_gagnant: n_gagnants += 1 print(infos_joueur.id_str() + " {:05d}pt".format(infos_joueur.points) + " s"[infos_joueur.points > 1] + (t and " It's over {:d}".format(POINTS_OBJECTIF) or "")) print(sep1) exaequo = n_gagnants > 1 _print("Fin de partie") for k in range(nbr_joueurs): infos_joueur = infos_joueurs[k] if infos_joueur.points == score_gagnant: _print(exaequo and "Ex aequo" or "Gagnant", infos_joueur.id_str()) if not exaequo: _print('Le mot du gagnant:\n"' + joueurs[k].msg_joueur + '"')