Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » [Bêta] PythonExtra.
Lephenixnoir Hors ligne Administrateur Points: 25566 Défis: 174 Message

[Bêta] PythonExtra.

Posté le 29/10/2022 09:49

PythonExtra est un add-in Python alternatif pour (à ce stade) Graph 35+E II, Prizm et Graph 90+E. L'objectif est de fournir plus de fonctionnalités : modules standard, getkey(), fonctions de dessin plus performantes, etc.

Version Bêta 0.4 (Changelog)
Graph 35+E II / Prizm / Graph 90+E / Math+ / ClassPad : PythonExtra-pe-0.4.0-beta.zip


Aperçu de PythonExtra sur Graph 90+E. (Cliquez pour agrandir)


Aperçu de PythonExtra sur Graph 35+E II (FxPyEdit par Mb88)

Description sommaire des fonctionnalités :
  • Compile pour Graph 90+E (fx-CG 10/20/50) et Graph 35+E II (fx-9860G III)
  • Peu de RAM sur Graph 35+E II (c'est difficile d'en trouver sur ce modèle)
  • Un shell pas trop mal (saisie rapide, scrolling) avec de bonnes performances
  • Plein de modules standard
    • array, builtins, cmath, collections, io, math, random, struct, sys, time
  • Le module spécifique CASIO : casioplot (fidèle à part sur les polices)
  • Un nouveau module gint avec les fonctionnalités avancées de gint :
    • Pour l'instant, une bonne partie de <gint/display.h> et <gint/keyboard.h>
    • Donc getkey() (attente de touche) ainsi que keydown() (test instantané) !
    • Et des fonctions de dessin rapides comme dline() ou drect()

Le plan actuel :
  • Être sensiblement compatible avec l'appli Python officielle.
  • Pousser les fonctionnalités ajoutées pour vraiment relever le niveau de Python !
  • Si du temps de développement se débloque : support autres Graph mono (pas de promesses).

Updates et screenshots à venir. Je n'ai pas l'intention d'implémenter un million de fonctionnalités, juste ce qu'il faut pour s'assurer que ça ne finisse pas mal documenté et non maintenu comme CasioPython.

Dépôt Git : https://gitea.planet-casio.com/Lephenixnoir/PythonExtra
PythonExtra est notamment possible grâce à l'aide précieuse de Mb88.

Comparaison directe

Dans l'exemple ci-dessous (réalisé par Mb88), un Flappy Bird déjà bien optimisé (dessin partiel etc, à gauche) est accéléré un bon gros coup en utilisant PythonExtra et le module gint pour le dessin (à droite).


Contexte historique

Aux journées APMEP 2022, redgl0w racontait comment le port MicroPython pour Numworks n'était finalement pas super difficile. Moi je parlais de comment un port maison résoudrait le problème de getkey(), et Critor m'a convaincu d'essayer sur-le-champ.

En fin de compte, j'ai clôné MicroPython Dimanche à midi et à 1 heure du matin j'avais un port fonctionnel avec getkey() sur ma Graph 90+E (que j'ai d'ailleurs montré à CASIO Lundi, pour la démo). Comme quoi, des fois ça marche tout seul !

(Enfin, le début marche tout seul. Faire une bonne UI et gérer tous les détails ensuite c'est une autre paire de manches !)

Fichier joint


Précédente 1, 2, 3 ··· 10 ··· 20 ··· 27, 28, 29, 30
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 25/11/2025 09:45 | #


Comme je disait il fonctionne sur l'appli officiel CASIO mais pas avec Python extra
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 26/11/2025 09:04 | #


nouvelle version de micropython j'ai trouvé 2 fichiers que j'ai mis en pièce jointe e comme il n'est pas possible de s'inscrire sur la forge de planet-casio
lien vers la version stable
lien vers le fichier en developpement de micropython
Slyvtt Hors ligne Maître du Puzzle Points: 2776 Défis: 17 Message

Citer : Posté le 26/11/2025 14:18 | #


Ce n'est pas un probleme de version de micropython. PE embarque la version 1.25 donc pas de soucis.

Par contre on sait que l'on ne peut pas faire tourner des programmes trop gourmands en mémoire sur la G35+EII car on a très peu de RAM disponible à allouer. Et là il n'y a pas de miracle possible.
There are only 10 types of people in the world: Those who understand binary, and those who don't ...
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 26/11/2025 15:43 | #


je pense pour ma part que CASIO utillise la mémoire de stockage et pas la RAM ce quidonne plus de puissance à leur application (le fichier EACTWORK.tmp)
Lephenixnoir Hors ligne Administrateur Points: 25566 Défis: 174 Message

Citer : Posté le 26/11/2025 18:10 | #


Non EACTWORK n'a absolument rien à voir avec cette affaire. CASIO utilise bien un tas plus gros, dans lequel on peut tenter de piocher, mais ça nous expose à des dépendances de version d'OS donc ce n'est pas encore codé.
Mon graphe (27 Juin): (MQ || Rogue Life) ; serial gint ; passe gint 3 ; Azur ; ...) || (shoutbox v5 ; v5)
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 27/11/2025 10:00 | #


Comment se fait-il que mon programme (et ces dépendances) fonctionnent sur l'appli Casio et pas sur PythonExtra
Comment allez-vous y prendre pour piocher dans le tas plus gros de CASIO
va t-il être facile sachant qui il ya eu une MàJ de l'OS il y pas longtemps
Graph 90+E 3.81 Correction d’un bug mineur 29/10/2025
et
Graph 35+E II 3.71 Correction d’un bug mineur 29/10/2025
Lephenixnoir Hors ligne Administrateur Points: 25566 Défis: 174 Message

Citer : Posté le 27/11/2025 11:21 | #


Comment ça se fait ? PythonExtra définit un tas plus petit.

Comment va-t-on s'y prendre ? En déclarant une arène supplémentaire.

La mise à jour récente de l'OS, qui est mineure, n'aura probablement pas d'impact.
Mon graphe (27 Juin): (MQ || Rogue Life) ; serial gint ; passe gint 3 ; Azur ; ...) || (shoutbox v5 ; v5)
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 27/11/2025 13:30 | #


C'est c programme (uno_main) et ese dépendances qui fonctionnent uniquement sur l'appli CASIO officiel sur ma graph 35 + E II
ia_learning.py
masquer
import urandom1 as r
# --- Paramètres du Q-Learning ---
ALPHA = 0.1 # Taux d'apprentissage (Learning Rate)
GAMMA = 0.9 # Facteur de rabais (Discount Factor)
EPSILON = 0.01 # Taux d'exploration (Exploration Rate)
# La Q-Table est stockee en memoire, elle est perdue a la fin de l'execution
Q_TABLE = {}
ACTIONS = ['JOUER', 'PIOCHER']
def obtenir_etat(main, carte_defausse, game_type):
  if game_type == 2:
    return generer_etat_dos(main, carte_defausse)
  elif game_type == 3:
    return generer_etat_no_mercy(main, carte_defausse, game_type)
  elif game_type == 4:
    return generer_etat_zero(main, carte_defausse)
  elif game_type == 5:
    return generer_etat_extreme(main, carte_defausse)
  else:
    return generer_etat_uno(main, carte_defausse, game_type)
def generer_etat_uno(main, carte_defausse, game_type):
  taille_main = len(main)
  couleur_defausse = carte_defausse[0]
  valeur_defausse = carte_defausse[1]
  # Simplification de la valeur de la carte de defausse pour reduire l'espace d'etat
  if valeur_defausse.isdigit():
    valeur_simplifiee = 'DIGIT'
  elif valeur_defausse in ['+2', 'I', 'PTT']:
    valeur_simplifiee = valeur_defausse
  elif valeur_defausse in ['W', '+4']:
    valeur_simplifiee = 'WILD'
  else:
    valeur_simplifiee = 'AUTRE'
  # Le mode NoMerci est traite comme un mode UNO simple par defaut
  mode_jeu='CLASSIC'
  return (mode_jeu, taille_main, couleur_defausse, valeur_simplifiee)
def generer_etat_zero(main, carte_defausse):
  etat = generer_etat_uno(main, carte_defausse, 4)
  return ('ZERO', etat[1], etat[2], etat[3])
def generer_etat_extreme(main, carte_defausse):
    etat = generer_etat_uno(main, carte_defausse, 5)
    return ('EXTREME', etat[1], etat[2], etat[3])
def generer_etat_dos(main, defausse_piles):
  taille_main = len(main)  
  carte_p1 = defausse_piles[0][-1]
  carte_p2 = defausse_piles[1][-1]  
  couleur_p1 = carte_p1[0]
  valeur_p1 = carte_p1[1]  
  couleur_p2 = carte_p2[0]
  valeur_p2 = carte_p2[1]  
  # Simplification de la valeur de la carte de defausse (seulement chiffre ou W)
  val_p1_simplifiee = 'DIGIT' if valeur_p1.isdigit() else valeur_p1
  val_p2_simplifiee = 'DIGIT' if valeur_p2.isdigit() else valeur_p2
  return ('DOS', taille_main, couleur_p1, val_p1_simplifiee, couleur_p2, val_p2_simplifiee)
def initialiser_q_valeur(etat, action):
  if etat not in Q_TABLE:
    Q_TABLE[etat] = {}
    if action not in Q_TABLE[etat]:
      Q_TABLE[etat][action] = 0.0
def choisir_action_apprentissage(etat, actions_legales, main):
  if r.random() < EPSILON:
   # Exploration: choisir une action aleatoire
    if actions_legales:
      return r.choice(actions_legales)
    else:
      return ('PIOCHER',)
  else:
  # Exploitation: choisir la meilleure action (la plus haute Q-valeur)
    meilleure_action = None
    meilleure_q_valeur = -float('inf')
    # 1. Tester l'action PIOCHER
    initialiser_q_valeur(etat, ('PIOCHER',))
    q_piocher = Q_TABLE[etat][('PIOCHER',)]
    meilleure_action = ('PIOCHER',)
    meilleure_q_valeur = q_piocher
    # 2. Tester toutes les actions JOUER legales
    for action in actions_legales:
      # L'action est un tuple (couleur, valeur, couleur_choisie) ou (couleur, valeur, pile_cible)
      # Normalisons l'action pour la Q-table (ex: ('R', '1') ou ('N', '+4', 'B'))
      # Action normalisee: tuple contenant (couleur, valeur) + un eventuel choix (couleur ou pile)
      action_cle = action
      initialiser_q_valeur(etat, action_cle)
      q_jouer = Q_TABLE[etat][action_cle]
      if q_jouer > meilleure_q_valeur:
        meilleure_q_valeur = q_jouer
        meilleure_action = action_cle
      return meilleure_action
def mettre_a_jour_q_table(etat_precedent, action_precedente, recompense, nouvel_etat, actions_legales_nouvel_etat):
  initialiser_q_valeur(etat_precedent, action_precedente)
  # 1. Calculer la Q-valeur maximale pour le nouvel etat
  max_q_nouvel_etat = 0  
  # 1.1 Inclure l'action PIOCHER dans les Q-valeurs maximales potentielles
  initialiser_q_valeur(nouvel_etat, ('PIOCHER',))
  max_q_nouvel_etat = Q_TABLE[nouvel_etat][('PIOCHER',)]    
  # 1.2 Verifier toutes les actions de JOUER
  for action in actions_legales_nouvel_etat:
    action_cle = action
    initialiser_q_valeur(nouvel_etat, action_cle)
    q_val = Q_TABLE[nouvel_etat][action_cle]    
    if q_val > max_q_nouvel_etat:
      max_q_nouvel_etat = q_val
  # 2. Appliquer la formule de Bellman (Q-Learning)
  ancienne_q=Q_TABLE[etat_precedent][action_precedente]
  nouvelle_q=(1-ALPHA) * ancienne_q+ALPHA*(recompense+GAMMA*max_q_nouvel_etat)
  Q_TABLE[etat_precedent][action_precedente]=nouvelle_q
def charger_q_table():
  global Q_TABLE
  # Pas de persistance, on retourne la table actuelle
  return Q_TABLE
def sauvegarder_q_table(q_table):
  # Pas de persistance.
  pass
def obtenir_recompense(taille_main_apres, taille_main_avant):
  if taille_main_apres < taille_main_avant:
    return 1
  elif taille_main_apres > taille_main_avant:
    return -10
  else:
    # A du piocher mais n'a pas pu jouer, ou a joue une carte "inutile"
    return -5

uno_classique.py
masquer
import urandom1 as r
import trys as t
from uno_rules import Colors, Val_spe, Val_digits, W_cards, W_count, Nbr_cards_init, piocher_carte_aleatoire, appliquer_penalite, recycler_defausse, calculer_score
from ia_learning import charger_q_table, sauvegarder_q_table, generer_etat_uno, choisir_action_apprentissage, obtenir_recompense, mettre_a_jour_q_table
# Charger la Q-Table au debut du script
Q_TABLE = charger_q_table()
HISTORIQUE_IA = []
def creer_paquet_classique():
  paquet = []
  # Cartes chiffrees (0-9)
  for couleur in Colors:
    # Un seul '0' par couleur
    paquet.append(('0',couleur,"0"))
    # Deux de chaque chiffre (1-9)
    for valeur in Val_digits[1:]:
      paquet.append((valeur,couleur,"0"))
      paquet.append((valeur,couleur,"1"))
  # Cartes d'action (+2, I, PTT)
  for couleur in Colors:
    for valeur in Val_spe:
      paquet.append((valeur,valeur,"0"))
      paquet.append((valeur,couleur,"1"))
  # Cartes sauvages (W, +4)
  for valeur in W_cards:
    for _ in range(W_count): # 4 cartes de chaque type (W, +4)
      paquet.append((valeur,"","0"))
  return r.shuffle(paquet)
def verifier_validite_uno_classique(carte_jouee, carte_defausse_tuple, couleur_actuelle):
  couleur_jouee, valeur_jouee = carte_jouee
  # Les cartes Joker ('N') sont toujours valides
  if couleur_jouee == 'N':
    return True
  # La carte doit correspondre a la couleur actuelle ou a la valeur de la carte du dessus
  return (couleur_jouee == couleur_actuelle or
          valeur_jouee == carte_defausse_tuple[1])
def choisir_couleur_ia_classique(main_ia):
  comptage_couleurs = {'R': 0, 'V': 0, 'B': 0, 'J': 0}
  for couleur, _ in main_ia:
    if couleur in comptage_couleurs:
      comptage_couleurs[couleur] += 1
  # Trouver la couleur avec le compte maximal
  couleur_choisie = 'R' # Couleur par defaut
  max_count = -1
  for couleur, count in comptage_couleurs.items():
    if count > max_count:
      max_count = count
      couleur_choisie = couleur
  # Si egalite, on choisit aleatoirement parmi les meilleures options
  best_colors = [c for c, count in comptage_couleurs.items() if count == max_count]
  # Utilise 'random.choice' de l'import 'random'
  return random.choice(best_colors)
def jouer_tour_ia_classique(main_ia, carte_defausse_tuple, couleur_actuelle, nbr_manches_jouees):
  global Q_TABLE, HISTORIQUE_IA
  # 1. Generer la liste des actions possibles
  actions_possibles = []
  # Cartes jouables (y compris les Jokers)
  cartes_jouables = [
    carte for carte in main_ia
    if verifier_validite_uno_classique(carte, carte_defausse_tuple, couleur_actuelle)
  ]
  # Creer la liste des actions pour la Q-Table: (carte, couleur_choisie)
  for carte in cartes_jouables:
    couleur, valeur = carte
    if couleur == 'N': # Joker ou +4
      # L'action inclut le choix de la couleur
      for c in Colors:
        actions_possibles.append((carte, c))
    else:
      # L'action n'inclut que la carte jouee (la couleur est celle de la carte)
      actions_possibles.append((carte, couleur))

  # Ajouter l'action de pioche
  actions_possibles.append(VALEUR_PIOCHE)
  # 2. Generer l'etat actuel
  etat_actuel = generer_etat_uno_classique(main_ia, carte_defausse_tuple, couleur_actuelle)
  # 3. Choisir l'action (Exploration ou Exploitation)
  action_choisie_tuple = choisir_action_apprentissage(Q_TABLE, etat_actuel, actions_possibles, nbr_manches_jouees)
  # 4. Enregistrer l'etat et l'action pour la mise a jour future
  if action_choisie_tuple:
    HISTORIQUE_IA.append({
      'etat_precedent': etat_actuel,
      'action_precedente': action_choisie_tuple,
      'nbr_cartes_avant': len(main_ia)
    })
  # L'action est soit (carte, couleur_choisie) ou ('P', None)
  if action_choisie_tuple[0] == 'P':
    return (None, None, 'Piocher') # Pas de carte jouee, pas de couleur choisie
  else:
    carte_jouee, couleur_choisie = action_choisie_tuple
    return (carte_jouee, couleur_choisie, 'Jouer')
def jouer_une_manche_classique(joueur_a_commencer, nbr_manches_jouees):
  global Q_TABLE, HISTORIQUE_IA
  paquet = creer_paquet_classique()
  main_joueur_1 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
  main_joueur_2 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
  defausse_pile = []
  # Tirer la premiere carte de defausse
  while True:
    carte_initiale = piocher_carte_aleatoire(paquet, 1)[0]
    # La carte initiale ne peut pas etre une carte speciale (pour simplification)
    if carte_initiale[0] != 'N' and carte_initiale[1] not in Val_spe:
      defausse_pile.append(carte_initiale)
      break
    else:
      # Remettre la carte dans le paquet (pas de melange)
      paquet.append(carte_initiale)
  # Etat initial du jeu
  etat_tour = {
    'sens_horaire': True,
    'couleur_actuelle': defausse_pile[-1][0], # Couleur de la premiere carte
    'sauter_tour_suivant': False,
    'total_cartes_a_piocher': 0
  }
  joueur_courant = joueur_a_commencer
  manche_terminee = False
  gagnant = None
  HISTORIQUE_IA = [] # Reinitialiser l'historique de l'IA pour la nouvelle manche
  print("Premiere carte: %s de couleur %s" % (defausse_pile[-1][1], etat_tour['couleur_actuelle']))
  while not manche_terminee:
    carte_jouee = None
    action_valide = False
    couleur_choisie_par_joker = None
    # 1. Gerer les cartes a piocher (+2 ou +4 empiles)
    if etat_tour['total_cartes_a_piocher'] > 0:
      penalite = etat_tour['total_cartes_a_piocher']
      print("Penalite de %d cartes a appliquer." % penalite)
      if joueur_courant == 1:
        appliquer_penalite(main_joueur_1, paquet, defausse_pile[-1], penalite)
      else: # IA
        appliquer_penalite(main_joueur_2, paquet, defausse_pile[-1], penalite)
      # Reinitialiser la penalite apres application
      etat_tour['total_cartes_a_piocher'] = 0
      # Passer au joueur suivant
      joueur_courant = 3 - joueur_courant
      continue # Fin du tour actuel, passage au suivant
    # 2. Gestion du tour saute (PTT)
    if etat_tour['sauter_tour_suivant']:
      print("Tour saute pour le Joueur %d." % joueur_courant)
      etat_tour['sauter_tour_suivant'] = False
      joueur_courant = 3 - joueur_courant
      continue # Fin du tour actuel, passage au suivant
    # 3. Tour du Joueur 1
    if joueur_courant==1:
      while not action_valide:
        k=d.pagination_cartes(defausse_pile[-1],main_joueur_1)
        if k=='P':
          # Action Piocher
          cartes_piochees = piocher_carte_aleatoire(paquet, 1)
          main_joueur_1.extend(cartes_piochees)
          print("Vous piochez : %s" % str(cartes_piochees[0]))
          # Offrir de jouer la carte piochee si elle est valide
          carte_piochee = cartes_piochees[0]
          if verifier_validite_uno_classique(carte_piochee, defausse_pile[-1], etat_tour['couleur_actuelle']):
            # Retrait des accents dans l'invite
            jouer_pioche =input("Voulez-vous jouer la carte piochee %s (O/N) ? " % str(carte_piochee)).upper()
            if jouer_pioche == 'O':
              carte_jouee = carte_piochee
              main_joueur_1.remove(carte_jouee)
              action_valide = True                
              if carte_jouee[0] == 'N': # Choix de couleur pour Joker/+4
                print("Choisissez une couleur (R, V, B, J):")
                couleur_choisie_par_joker = t.trys(input("Couleur: ").upper(), 1, 1, options=Colors)
          action_valide = True # Termine le tour (soit en jouant, soit sans jouer)
        else:
          index_carte =k-1
          carte_tentative = main_joueur_1[index_carte]
          if verifier_validite_uno_classique(carte_tentative, defausse_pile[-1], etat_tour['couleur_actuelle']):
            carte_jouee = carte_tentative
            main_joueur_1.pop(index_carte)
            action_valide = True
          if carte_jouee[0] == 'N': # Choix de couleur pour Joker/+4
            print("Choisissez une couleur (R, V, B, J):")
            couleur_choisie_par_joker = t.trys(input("Couleur: ").upper(), 1, 1, options=Colors)
          else:
          # Retrait des accents
            print("Carte invalide. ")
        if action_valide and carte_jouee:
          print("Vous jouez :%s." % str(carte_jouee))
    # 4. Tour de l'IA (2)
    else: # joueur_courant == 2
      print("\n---------------------\nTour de l'IA (Joueur 2) - Cartes: %d" % len(main_joueur_2))
      print("Defausse: %s " % (defausse_pile[-1]))
      # Obtenir l'action de l'IA (carte_jouee, couleur_choisie, type_action)
      action_result=jouer_tour_ia_classique(main_joueur_2, defausse_pile[-1], etat_tour['couleur_actuelle'], nbr_manches_jouees)
      carte_jouee, couleur_choisie_par_joker, type_action = action_result
      if type_action == 'Piocher':
        # Action Piocher
        cartes_piochees = piocher_carte_aleatoire(paquet, 1)
        main_joueur_2.extend(cartes_piochees)
        print("L'IA pioche 1 carte.")
        # L'IA ne joue pas la carte piochee dans cette implementation simple
        action_valide = True

      elif type_action == 'Jouer':
        # Action Jouer
        if carte_jouee and carte_jouee in main_joueur_2:
          main_joueur_2.remove(carte_jouee)
          print("L'IA joue %s." % str(carte_jouee))

          if carte_jouee[0] == 'N':
            # Utiliser la strategie pour choisir la couleur si l'action choisie l'autorise
            if couleur_choisie_par_joker is None:
              # Si le choix de l'action Q-Learning n'a pas inclus de couleur (car c'est un Joker),
              # l'IA applique sa strategie ici.
              couleur_choisie_par_joker = choisir_couleur_ia_classique(main_joueur_2)

            print("L'IA choisit la couleur %s" % couleur_choisie_par_joker)

          action_valide = True
        else:
          # Retrait des accents
          print("Erreur: L'IA a choisi une action invalide ou une carte non posee. Piocher par defaut.")
          cartes_piochees = piocher_carte_aleatoire(paquet, 1)
          main_joueur_2.extend(cartes_piochees)
          action_valide = True # Le tour se termine par une pioche

    # 5. Application des effets de la carte jouee
    if carte_jouee and action_valide:
      couleur_carte_jouee, valeur_carte_jouee = carte_jouee
      defausse_pile.append(carte_jouee)

      # Mise a jour de la couleur actuelle (couleur de la carte jouee ou couleur choisie par Joker)
      if couleur_choisie_par_joker:
        etat_tour['couleur_actuelle'] = couleur_choisie_par_joker
      else:
        etat_tour['couleur_actuelle'] = couleur_carte_jouee

      # Effets de carte
      if valeur_carte_jouee == '+2':
        etat_tour['total_cartes_a_piocher'] += 2
        etat_tour['sauter_tour_suivant'] = True
      elif valeur_carte_jouee == 'I': # Inversion
        etat_tour['sens_horaire'] = not etat_tour['sens_horaire']
      elif valeur_carte_jouee == 'PTT': # Passe Ton Tour
        etat_tour['sauter_tour_suivant'] = True
      elif valeur_carte_jouee == '+4':
        etat_tour['total_cartes_a_piocher'] += 4
        etat_tour['sauter_tour_suivant'] = True

      # Verification de fin de manche (main vide)
      if joueur_courant == 1 and not main_joueur_1:
        gagnant = 1
        manche_terminee = True
      elif joueur_courant == 2 and not main_joueur_2:
        gagnant = 2
        manche_terminee = True

    # 6. Gestion du paquet vide
    if not paquet:
      # Note: recycler_defausse ne melange plus le paquet
      recycler_defausse(paquet, defausse_pile)
      # Retrait des accents
      print("Paquet recycle.")
      if not paquet:
        # Retrait des accents
        print("La defausse etait trop petite. Fin de manche par manque de cartes.")
        manche_terminee = True
        if len(main_joueur_1) < len(main_joueur_2):
          gagnant = 1
        else:
          gagnant = 2

    # 7. Mise a jour de la Q-Table de l'IA apres son tour
    if joueur_courant == 2 and HISTORIQUE_IA and action_valide:
      derniere_action_ia = HISTORIQUE_IA.pop()

      # L'etat actuel de la partie pour l'IA est l'etat du joueur 1 a son tour
      etat_actuel_ia = generer_etat_uno_classique(main_joueur_1, defausse_pile[-1], etat_tour['couleur_actuelle'])

      recompense = obtenir_recompense(
        game_mode = 'UNO_CL',
        victoire_ia = (gagnant == 2 if manche_terminee else False),
        nbr_cartes_avant = derniere_action_ia['nbr_cartes_avant'],
        nbr_cartes_apres = len(main_joueur_2),
        action_carte = derniere_action_ia['action_precedente'],
        main_ia_apres = main_joueur_2
      )

      mettre_a_jour_q_table(
        Q_TABLE,
        derniere_action_ia['etat_precedent'],
        derniere_action_ia['action_precedente'],
        recompense,
        etat_actuel_ia
      )

    if not manche_terminee and action_valide:
      # Passage au joueur suivant (gestion de l'inversion par le 'sens_horaire')
      if etat_tour['sens_horaire']:
        joueur_courant = 3 - joueur_courant
      else:
        # Dans un jeu a 2 joueurs, Inversion ne change pas de joueur, on reste sur le meme
        pass

  # Fin de manche
  if gagnant is None:
    # Si la manche s'est terminee prematurement (paquet vide)
    gagnant = 1 if len(main_joueur_1) < len(main_joueur_2) else 2
    perdant = 3 - gagnant
    if gagnant == 1:
      points_marque_par_perdant = calculer_score(main_joueur_2, 'UNO')
    else:
      points_marque_par_perdant = calculer_score(main_joueur_1, 'UNO')
  else:
    perdant = 3 - gagnant
    if gagnant == 1:
      points_marque_par_perdant = calculer_score(main_joueur_2, 'UNO')
    else:
      points_marque_par_perdant = calculer_score(main_joueur_1, 'UNO')

  # Sauvegarde de la Q-Table
  sauvegarder_q_table(Q_TABLE)

  print("\n=============================================")
  # Retrait des accents et f-string
  print("FIN DE MANCHE UNO CLASSIQUE ! Le Joueur %d a gagne." % gagnant)
  print("Le Joueur %d marque %d points." % (perdant, points_marque_par_perdant))
  print("Taille de la Q-Table : %d etats UNO_CL appris." % len([k for k in Q_TABLE.keys() if 'UNO_CL' in k]))
  print("=============================================\n")

  return gagnant, points_marque_par_perdant

uno_dos.py
masquer
import urandom1 as r
import trys as t
from uno_rules import Colors, Val_spe, Val_digits, W_cards, W_count, Nbr_cards_init, piocher_carte_aleatoire, appliquer_penalite, recycler_defausse, calculer_score
from ia_learning import charger_q_table, sauvegarder_q_table, generer_etat_uno, choisir_action_apprentissage, obtenir_recompense, mettre_a_jour_q_table
# Charger la Q-Table au debut du script
Q_TABLE = charger_q_table()
HISTORIQUE_IA = []
def creer_paquet_classique():
  paquet = []
  # Cartes chiffrees (0-9)
  for couleur in Colors:
    # Un seul '0' par couleur
    paquet.append(('0',couleur,"0"))
    # Deux de chaque chiffre (1-9)
    for valeur in Val_digits[1:]:
      paquet.append((valeur,couleur,"0"))
      paquet.append((valeur,couleur,"1"))
  # Cartes d'action (+2, I, PTT)
  for couleur in Colors:
    for valeur in Val_spe:
      paquet.append((valeur,valeur,"0"))
      paquet.append((valeur,couleur,"1"))
  # Cartes sauvages (W, +4)
  for valeur in W_cards:
    for _ in range(W_count): # 4 cartes de chaque type (W, +4)
      paquet.append((valeur,"","0"))
  return r.shuffle(paquet)
def verifier_validite_uno_classique(carte_jouee, carte_defausse_tuple, couleur_actuelle):
  couleur_jouee, valeur_jouee = carte_jouee
  # Les cartes Joker ('N') sont toujours valides
  if couleur_jouee == 'N':
    return True
  # La carte doit correspondre a la couleur actuelle ou a la valeur de la carte du dessus
  return (couleur_jouee == couleur_actuelle or
          valeur_jouee == carte_defausse_tuple[1])
def choisir_couleur_ia_classique(main_ia):
  comptage_couleurs = {'R': 0, 'V': 0, 'B': 0, 'J': 0}
  for couleur, _ in main_ia:
    if couleur in comptage_couleurs:
      comptage_couleurs[couleur] += 1
  # Trouver la couleur avec le compte maximal
  couleur_choisie = 'R' # Couleur par defaut
  max_count = -1
  for couleur, count in comptage_couleurs.items():
    if count > max_count:
      max_count = count
      couleur_choisie = couleur
  # Si egalite, on choisit aleatoirement parmi les meilleures options
  best_colors = [c for c, count in comptage_couleurs.items() if count == max_count]
  # Utilise 'random.choice' de l'import 'random'
  return random.choice(best_colors)
def jouer_tour_ia_classique(main_ia, carte_defausse_tuple, couleur_actuelle, nbr_manches_jouees):
  global Q_TABLE, HISTORIQUE_IA
  # 1. Generer la liste des actions possibles
  actions_possibles = []
  # Cartes jouables (y compris les Jokers)
  cartes_jouables = [
    carte for carte in main_ia
    if verifier_validite_uno_classique(carte, carte_defausse_tuple, couleur_actuelle)
  ]
  # Creer la liste des actions pour la Q-Table: (carte, couleur_choisie)
  for carte in cartes_jouables:
    couleur, valeur = carte
    if couleur == 'N': # Joker ou +4
      # L'action inclut le choix de la couleur
      for c in Colors:
        actions_possibles.append((carte, c))
    else:
      # L'action n'inclut que la carte jouee (la couleur est celle de la carte)
      actions_possibles.append((carte, couleur))

  # Ajouter l'action de pioche
  actions_possibles.append(VALEUR_PIOCHE)
  # 2. Generer l'etat actuel
  etat_actuel = generer_etat_uno_classique(main_ia, carte_defausse_tuple, couleur_actuelle)
  # 3. Choisir l'action (Exploration ou Exploitation)
  action_choisie_tuple = choisir_action_apprentissage(Q_TABLE, etat_actuel, actions_possibles, nbr_manches_jouees)
  # 4. Enregistrer l'etat et l'action pour la mise a jour future
  if action_choisie_tuple:
    HISTORIQUE_IA.append({
      'etat_precedent': etat_actuel,
      'action_precedente': action_choisie_tuple,
      'nbr_cartes_avant': len(main_ia)
    })
  # L'action est soit (carte, couleur_choisie) ou ('P', None)
  if action_choisie_tuple[0] == 'P':
    return (None, None, 'Piocher') # Pas de carte jouee, pas de couleur choisie
  else:
    carte_jouee, couleur_choisie = action_choisie_tuple
    return (carte_jouee, couleur_choisie, 'Jouer')
def jouer_une_manche_classique(joueur_a_commencer, nbr_manches_jouees):
  global Q_TABLE, HISTORIQUE_IA
  paquet = creer_paquet_classique()
  main_joueur_1 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
  main_joueur_2 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
  defausse_pile = []
  # Tirer la premiere carte de defausse
  while True:
    carte_initiale = piocher_carte_aleatoire(paquet, 1)[0]
    # La carte initiale ne peut pas etre une carte speciale (pour simplification)
    if carte_initiale[0] != 'N' and carte_initiale[1] not in Val_spe:
      defausse_pile.append(carte_initiale)
      break
    else:
      # Remettre la carte dans le paquet (pas de melange)
      paquet.append(carte_initiale)
  # Etat initial du jeu
  etat_tour = {
    'sens_horaire': True,
    'couleur_actuelle': defausse_pile[-1][0], # Couleur de la premiere carte
    'sauter_tour_suivant': False,
    'total_cartes_a_piocher': 0
  }
  joueur_courant = joueur_a_commencer
  manche_terminee = False
  gagnant = None
  HISTORIQUE_IA = [] # Reinitialiser l'historique de l'IA pour la nouvelle manche
  print("Premiere carte: %s de couleur %s" % (defausse_pile[-1][1], etat_tour['couleur_actuelle']))
  while not manche_terminee:
    carte_jouee = None
    action_valide = False
    couleur_choisie_par_joker = None
    # 1. Gerer les cartes a piocher (+2 ou +4 empiles)
    if etat_tour['total_cartes_a_piocher'] > 0:
      penalite = etat_tour['total_cartes_a_piocher']
      print("Penalite de %d cartes a appliquer." % penalite)
      if joueur_courant == 1:
        appliquer_penalite(main_joueur_1, paquet, defausse_pile[-1], penalite)
      else: # IA
        appliquer_penalite(main_joueur_2, paquet, defausse_pile[-1], penalite)
      # Reinitialiser la penalite apres application
      etat_tour['total_cartes_a_piocher'] = 0
      # Passer au joueur suivant
      joueur_courant = 3 - joueur_courant
      continue # Fin du tour actuel, passage au suivant
    # 2. Gestion du tour saute (PTT)
    if etat_tour['sauter_tour_suivant']:
      print("Tour saute pour le Joueur %d." % joueur_courant)
      etat_tour['sauter_tour_suivant'] = False
      joueur_courant = 3 - joueur_courant
      continue # Fin du tour actuel, passage au suivant
    # 3. Tour du Joueur 1
    if joueur_courant==1:
      while not action_valide:
        k=d.pagination_cartes(defausse_pile[-1],main_joueur_1)
        if k=='P':
          # Action Piocher
          cartes_piochees = piocher_carte_aleatoire(paquet, 1)
          main_joueur_1.extend(cartes_piochees)
          print("Vous piochez : %s" % str(cartes_piochees[0]))
          # Offrir de jouer la carte piochee si elle est valide
          carte_piochee = cartes_piochees[0]
          if verifier_validite_uno_classique(carte_piochee, defausse_pile[-1], etat_tour['couleur_actuelle']):
            # Retrait des accents dans l'invite
            jouer_pioche =input("Voulez-vous jouer la carte piochee %s (O/N) ? " % str(carte_piochee)).upper()
            if jouer_pioche == 'O':
              carte_jouee = carte_piochee
              main_joueur_1.remove(carte_jouee)
              action_valide = True                
              if carte_jouee[0] == 'N': # Choix de couleur pour Joker/+4
                print("Choisissez une couleur (R, V, B, J):")
                couleur_choisie_par_joker = t.trys(input("Couleur: ").upper(), 1, 1, options=Colors)
          action_valide = True # Termine le tour (soit en jouant, soit sans jouer)
        else:
          index_carte =k-1
          carte_tentative = main_joueur_1[index_carte]
          if verifier_validite_uno_classique(carte_tentative, defausse_pile[-1], etat_tour['couleur_actuelle']):
            carte_jouee = carte_tentative
            main_joueur_1.pop(index_carte)
            action_valide = True
          if carte_jouee[0] == 'N': # Choix de couleur pour Joker/+4
            print("Choisissez une couleur (R, V, B, J):")
            couleur_choisie_par_joker = t.trys(input("Couleur: ").upper(), 1, 1, options=Colors)
          else:
          # Retrait des accents
            print("Carte invalide. ")
        if action_valide and carte_jouee:
          print("Vous jouez :%s." % str(carte_jouee))
    # 4. Tour de l'IA (2)
    else: # joueur_courant == 2
      print("\n---------------------\nTour de l'IA (Joueur 2) - Cartes: %d" % len(main_joueur_2))
      print("Defausse: %s " % (defausse_pile[-1]))
      # Obtenir l'action de l'IA (carte_jouee, couleur_choisie, type_action)
      action_result=jouer_tour_ia_classique(main_joueur_2, defausse_pile[-1], etat_tour['couleur_actuelle'], nbr_manches_jouees)
      carte_jouee, couleur_choisie_par_joker, type_action = action_result
      if type_action == 'Piocher':
        # Action Piocher
        cartes_piochees = piocher_carte_aleatoire(paquet, 1)
        main_joueur_2.extend(cartes_piochees)
        print("L'IA pioche 1 carte.")
        # L'IA ne joue pas la carte piochee dans cette implementation simple
        action_valide = True

      elif type_action == 'Jouer':
        # Action Jouer
        if carte_jouee and carte_jouee in main_joueur_2:
          main_joueur_2.remove(carte_jouee)
          print("L'IA joue %s." % str(carte_jouee))

          if carte_jouee[0] == 'N':
            # Utiliser la strategie pour choisir la couleur si l'action choisie l'autorise
            if couleur_choisie_par_joker is None:
              # Si le choix de l'action Q-Learning n'a pas inclus de couleur (car c'est un Joker),
              # l'IA applique sa strategie ici.
              couleur_choisie_par_joker = choisir_couleur_ia_classique(main_joueur_2)

            print("L'IA choisit la couleur %s" % couleur_choisie_par_joker)

          action_valide = True
        else:
          # Retrait des accents
          print("Erreur: L'IA a choisi une action invalide ou une carte non posee. Piocher par defaut.")
          cartes_piochees = piocher_carte_aleatoire(paquet, 1)
          main_joueur_2.extend(cartes_piochees)
          action_valide = True # Le tour se termine par une pioche

    # 5. Application des effets de la carte jouee
    if carte_jouee and action_valide:
      couleur_carte_jouee, valeur_carte_jouee = carte_jouee
      defausse_pile.append(carte_jouee)

      # Mise a jour de la couleur actuelle (couleur de la carte jouee ou couleur choisie par Joker)
      if couleur_choisie_par_joker:
        etat_tour['couleur_actuelle'] = couleur_choisie_par_joker
      else:
        etat_tour['couleur_actuelle'] = couleur_carte_jouee

      # Effets de carte
      if valeur_carte_jouee == '+2':
        etat_tour['total_cartes_a_piocher'] += 2
        etat_tour['sauter_tour_suivant'] = True
      elif valeur_carte_jouee == 'I': # Inversion
        etat_tour['sens_horaire'] = not etat_tour['sens_horaire']
      elif valeur_carte_jouee == 'PTT': # Passe Ton Tour
        etat_tour['sauter_tour_suivant'] = True
      elif valeur_carte_jouee == '+4':
        etat_tour['total_cartes_a_piocher'] += 4
        etat_tour['sauter_tour_suivant'] = True

      # Verification de fin de manche (main vide)
      if joueur_courant == 1 and not main_joueur_1:
        gagnant = 1
        manche_terminee = True
      elif joueur_courant == 2 and not main_joueur_2:
        gagnant = 2
        manche_terminee = True

    # 6. Gestion du paquet vide
    if not paquet:
      # Note: recycler_defausse ne melange plus le paquet
      recycler_defausse(paquet, defausse_pile)
      # Retrait des accents
      print("Paquet recycle.")
      if not paquet:
        # Retrait des accents
        print("La defausse etait trop petite. Fin de manche par manque de cartes.")
        manche_terminee = True
        if len(main_joueur_1) < len(main_joueur_2):
          gagnant = 1
        else:
          gagnant = 2

    # 7. Mise a jour de la Q-Table de l'IA apres son tour
    if joueur_courant == 2 and HISTORIQUE_IA and action_valide:
      derniere_action_ia = HISTORIQUE_IA.pop()

      # L'etat actuel de la partie pour l'IA est l'etat du joueur 1 a son tour
      etat_actuel_ia = generer_etat_uno_classique(main_joueur_1, defausse_pile[-1], etat_tour['couleur_actuelle'])

      recompense = obtenir_recompense(
        game_mode = 'UNO_CL',
        victoire_ia = (gagnant == 2 if manche_terminee else False),
        nbr_cartes_avant = derniere_action_ia['nbr_cartes_avant'],
        nbr_cartes_apres = len(main_joueur_2),
        action_carte = derniere_action_ia['action_precedente'],
        main_ia_apres = main_joueur_2
      )

      mettre_a_jour_q_table(
        Q_TABLE,
        derniere_action_ia['etat_precedent'],
        derniere_action_ia['action_precedente'],
        recompense,
        etat_actuel_ia
      )

    if not manche_terminee and action_valide:
      # Passage au joueur suivant (gestion de l'inversion par le 'sens_horaire')
      if etat_tour['sens_horaire']:
        joueur_courant = 3 - joueur_courant
      else:
        # Dans un jeu a 2 joueurs, Inversion ne change pas de joueur, on reste sur le meme
        pass

  # Fin de manche
  if gagnant is None:
    # Si la manche s'est terminee prematurement (paquet vide)
    gagnant = 1 if len(main_joueur_1) < len(main_joueur_2) else 2
    perdant = 3 - gagnant
    if gagnant == 1:
      points_marque_par_perdant = calculer_score(main_joueur_2, 'UNO')
    else:
      points_marque_par_perdant = calculer_score(main_joueur_1, 'UNO')
  else:
    perdant = 3 - gagnant
    if gagnant == 1:
      points_marque_par_perdant = calculer_score(main_joueur_2, 'UNO')
    else:
      points_marque_par_perdant = calculer_score(main_joueur_1, 'UNO')

  # Sauvegarde de la Q-Table
  sauvegarder_q_table(Q_TABLE)

  print("\n=============================================")
  # Retrait des accents et f-string
  print("FIN DE MANCHE UNO CLASSIQUE ! Le Joueur %d a gagne." % gagnant)
  print("Le Joueur %d marque %d points." % (perdant, points_marque_par_perdant))
  print("Taille de la Q-Table : %d etats UNO_CL appris." % len([k for k in Q_TABLE.keys() if 'UNO_CL' in k]))
  print("=============================================\n")

  return gagnant, points_marque_par_perdant

uno_extreme.py
masquer
import trys as t
import ia_learning as ia # Importation du module d'apprentissage
import uno_rules as rules
import display as d
from uno_rules import Colors, Val_digits, Val_spe, W_cards, EXTREME_ACTION_SPE, EXTREME_W_CARDS, Nbr_cards_init_extreme
# --- CONSTANTES SPÉCIFIQUES À UNO EXTRÊME ---
GAME_MODE ='UNO_EX'
ALL_EXTREME_ACTIONS = Val_spe + EXTREME_ACTION_SPE
ALL_EXTREME_WILDS = W_cards + EXTREME_W_CARDS
def gerer_etat_uno_extreme():
    etat = {
        'sens_horaire': True,       # True = sens horaire, False = sens anti-horaire
        'couleur_actuelle': None,   # Couleur de la carte du dessus
        'uno_crie_joueur_1': False,
        'uno_crie_joueur_2': False,
        'sauter_tour_suivant': False, # Gère l'effet PTT, +2, +4, +6, +8W
        'total_cartes_a_piocher': 0  # Compteur pour les cartes empilées
    }
    return etat

def verifier_validite_extreme(carte_jouee, carte_defausse_tuple, couleur_actuelle):
    couleur_jouee, valeur_jouee = carte_jouee
    
    # Règle de base : correspondance de couleur, de valeur ou Joker
    return (couleur_jouee == couleur_actuelle or # Correspondance de couleur choisie
            valeur_jouee == carte_defausse_tuple[1] or # Correspondance de valeur
            couleur_jouee == 'N')

def gerer_effet_carte_extreme(carte_jouee, joueur_courant, paquet, defausse_pile, main_joueur_1, main_joueur_2, etat_tour):
    couleur, valeur = carte_jouee
    prochain_joueur = 3 - joueur_courant
    main_cible = main_joueur_1 if prochain_joueur == 1 else main_joueur_2
    
    # Effets de pioche (+2, +4, +6, +8W)
    if valeur in ['+2', '+4', '+6', '+8W']:
        pioche_valeur=int(valeur.replace('+', '').replace('W', ''))
        etat_tour['total_cartes_a_piocher'] += pioche_valeur
        print("La pioche est augmentee de {} cartes.".format(pioche_valeur))      
        # Le prochain joueur doit piocher ou jouer une carte +
        etat_tour['sauter_tour_suivant'] = True
    # Effets de saut de tour (I, PTT)
    if valeur in ['I', 'PTT']:
        etat_tour['sauter_tour_suivant'] = True
        if valeur == 'I':
            etat_tour['sens_horaire'] = not etat_tour['sens_horaire']
            print("Le sens de jeu est inversé.")
        if valeur == 'PTT':
            print("Le prochain joueur passe son tour.")
    
    # Effets Extrêmes Spécifiques
    if valeur == 'PA': # Poser Tout (Poser toutes les cartes de même couleur que la carte jouée)
        cartes_a_garder = []
        cartes_defaussees_supp = []
        main_joueur = main_joueur_1 if joueur_courant == 1 else main_joueur_2

        for carte in main_joueur:
            if carte[0] == etat_tour['couleur_actuelle']:
                cartes_defaussees_supp.append(carte)
            else:
                cartes_a_garder.append(carte)
        
        main_joueur[:] = cartes_a_garder
        defausse_pile.extend(cartes_defaussees_supp)

        if cartes_defaussees_supp:
            input("Joueur {} a pose\nTOUTES les cartes\n{} en plus\n({} cartes)!".format(joueur_courant,etat_tour['couleur_actuelle'],len(cartes_defaussees_supp)))
        else:
            input("Joueur {} a pose\nPA mais n'avait\npas d'autres cartes\n{} a poser.".format(joueur_courant,etat_tour['couleur_actulle']))

    elif valeur == 'DA': # Défausser tout (Le joueur choisit une couleur et l'adversaire défausse toutes ses cartes de cette couleur)
        # Le joueur qui a posé le DA choisit une couleur
        couleur_choisie = t.get_color_choice(joueur_courant)
        
        cartes_a_garder = []
        cartes_defaussees_supp = []
        
        for carte in main_cible:
            if carte[0] == couleur_choisie:
                cartes_defaussees_supp.append(carte)
            else:
                cartes_a_garder.append(carte)
        
        main_cible[:] = cartes_a_garder
        defausse_pile.extend(cartes_defaussees_supp)
        
        if cartes_defaussees_supp:
             input("L'adversaire (Joueur {}) doit defausser {} cartes {}.".format(prochain_joueur,len(cartes_defauses_supp),couleur_choisie))
        else:
             input("L'adversaire (Joueur {}) n'avait pas de cartes {} a defausser.".format(prochain_joueur,couleur_choisie))
    return etat_tour
def jouer_une_manche_extreme(joueur_a_commencer, game_type):
  # INITIALISATION DE LA Q-TABLE EN MÉMOIRE
    Q_TABLE = ia.charger_q_table()
    
    # 1. Initialisation de la manche
    paquet_pioche = rules.creer_paquet_uno_extreme()
    
    main_joueur_1 = rules.piocher_carte_aleatoire(paquet_pioche, Nbr_cards_init_extreme)
    main_joueur_2 = rules.piocher_carte_aleatoire(paquet_pioche, Nbr_cards_init_extreme)
    
    defausse_pile = rules.piocher_carte_aleatoire(paquet_pioche, 1)
    
    # Assurer que la première carte n'est pas une carte spéciale (pour l'instant, on simplifie)
    while defausse_pile[0][1] in ALL_EXTREME_ACTIONS + ALL_EXTREME_WILDS:
        paquet_pioche.insert(0, defausse_pile.pop(0))
        r.shuffle(paquet_pioche)
        defausse_pile.extend(rules.piocher_carte_aleatoire(paquet_pioche, 1))

    etat_tour = gerer_etat_uno_extreme()
    etat_tour['couleur_actuelle'] = defausse_pile[-1][0]
    
    joueur_courant = joueur_a_commencer
    manche_terminee = False
    
    derniere_action_ia = None # Pour l'apprentissage
    
    print("Debut de manche.\nPremiere carte :{}.\nCouleur actuelle:\n{}".format(defausse-pile[-1],eta_tour['couleur_actuelle']))
    while not manche_terminee:
        # 2. Gestion des états et de l'affichage
        carte_jouee = None
        couleur_choisie = None
        action_valide = False
        
        if not paquet_pioche and len(defausse_pile) > 1:
             rules.recycler_defausse(paquet_pioche, defausse_pile)
        elif not paquet_pioche and len(defausse_pile) <= 1:
            print("Paquet et défausse vides, fin de manche par manque de cartes.")
            break

        print("C'est au Joueur {}!".format(joueur_courant))
        
        # Gestion de l'effet de pioche empilé
        if etat_tour['total_cartes_a_piocher'] > 0:
            print("Pioche en cours :{} cartes a prendre (ou a contrer).".format(etat_tour['total_cartes_a_piocher']))
            
            if joueur_courant == 1:
                 jouer_ou_piocher = t.trys(input("Voulez-vous tenter de contrer avec un '+' (o/n) ?"), 'on', 'n')
                
                 main_joueur = main_joueur_1
                 cartes_jouables_plus = [c for c in main_joueur if c[1] in ['+2', '+4', '+6', '+8W'] and verifier_validite_extreme(c, defausse_pile[-1], etat_tour['couleur_actuelle'])]

                 if jouer_ou_piocher.lower() == 'o' and cartes_jouables_plus:
                     t.afficher_main(main_joueur, [c for c in main_joueur if c in cartes_jouables_plus])
                     index_carte = t.trys_index(input("Choisissez l'index de la carte '+' à jouer (ou 'p' pour piocher) :"), len(main_joueur))
                     if index_carte != 'p':
                        carte_jouee = main_joueur.pop(index_carte)
                        action_valide = True
                     else:
                        action_valide = False
                 else:
                    print("Aucune carte '+' jouable ou choix de piocher. Pénalité appliquée.")
                    action_valide = False

            else: # IA
                 main_joueur = main_joueur_2
                 cartes_jouables_plus = [c for c in main_joueur if c[1] in ['+2', '+4', '+6', '+8W'] and verifier_validite_extreme(c, defausse_pile[-1], etat_tour['couleur_actuelle'])]
                
                 if cartes_jouables_plus:
                     carte_jouee = r.choice(cartes_jouables_plus)
                     main_joueur.remove(carte_jouee)
                     action_valide = True
                     print("L'IA contre avec {}.".format(carte_jouee))
                 else:
                     print("L'IA n'a pas pu contrer.")
                     action_valide = False

            if not action_valide:
                # Appliquer la pénalité et réinitialiser le compteur de pioche
                rules.appliquer_penalite(main_joueur_1 if joueur_courant == 1 else main_joueur_2, paquet_pioche, defausse_pile[-1], etat_tour['total_cartes_a_piocher'])
                etat_tour['total_cartes_a_piocher'] = 0
                etat_tour['sauter_tour_suivant'] = False
                joueur_courant = 3 - joueur_courant
                continue
            
        # 3. Tour normal (pas de pioche empilée en cours)
        if etat_tour['total_cartes_a_piocher'] == 0:
            if joueur_courant == 1: # Joueur Humain
                print("Defausse :{}.".format(defausse_pile[-1]))
                t.afficher_main(main_joueur_1)
                
                cartes_jouables = [
                    carte for carte in main_joueur_1
                    if verifier_validite_extreme(carte, defausse_pile[-1], etat_tour['couleur_actuelle'])
                ]
                
                if cartes_jouables:
                    t.afficher_main(main_joueur_1, cartes_jouables)
                    index_carte = t.trys_index(input("Choisissez l'index de la carte à jouer (ou 'p' pour piocher):"), len(main_joueur_1))

                    if index_carte == 'p':
                        main_joueur_1.extend(rules.piocher_carte_aleatoire(paquet_pioche))
                        print("Vous piochez 1 carte.")
                        action_valide = True
                    else:
                        carte_jouee = main_joueur_1.pop(index_carte)
                        action_valide = True
                else:
                    main_joueur_1.extend(rules.piocher_carte_aleatoire(paquet_pioche))
                    print("Aucune carte jouable. Vous piochez 1 carte et passez votre tour.")
                    action_valide = True

            else: # Joueur IA (Apprentissage par renforcement)
                main_joueur = main_joueur_2
                
                etat_actuel_ia = ia.generer_etat_uno_classique(main_joueur_2, defausse_pile, GAME_MODE)
                action_choisie = ia.choisir_action_apprentissage(Q_TABLE, etat_actuel_ia, main_joueur_2, defausse_pile, GAME_MODE)
                
                if action_choisie == ia.VALEUR_PIOCHE:
                    main_joueur_2.extend(rules.piocher_carte_aleatoire(paquet_pioche))
                    print("L'IA pioche 1 carte.")
                    action_valide = True
                    carte_jouee = None
                else:
                    carte_jouee, couleur_choisie = action_choisie
                    main_joueur_2.remove(carte_jouee)
                    print("L'IA joue {}.".format(carte_jouee))
                    action_valide = True
                
                derniere_action_ia = {
                    'etat_precedent': etat_actuel_ia,
                    'action_precedente': action_choisie,
                    'nbr_cartes_avant': len(main_joueur_2) + (1 if carte_jouee else 0),
                }

        # 4. Traitement de la carte jouée
        if action_valide and carte_jouee:
            # 4a. Traitement des cartes Wild (Joker)
            if carte_jouee[0] == 'N':
                if joueur_courant == 1 and carte_jouee[1] in rules.W_cards + EXTREME_W_CARDS:
                    couleur_choisie = t.get_color_choice(joueur_courant)
                
                if not couleur_choisie:
                    couleur_choisie = r.choice(rules.Colors)

            # 4b. Mise à jour de la défausse et de la couleur actuelle
            defausse_pile.append(carte_jouee)
            etat_tour['couleur_actuelle'] = couleur_choisie if couleur_choisie else carte_jouee[0]
            
            # 4c. Gestion des effets spéciaux
            etat_tour = gerer_effet_carte_extreme(carte_jouee, joueur_courant, paquet_pioche, defausse_pile, main_joueur_1, main_joueur_2, etat_tour)
            
            # 4d. Vérification de la fin de manche (main vide)
            if not main_joueur_1 or not main_joueur_2:
                manche_terminee = True
                gagnant = 1 if not main_joueur_1 else 2
                perdant = 3 - gagnant
                main_perdant = main_joueur_2 if perdant == 2 else main_joueur_1
                points_marque_par_perdant = rules.calculer_score(main_perdant, GAME_MODE)
                
                # Mise à jour Q-Table finale (si l'IA a perdu/gagné)
                if derniere_action_ia:
                    recompense = ia.obtenir_recompense(
                        game_mode=GAME_MODE,
                        victoire_ia=(gagnant == 2),
                        nbr_cartes_avant=derniere_action_ia['nbr_cartes_avant'],
                        nbr_cartes_apres=len(main_joueur_2),
                        action_carte=derniere_action_ia['action_precedente'],
                        main_ia_apres=main_joueur_2
                    )
                    ia.mettre_a_jour_q_table(
                        Q_TABLE,
                        derniere_action_ia['etat_precedent'],
                        derniere_action_ia['action_precedente'],
                        recompense,
                        None # État final
                    )
                break
            
        # 5. Mise à jour Q-Table (si le tour n'est pas terminé et que l'IA a joué)
        if joueur_courant == 2 and derniere_action_ia and not manche_terminee:
            etat_actuel_ia = ia.generer_etat_uno_classique(main_joueur_2, defausse_pile, GAME_MODE)

            recompense = ia.obtenir_recompense(
                game_mode = GAME_MODE,
                victoire_ia = False,
                nbr_cartes_avant = derniere_action_ia['nbr_cartes_avant'],
                nbr_cartes_apres = len(main_joueur_2),
                action_carte = derniere_action_ia['action_precedente'],
                main_ia_apres = main_joueur_2
            )
            
            ia.mettre_a_jour_q_table(
                Q_TABLE,
                derniere_action_ia['etat_precedent'],
                derniere_action_ia['action_precedente'],
                recompense,
                etat_actuel_ia
            )

        # 6. Passage au joueur suivant
        if not manche_terminee and action_valide:
            if etat_tour['total_cartes_a_piocher'] == 0 and etat_tour['sauter_tour_suivant']:
                print("Joueur {} voit son tour sauté.".format(3-joueur_courant))
                etat_tour['sauter_tour_suivant'] = False
            else:
                if etat_tour['sens_horaire']:
                    joueur_courant = 3 - joueur_courant
                else:
                    joueur_courant = 3 - joueur_courant

        elif not manche_terminee and action_valide and not carte_jouee:
            joueur_courant = 3 - joueur_courant
    
    # Résultat de la manche
    if not manche_terminee:
        score_j1 = rules.calculer_score(main_joueur_1, GAME_MODE)
        score_j2 = rules.calculer_score(main_joueur_2, GAME_MODE)
        
        gagnant = 1 if score_j1 < score_j2 else 2
        perdant = 3 - gagnant
        points_marque_par_perdant = max(score_j1, score_j2)

    print("==================")
    print("FIN DE MANCHE UNO EXTREME !\nLe Joueur {} a gagne.".format(gagnant))
    print("Le Joueur {} marque {points_marque_par_perdant} points.".format(perdant,points_marque_par_perdant))
    print("==================")
    return gagnant, points_marque_par_perdant

uno_main.py
masquer
import urandom1 as r
from uno_rules import types_paquets
from uno_classique import jouer_une_manche_classique
from uno_dos import jouer_une_manche_dos
from uno_nomerci import jouer_une_manche_no_merci
from uno_extreme import jouer_une_manche_extreme
from uno_zero import jouer_une_manche_zero
def launch_uno():
  name=input("Nom du joueur ?")
  score_joueur_1=0
  score_joueur_2=0
  joueur_a_commencer_prochaine_manche=1    
  game_type=types_paquets()
  if game_type==2:
    game_function=jouer_une_manche_dos
    game_name="DOS"
  elif game_type==3:
    game_function=jouer_une_manche_no_merci
    game_name="UNO NoMerci"
  elif game_type==4: # NOUVELLE OPTION
    game_function=jouer_une_manche_extreme
    game_name="UNO Extreme"
  elif game_type==5:
    game_function=jouer_une_manche_zero
    game_name="UNO Zero"
  else:
    game_function=jouer_une_manche_classique
    game_name="UNO Classique"    
  print("---------------------")
  print("{} contre l'IA\nstrategique !".format(game_name))
  print("Le premier joueur\ndont l'adversaire\naccumule 500 points\ngagne la partie.")  
  while True:
    print("=====================")
    print("Joueur 1: {} points\nIA : {} points".format(score_joueur_1, score_joueur_2))
    print("La manche commence.\nJoueur {} debute.".format(joueur_a_commencer_prochaine_manche))
    print("=====================")    
    gagnant,points_marque_par_perdant=game_function(joueur_a_commencer_prochaine_manche, game_type)  
    if gagnant == 1:
      score_joueur_1+=points_marque_par_perdant
      perdant=2
    else:
      score_joueur_2+=points_marque_par_perdant
      perdant=1    
    joueur_a_commencer_prochaine_manche = perdant # L'adversaire commence la manche suivante
    if score_joueur_1 >= 500:
      print("\\n*** FIN DE PARTIE ! ***")
      print("Fellitation {}!tu a gagne la partie!".format(name))
      break
    elif score_joueur_2 >= 500:
      print("\\n*** FIN DE PARTIE ! ***")
      print("L'IA a gagn   la partie complete !")
      break

if __name__ == '__main__':
    launch_uno()

uno_nomerci.py
masquer
import urandom1 as r
import trys as t
from uno_rules import Colors, Val_digits, W_cards, W_count, Nbr_cards_init, piocher_carte_aleatoire, appliquer_penalite, recycler_defausse, calculer_score
from ia_learning import charger_q_table, sauvegarder_q_table, generer_etat_uno, choisir_action_apprentissage, obtenir_recompense, mettre_a_jour_q_table #, VALEUR_PIOCHE
# Charger la Q-Table au debut du script
Q_TABLE = charger_q_table()
HISTORIQUE_IA = []
# --- CONSTANTES SPÉCIFIQUES À NO MERCY ---
# Cartes chiffrées de 0 à 10
VAL_CHIFFRES_NO_MERCI = [str(n) for n in range(0, 11)]
# Cartes Action Spéciales (selon le paquet étendu de No Mercy)
VAL_SPEC_NO_MERCI_SIMPLIFIE = ['+10', '+6', '+4I', 'PTT', 'I', '+2'] # 'RC' et 'PA' ne sont pas gérés ici pour simplification
# Cartes Joker
WILD_NO_MERCI = W_cards # W et +4
WILD_NO_MERCI_COUNT = 4

def creer_paquet_no_merci():
  paquet = []
  # Cartes chiffrées (0-10) - 2 par couleur
  for couleur in Colors:
    for valeur in VAL_CHIFFRES_NO_MERCI:
      paquet.append((couleur, valeur))
      paquet.append((couleur, valeur))

  # Cartes Action (2 de chaque par couleur)
  for couleur in Colors:
    for valeur in VAL_SPEC_NO_MERCI_SIMPLIFIE:
      paquet.append((couleur, valeur))
      paquet.append((couleur, valeur))

  # Cartes Sauvages (4 de chaque)
  for valeur in WILD_NO_MERCI:
    for _ in range(WILD_NO_MERCI_COUNT):
      paquet.append(('N', valeur))

  r.shuffle(paquet)
  return paquet

def gerer_etat_no_merci():
  """Initialise l'etat de la manche UNO No Mercy."""
  etat = {
    'sens_horaire': True,
    'couleur_actuelle': None,
    'uno_crie_joueur_1': False,
    'uno_crie_joueur_2': False,
    'total_cartes_a_piocher': 0  # L'element CRITIQUE du No Mercy : le compteur de penalite
  }
  return etat

def verifier_validite_no_merci(carte_jouee, carte_defausse_tuple, couleur_actuelle, cartes_a_piocher):
  """
  Verifie si la carte jouee est legale, en tenant compte du stacking de penalite.
  """
  couleur_jouee, valeur_jouee = carte_jouee

  # 1. Stacking de penalite actif
  if cartes_a_piocher > 0:
    # Seules les cartes +X et +4 sont valides
    if valeur_jouee in ['+2', '+6', '+10'] and couleur_jouee == couleur_actuelle:
      return True
    if valeur_jouee in ['+4', '+4I']:
      return True
    
    # +2 sur +2 d'une couleur differente si la carte du dessus est un +2
    if valeur_jouee == '+2' and carte_defausse_tuple[1] == '+2' and couleur_jouee == couleur_actuelle:
        return True
    
    # Si on ne stack pas, on ne peut rien jouer d'autre que Piocher/Accepter
    return False

  # 2. Jeu normal (pas de stacking actif)
  # Règle UNO classique : correspondance de couleur, de valeur ou Joker
  return (couleur_jouee == couleur_actuelle or
          valeur_jouee == carte_defausse_tuple[1] or
          couleur_jouee == 'N')


def choisir_carte_jouer_ia_no_merci(main_ia, defausse_pile, etat_tour, nbr_manches_jouees):
  """
  Decide de l'action de l'IA (carte a jouer et couleur choisie) basee sur la Q-Table.
  Retourne ((carte_jouee, couleur_choisie), None) ou (VALEUR_PIOCHE, -1)
  """
  global Q_TABLE, HISTORIQUE_IA

  # 1. Generer l'etat
  etat_actuel = generer_etat_uno_classique(main_ia, defausse_pile, etat_tour['couleur_actuelle'], etat_tour['total_cartes_a_piocher'])

  # 2. Determiner les actions possibles: (carte, couleur_choisie)
  actions_possibles = []
  couleur_actuelle = etat_tour['couleur_actuelle']
  cartes_a_piocher = etat_tour['total_cartes_a_piocher']

  for carte in main_ia:
    is_valid = verifier_validite_no_merci(carte, defausse_pile[-1], couleur_actuelle, cartes_a_piocher)
    
    if is_valid:
      couleur_jouee, valeur_jouee = carte
      
      # Si c'est un Joker ('W', '+4', '+4I'), l'IA choisit la couleur
      if couleur_jouee == 'N':
        # Strategie IA simplifiee : choisir la couleur qu'elle a le plus
        couleurs_main = [c[0] for c in main_ia if c[0] != 'N']
        couleur_choisie = max(set(couleurs_main), key=couleurs_main.count, default=r.choice(Colors))
        actions_possibles.append(((carte, couleur_choisie), None))
      else:
        # Couleur non Joker, la couleur choisie est la couleur de la carte jouee
        actions_possibles.append(((carte, couleur_jouee), None))


  # Si penalite active et aucune carte jouable, la seule action est d'accepter la penalite (Piocher)
  if cartes_a_piocher > 0 and not actions_possibles:
      actions_possibles.append((VALEUR_PIOCHE, -1))
  
  # Si aucune penalite active et aucune carte jouable, l'action est Piocher
  if cartes_a_piocher == 0 and not actions_possibles:
      actions_possibles.append((VALEUR_PIOCHE, -1))
  
  # Si penalite active et actions de stacking possibles, on n'ajoute pas l'action pioche ici
  # L'IA doit choisir entre les actions possibles de stacking, ou forcer la pioche
  if cartes_a_piocher == 0 or actions_possibles:
      # L'IA peut toujours decider de piocher pour eviter de jouer une carte cles
      actions_possibles.append((VALEUR_PIOCHE, -1))

  # 3. Choisir l'action (Exploration ou Exploitation)
  action_choisie = choisir_action_apprentissage(Q_TABLE, etat_actuel, actions_possibles, nbr_manches_jouees)

  # 4. Enregistrer l'etat et l'action pour la mise a jour future
  if action_choisie:
    HISTORIQUE_IA.append({
      'etat_precedent': etat_actuel,
      'action_precedente': action_choisie,
      'nbr_cartes_avant': len(main_ia)
    })

  return action_choisie


def jouer_une_manche_no_merci(joueur_a_commencer, nbr_manches_jouees):
  """
  Simule une manche de UNO No Mercy (Joueur 1 vs IA).
  Retourne (gagnant, points_marque_par_perdant).
  """
  global Q_TABLE, HISTORIQUE_IA
  
  paquet = creer_paquet_no_merci()
  main_joueur_1 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
  main_joueur_2 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
  defausse_pile = []

  # Initialiser la pile de defausse
  while True:
    carte_initiale = piocher_carte_aleatoire(paquet, 1)[0]
    # On commence avec une carte chiffre normale
    if carte_initiale[1] in VAL_CHIFFRES_NO_MERCI and carte_initiale[0] != 'N':
      defausse_pile.append(carte_initiale)
      break
    else:
      paquet.append(carte_initiale) # Remettre la carte dans le paquet

  etat_tour = gerer_etat_no_merci()
  etat_tour['couleur_actuelle'] = defausse_pile[-1][0]
  
  joueur_courant = joueur_a_commencer
  manche_terminee = False
  gagnant = None
  HISTORIQUE_IA = []

  print("Carte du dessus : %s (Couleur actuelle: %s)" % (str(defausse_pile[-1]), etat_tour['couleur_actuelle']))

  while not manche_terminee:
    action_valide = False
    carte_jouee = None
    couleur_choisie = None
    
    # Verifier si une penalite de pioche est active
    is_penalty_active = etat_tour['total_cartes_a_piocher'] > 0

    print("\n")
    print("---------------------\nCarte du dessus: %s | Couleur actuelle: %s" % (str(defausse_pile[-1]), etat_tour['couleur_actuelle']))
    if is_penalty_active:
        print("ATTENTION: Penalite de PIOCHE de +%d cartes ACTIVE!" % etat_tour['total_cartes_a_piocher'])


    # 1. Tour du Joueur Humain (1)
    if joueur_courant == 1:
      print("\nTour du Joueur 1 (Humain) - Cartes: %d" % len(main_joueur_1))
      print("Votre main:", main_joueur_1)

      cartes_jouables_indices = [
        i for i, carte in enumerate(main_joueur_1)
        if verifier_validite_no_merci(carte, defausse_pile[-1], etat_tour['couleur_actuelle'], is_penalty_active)
      ]
      
      choix = t.trys(input("Action (J/P pour Jouer/Piocher): ").upper(), 1, 1)

      if choix == 'P':
        # Action Piocher / Accepter la penalite
        if is_penalty_active:
          appliquer_penalite(main_joueur_1, paquet, defausse_pile[-1], etat_tour['total_cartes_a_piocher'])
          etat_tour['total_cartes_a_piocher'] = 0 # La penalite est purge
          action_valide = True
        else:
          # Piocher 1 carte et passer son tour (regle No Mercy simplifiee)
          cartes_piochees = piocher_carte_aleatoire(paquet, 1)
          main_joueur_1.extend(cartes_piochees)
          print("Vous piochez 1 carte.")
          action_valide = True
          # Si le joueur peut jouer la carte piochee, il le fait (simplification)
          carte_piochee = cartes_piochees[0]
          if verifier_validite_no_merci(carte_piochee, defausse_pile[-1], etat_tour['couleur_actuelle'], is_penalty_active):
              print("Carte piochee jouee automatiquement: %s" % str(carte_piochee))
              defausse_pile.append(carte_piochee)
              etat_tour['couleur_actuelle'] = carte_piochee[0] if carte_piochee[0] != 'N' else r.choice(Colors)
              main_joueur_1.remove(carte_piochee) # Retire la carte jouee
              # Si jouee, il passe au joueur suivant, sans jouer de tour supplementaire.
              # On doit recalculer les effets de la carte jouee
              carte_jouee = carte_piochee
              couleur_choisie = etat_tour['couleur_actuelle'] # Simuler le choix de couleur


      elif choix == 'J' and cartes_jouables_indices:
        # Action Jouer
        try:
          print("Cartes jouables (indices):", cartes_jouables_indices)
          index_carte = int(input("Index de la carte a jouer: "))
          
          if index_carte in cartes_jouables_indices:
            carte_tentative = main_joueur_1[index_carte]
            carte_jouee = carte_tentative
            main_joueur_1.pop(index_carte)
            action_valide = True
            
            # Gestion des Jokers
            if carte_jouee[0] == 'N':
              choix_couleur = t.trys(input("Choisir couleur (R, V, B, J): ").upper(), 1, 1)
              if choix_couleur in Colors:
                couleur_choisie = choix_couleur
              else:
                couleur_choisie = r.choice(Colors) # Couleur par defaut si mauvaise entree
            else:
              couleur_choisie = carte_jouee[0]
            
            defausse_pile.append(carte_jouee)
            etat_tour['couleur_actuelle'] = couleur_choisie

          else:
            print("Carte invalide ou non jouable.")

        except (ValueError, IndexError):
          print("Choix invalide.")
      else:
        print("Action invalide ou aucune carte jouable. Vous devez piocher.")
        
        
    # 2. Tour de l'IA (2)
    else: # joueur_courant == 2
      print("\nTour de l'IA (Joueur 2) - Cartes: %d" % len(main_joueur_2))

      action_choisie = choisir_carte_jouer_ia_no_merci(main_joueur_2, defausse_pile, etat_tour, nbr_manches_jouees)
      carte_action, couleur_action = action_choisie # carte_action peut etre VALEUR_PIOCHE

      if carte_action is VALEUR_PIOCHE:
        # Action Piocher / Accepter la penalite
        if is_penalty_active:
          appliquer_penalite(main_joueur_2, paquet, defausse_pile[-1], etat_tour['total_cartes_a_piocher'])
          etat_tour['total_cartes_a_piocher'] = 0 # La penalite est purge
          action_valide = True
          print("L'IA accepte la penalite de +%d cartes." % etat_tour['total_cartes_a_piocher'])
        else:
          # Piocher 1 carte et passer son tour (regle No Mercy simplifiee)
          cartes_piochees = piocher_carte_aleatoire(paquet, 1)
          main_joueur_2.extend(cartes_piochees)
          print("L'IA pioche 1 carte.")
          action_valide = True
          # L'IA joue la carte piochee si possible (simplification)
          carte_piochee = cartes_piochees[0]
          if verifier_validite_no_merci(carte_piochee, defausse_pile[-1], etat_tour['couleur_actuelle'], is_penalty_active):
              carte_jouee = carte_piochee
              couleur_choisie = carte_piochee[0] if carte_piochee[0] != 'N' else r.choice(Colors)
              main_joueur_2.remove(carte_piochee) # Retire la carte jouee
              defausse_pile.append(carte_jouee)
              etat_tour['couleur_actuelle'] = couleur_choisie
              print("L'IA joue la carte piochee: %s, Couleur choisie: %s" % (str(carte_jouee), couleur_choisie))


      else:
        # Action Jouer
        carte_jouee = carte_action[0]
        couleur_choisie = carte_action[1]
        
        main_joueur_2.remove(carte_jouee)
        defausse_pile.append(carte_jouee)
        etat_tour['couleur_actuelle'] = couleur_choisie
        action_valide = True
        print("L'IA joue %s. Nouvelle couleur: %s" % (str(carte_jouee), couleur_choisie))


    # 3. Application des effets de la carte jouee
    if carte_jouee and action_valide:
      valeur_carte_jouee = carte_jouee[1]
      
      # Penalites de Pioche (Stacking)
      penalites_stack = {'+2': 2, '+6': 6, '+10': 10, '+4': 4, '+4I': 4}
      if valeur_carte_jouee in penalites_stack:
        etat_tour['total_cartes_a_piocher'] += penalites_stack[valeur_carte_jouee]
        # Dans No Mercy, le +4I inverse aussi le sens
        if valeur_carte_jouee == '+4I':
            etat_tour['sens_horaire'] = not etat_tour['sens_horaire']

      # Actions non-stackables
      elif valeur_carte_jouee == 'I': # Inversion
        etat_tour['sens_horaire'] = not etat_tour['sens_horaire']
      elif valeur_carte_jouee == 'PTT': # Passe Ton Tour
        joueur_courant = 3 - joueur_courant # Passe deux fois

      # Verification de fin de manche (main vide)
      if joueur_courant == 1 and not main_joueur_1:
        gagnant = 1
        manche_terminee = True
      elif joueur_courant == 2 and not main_joueur_2:
        gagnant = 2
        manche_terminee = True


    # 4. Gestion du paquet vide
    if not paquet:
      recycler_defausse(paquet, defausse_pile)
      if not paquet:
        print("Fin de manche par manque de cartes.")
        manche_terminee = True
        gagnant = 1 if len(main_joueur_1) < len(main_joueur_2) else 2


    # 5. Mise a jour de la Q-Table de l'IA apres son tour
    if joueur_courant == 2 and HISTORIQUE_IA and action_valide:
      derniere_action_ia = HISTORIQUE_IA.pop()

      # L'etat actuel de la partie pour l'IA est l'etat du joueur 1 a son tour
      etat_actuel_ia = generer_etat_uno_classique(main_joueur_1, defausse_pile, etat_tour['couleur_actuelle'], etat_tour['total_cartes_a_piocher'])

      recompense = obtenir_recompense(
        game_mode = 'NO_MERCI',
        victoire_ia = (gagnant == 2 if manche_terminee else False),
        nbr_cartes_avant = derniere_action_ia['nbr_cartes_avant'],
        nbr_cartes_apres = len(main_joueur_2),
        action_carte = derniere_action_ia['action_precedente'],
        main_ia_apres = main_joueur_2
      )

      mettre_a_jour_q_table(
        Q_TABLE,
        derniere_action_ia['etat_precedent'],
        derniere_action_ia['action_precedente'],
        recompense,
        etat_actuel_ia
      )


    # 6. Passage au joueur suivant
    if not manche_terminee and action_valide:
      if etat_tour['sens_horaire']:
        joueur_courant = 3 - joueur_courant
      else:
        joueur_courant = 3 - joueur_courant
        
  # Fin de manche
  perdant = 3 - gagnant
  points_marque_par_perdant = calculer_score(main_joueur_2 if gagnant == 1 else main_joueur_1, 'NO_MERCI')

  # Sauvegarde de la Q-Table
  sauvegarder_q_table(Q_TABLE)

  print("\n=============================================")
  print("FIN DE MANCHE UNO NO MERCY ! Le Joueur %d a gagne." % gagnant)
  print("Le Joueur %d marque %d points." % (perdant, points_marque_par_perdant))
  print("Taille de la Q-Table : %d etats NO_MERCI appris." % len([k for k in Q_TABLE.keys() if 'NO_MERCI' in k]))
  print("=============================================\n")

  return gagnant, points_marque_par_perdant

uno_zero.py
masquer
import random as r
import trys as t
from uno_rules import Colors, Val_spe, Val_digits, W_cards, W_count, Nbr_cards_init, piocher_carte_aleatoire, appliquer_penalite, recycler_defausse, calculer_score, creer_paquet_uno_classique
# Importation des fonctions d'apprentissage
from ia_learning import charger_q_table, sauvegarder_q_table, generer_etat_uno, choisir_action_apprentissage, obtenir_recompense, mettre_a_jour_q_table
# Charger la Q-Table au debut du script
Q_TABLE = charger_q_table()
HISTORIQUE_IA = []
def verifier_validite_uno_zero(carte_jouee, carte_defausse_tuple, couleur_actuelle):
    couleur_jouee, valeur_jouee = carte_jouee
    
    # Regle UNO classique : correspondance de couleur, de valeur ou Joker
    return (couleur_jouee == couleur_actuelle or # Correspondance de couleur choisie
            valeur_jouee == carte_defausse_tuple[1] or # Correspondance de valeur
            couleur_jouee == 'N')

def choisir_carte_jouer_ia_zero(main_ia, defausse_pile, etat_tour, nbr_manches_jouees):
    global Q_TABLE, HISTORIQUE_IA

    # 1. Générer l'état (utilise l'état classique car les cartes sont les mêmes)
    etat_actuel = generer_etat_uno_classique(main_ia, defausse_pile, etat_tour['couleur_actuelle'], etat_tour['total_cartes_a_piocher'])

    # 2. Déterminer les actions possibles: (carte, couleur_choisie)
    actions_possibles = []
    couleur_actuelle = etat_tour['couleur_actuelle']

    for carte in main_ia:
        is_valid = verifier_validite_uno_zero(carte, defausse_pile[-1], couleur_actuelle)
        
        if is_valid:
            couleur_jouee, valeur_jouee = carte
            
            # Si c'est un Joker ('N'), l'IA choisit la couleur
            if couleur_jouee == 'N':
                # Stratégie IA simplifiée : choisir la couleur qu'elle a le plus
                couleurs_main = [c[0] for c in main_ia if c[0] != 'N']
                couleur_choisie = max(set(couleurs_main), key=couleurs_main.count, default=r.choice(Colors))
                actions_possibles.append(((carte, couleur_choisie), None))
            else:
                # Couleur non Joker, la couleur choisie est la couleur de la carte jouée
                actions_possibles.append(((carte, couleur_jouee), None))

    # Action Piocher
    actions_possibles.append((VALEUR_PIOCHE, -1))

    # 3. Choisir l'action (Exploration ou Exploitation)
    action_choisie = choisir_action_apprentissage(Q_TABLE, etat_actuel, actions_possibles, nbr_manches_jouees)

    # 4. Enregistrer l'etat et l'action pour la mise a jour future
    if action_choisie:
        HISTORIQUE_IA.append({
            'etat_precedent': etat_actuel,
            'action_precedente': action_choisie,
            'nbr_cartes_avant': len(main_ia)
        })

    return action_choisie

def jouer_une_manche_zero(joueur_a_commencer, nbr_manches_jouees):
    global Q_TABLE, HISTORIQUE_IA
    
    paquet = creer_paquet_uno_classique() # Le paquet est le même que le classique
    main_joueur_1 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
    main_joueur_2 = piocher_carte_aleatoire(paquet, Nbr_cards_init)
    defausse_pile = []

    # Initialiser la pile de defausse
    while True:
        carte_initiale = piocher_carte_aleatoire(paquet, 1)[0]
        # On commence avec une carte chiffre normale
        if carte_initiale[1] in Val_digits and carte_initiale[0] != 'N':
            defausse_pile.append(carte_initiale)
            break
        else:
            paquet.append(carte_initiale) # Remettre la carte dans le paquet

    etat_tour = {
        'sens_horaire': True,
        'couleur_actuelle': defausse_pile[-1][0],
        'uno_crie_joueur_1': False,
        'uno_crie_joueur_2': False,
        'total_cartes_a_piocher': 0
    }
    
    joueur_courant = joueur_a_commencer
    manche_terminee = False
    gagnant = None
    HISTORIQUE_IA = []

    print("Carte du dessus : %s (Couleur actuelle: %s)" % (str(defausse_pile[-1]), etat_tour['couleur_actuelle']))

    while not manche_terminee:
        action_valide = False
        carte_jouee = None
        couleur_choisie = None
        
        print("\n---------------------\nCarte du dessus: %s | Couleur actuelle: %s" % (str(defausse_pile[-1]), etat_tour['couleur_actuelle']))

        # 1. Tour du Joueur Humain (1)
        if joueur_courant == 1:
            print("\nTour du Joueur 1 (Humain) - Cartes: %d" % len(main_joueur_1))
            print("Votre main:", main_joueur_1)

            cartes_jouables_indices = [
                i for i, carte in enumerate(main_joueur_1)
                if verifier_validite_uno_zero(carte, defausse_pile[-1], etat_tour['couleur_actuelle'])
            ]
            
            choix = t.trys(input("Action (J/P pour Jouer/Piocher): ").upper(), 1, 1)

            if choix == 'P':
                # Piocher 1 carte
                cartes_piochees = piocher_carte_aleatoire(paquet, 1)
                main_joueur_1.extend(cartes_piochees)
                print("Vous piochez 1 carte.")
                action_valide = True
                
                # Le joueur peut jouer la carte piochee (regle classique)
                carte_piochee = cartes_piochees[0]
                if verifier_validite_uno_zero(carte_piochee, defausse_pile[-1], etat_tour['couleur_actuelle']):
                    print("Carte piochee jouee automatiquement: %s" % str(carte_piochee))
                    defausse_pile.append(carte_piochee)
                    main_joueur_1.remove(carte_piochee)
                    carte_jouee = carte_piochee
                    couleur_choisie = carte_piochee[0] if carte_piochee[0] != 'N' else r.choice(Colors)
                    etat_tour['couleur_actuelle'] = couleur_choisie

            elif choix == 'J' and cartes_jouables_indices:
                # Action Jouer
                try:
                    print("Cartes jouables (indices):", cartes_jouables_indices)
                    index_carte = int(input("Index de la carte a jouer: "))
                    
                    if index_carte in cartes_jouables_indices:
                        carte_tentative = main_joueur_1[index_carte]
                        carte_jouee = carte_tentative
                        main_joueur_1.pop(index_carte)
                        action_valide = True
                        
                        # Gestion des Jokers
                        if carte_jouee[0] == 'N':
                            choix_couleur = t.trys(input("Choisir couleur (R, V, B, J): ").upper(), 1, 1)
                            couleur_choisie = choix_couleur if choix_couleur in Colors else r.choice(Colors)
                        else:
                            couleur_choisie = carte_jouee[0]
                        
                        defausse_pile.append(carte_jouee)
                        etat_tour['couleur_actuelle'] = couleur_choisie
                        
                        # Application de l'effet spécial '0' - Échange de mains
                        if carte_jouee[1] == '0':
                            main_joueur_1, main_joueur_2 = main_joueur_2, main_joueur_1
                            print("!!! CARTE ZERO JOUÉE !!! Les mains ont été échangées!")

                    else:
                        print("Carte invalide ou non jouable.")

                except (ValueError, IndexError):
                    print("Choix invalide.")
            else:
                print("Action invalide ou aucune carte jouable. Vous devez piocher.")
        
        # 2. Tour de l'IA (2)
        else: # joueur_courant == 2
            print("\nTour de l'IA (Joueur 2) - Cartes: %d" % len(main_joueur_2))

            action_choisie = choisir_carte_jouer_ia_zero(main_joueur_2, defausse_pile, etat_tour, nbr_manches_jouees)
            carte_action, couleur_action = action_choisie # carte_action peut etre VALEUR_PIOCHE

            if carte_action is VALEUR_PIOCHE:
                # Action Piocher
                cartes_piochees = piocher_carte_aleatoire(paquet, 1)
                main_joueur_2.extend(cartes_piochees)
                print("L'IA pioche 1 carte.")
                action_valide = True
                
                # L'IA joue la carte piochee si possible
                carte_piochee = cartes_piochees[0]
                if verifier_validite_uno_zero(carte_piochee, defausse_pile[-1], etat_tour['couleur_actuelle']):
                    carte_jouee = carte_piochee
                    couleur_choisie = carte_piochee[0] if carte_piochee[0] != 'N' else r.choice(Colors)
                    main_joueur_2.remove(carte_piochee) # Retire la carte jouee
                    defausse_pile.append(carte_jouee)
                    etat_tour['couleur_actuelle'] = couleur_choisie
                    print("L'IA joue la carte piochee: %s, Couleur choisie: %s" % (str(carte_jouee), couleur_choisie))

            else:
                # Action Jouer
                carte_jouee = carte_action[0]
                couleur_choisie = carte_action[1]
                
                main_joueur_2.remove(carte_jouee)
                defausse_pile.append(carte_jouee)
                etat_tour['couleur_actuelle'] = couleur_choisie
                action_valide = True
                print("L'IA joue %s. Nouvelle couleur: %s" % (str(carte_jouee), couleur_choisie))
                
                # Application de l'effet spécial '0' - Échange de mains
                if carte_jouee[1] == '0':
                    main_joueur_1, main_joueur_2 = main_joueur_2, main_joueur_1
                    print("!!! CARTE ZERO JOUÉE PAR L'IA !!! Les mains ont été échangées!")


        # 3. Application des autres effets de la carte jouee
        if carte_jouee and action_valide:
            valeur_carte_jouee = carte_jouee[1]
            
            if valeur_carte_jouee == 'I': # Inversion
                etat_tour['sens_horaire'] = not etat_tour['sens_horaire']
            elif valeur_carte_jouee == 'PTT': # Passe Ton Tour
                joueur_courant = 3 - joueur_courant # Passe deux fois

            # Gestion des cartes +2 ou +4
            if valeur_carte_jouee == '+2':
                main_cible = main_joueur_2 if joueur_courant == 1 else main_joueur_1
                appliquer_penalite(main_cible, paquet, defausse_pile[-1], 2)
            elif valeur_carte_jouee == '+4':
                main_cible = main_joueur_2 if joueur_courant == 1 else main_joueur_1
                appliquer_penalite(main_cible, paquet, defausse_pile[-1], 4)
            
            # Verification de fin de manche (main vide)
            if joueur_courant == 1 and not main_joueur_1:
                gagnant = 1
                manche_terminee = True
            elif joueur_courant == 2 and not main_joueur_2:
                gagnant = 2
                manche_terminee = True


        # 4. Gestion du paquet vide
        if not paquet:
            recycler_defausse(paquet, defausse_pile)
            if not paquet:
                print("Fin de manche par manque de cartes.")
                manche_terminee = True
                gagnant = 1 if len(main_joueur_1) < len(main_joueur_2) else 2


        # 5. Mise a jour de la Q-Table de l'IA apres son tour
        if joueur_courant == 2 and HISTORIQUE_IA and action_valide:
            derniere_action_ia = HISTORIQUE_IA.pop()

            # L'etat actuel de la partie pour l'IA est l'etat du joueur 1 a son tour
            etat_actuel_ia = generer_etat_uno_classique(main_joueur_1, defausse_pile, etat_tour['couleur_actuelle'], etat_tour['total_cartes_a_piocher'])

            recompense = obtenir_recompense(
                game_mode = 'UNO_ZERO',
                victoire_ia = (gagnant == 2 if manche_terminee else False),
                nbr_cartes_avant = derniere_action_ia['nbr_cartes_avant'],
                nbr_cartes_apres = len(main_joueur_2),
                action_carte = derniere_action_ia['action_precedente'],
                main_ia_apres = main_joueur_2
            )

            mettre_a_jour_q_table(
                Q_TABLE,
                derniere_action_ia['etat_precedent'],
                derniere_action_ia['action_precedente'],
                recompense,
                etat_actuel_ia
            )

        # 6. Passage au joueur suivant
        if not manche_terminee and action_valide:
            if etat_tour['sens_horaire']:
                joueur_courant = 3 - joueur_courant
            else:
                joueur_courant = 3 - joueur_courant
                
    # Fin de manche
    perdant = 3 - gagnant
    points_marque_par_perdant = calculer_score(main_joueur_2 if gagnant == 1 else main_joueur_1, 'UNO_ZERO')

    # Sauvegarde de la Q-Table
    sauvegarder_q_table(Q_TABLE)

    print("\n=============================================")
    print("FIN DE MANCHE UNO ZERO ! Le Joueur %d a gagne." % gagnant)
    print("Le Joueur %d marque %d points." % (perdant, points_marque_par_perdant))
    print("Taille de la Q-Table : %d etats UNO_ZERO appris." % len([k for k in Q_TABLE.keys() if 'UNO_ZERO' in k]))
    print("=============================================\n")

    return gagnant, points_marque_par_perdant
    

fichiers utillitaires :
urandom1.py
masquer
from random import *
def shuffle(l):    
  tmp=[]
  while len(l)>0:
    e=randint(0,len(l)-1)
    tp=l[e]
    tmp+=[tp]
    l.pop(e)
  return tmp

trys.py
masquer
def trys(i,e,s):
  if i.isdigit()==True and s<=int(i)<=e:
    return int(i)
  else:
    if i=="q":
      return i
    else:
      print("Bad number or\ninvalid charactere")
      return None  
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 28/11/2025 22:16 | #


voici les fichiers de ROM et de RAM et CPU si cela peut vous aider
lien vers le fichier google drive (j'ai pas d'autre solutions) et on voit qu'il y a plusieur fichier de RAM et de ROM user ou pas https://drive.google.com/file/d/11oXuh-vBpRbLAS3yNpOBX4LYTfc0UPD2/view?usp=sharing
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 29/11/2025 22:49 | #


voici ce qui ce passe lorsque je tente de compiler JustUI. Comment pouvoir résoudre le problème?
giteapc install Lephenixnoir/JustUI
<giteapc> Cloning Lephenixnoir/JustUI...
<giteapc> Fetching Lephenixnoir/gint...
<giteapc> Fetching Lephenixnoir/sh-elf-gcc...
<giteapc> Fetching Lephenixnoir/sh-elf-binutils...
<giteapc> Fetching Lephenixnoir/fxsdk...
<giteapc> Fetching Lephenixnoir/OpenLibm...
<giteapc> Fetching Vhex-Kernel-Core/fxlibc...
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
Dépaquetage des objets: 100% (11/11), 3.96 Kio | 675.00 Kio/s, fait.
Depuis https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc
   f284c12..7a70aae  dev        -> origin/dev
<giteapc> Will install: Lephenixnoir/fxsdk, Lephenixnoir/sh-elf-binutils, Lephenixnoir/sh-elf-gcc, Lephenixnoir/OpenLibm, Vhex-Kernel-Core/fxlibc, Lephenixnoir/gint, Lephenixnoir/JustUI
<giteapc> Is that okay (Y/n)? y
<giteapc> Lephenixnoir/fxsdk: Configuring
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Lephenixnoir/fxsdk/build
<giteapc> Lephenixnoir/fxsdk: Building
make[1] : on entre dans le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/fxsdk/build »
[ 22%] Built target fxgxa
[ 22%] Built target fxg1a
[ 25%] Built target fxsdk
[ 45%] Built target libfxlink
[ 93%] Built target fxlink
[100%] Built target fxsdk-gdb-bridge
make[1] : on quitte le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/fxsdk/build »
<giteapc> Lephenixnoir/fxsdk: Installing
make[1] : on entre dans le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/fxsdk/build »
[ 22%] Built target fxgxa
[ 22%] Built target fxg1a
[ 25%] Built target fxsdk
[ 45%] Built target libfxlink
[ 93%] Built target fxlink
[100%] Built target fxsdk-gdb-bridge
Install the project...
-- Install configuration: ""
make[1] : on quitte le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/fxsdk/build »
<giteapc> Lephenixnoir/fxsdk: Done! :D
<giteapc> Lephenixnoir/sh-elf-binutils: Configuring
<sh-elf-binutils> binutils 2.42 already installed, skipping rebuild
<giteapc> Lephenixnoir/sh-elf-binutils: Building
<giteapc> Lephenixnoir/sh-elf-binutils: Installing
<giteapc> Lephenixnoir/sh-elf-binutils: Done! :D
<giteapc> Lephenixnoir/sh-elf-gcc: Configuring
<sh-elf-gcc> libsupc++.a found, libstdc++-v3 is already built
<sh-elf-gcc> GCC 14.1.0 with libstdc++-v3 already there; skipping rebuild
<giteapc> Lephenixnoir/sh-elf-gcc: Building
<giteapc> Lephenixnoir/sh-elf-gcc: Installing
<giteapc> Lephenixnoir/sh-elf-gcc: Done! :D
<giteapc> Lephenixnoir/OpenLibm: Configuring
<giteapc> Lephenixnoir/OpenLibm: Building
make[1] : on entre dans le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/OpenLibm »
make[1]: Rien à faire pour « default ».
make[1] : on quitte le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/OpenLibm »
<giteapc> Lephenixnoir/OpenLibm: Installing
make[1] : on entre dans le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/OpenLibm »
mkdir -p /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib
cp -RpP -f libopenlibm.a /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib/
ln -sf libopenlibm.a /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib/libm.a
mkdir -p /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/include
cp -RpP -f                        \
  include/openlibm.h              \
  include/openlibm_complex.h      \
  include/openlibm_defs.h         \
  include/openlibm_fenv.h         \
  include/openlibm_fenv_sh3eb.h   \
  include/openlibm_math.h         \
  /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/include
make[1] : on quitte le répertoire « /home/dello3/.local/share/giteapc/Lephenixnoir/OpenLibm »
<giteapc> Lephenixnoir/OpenLibm: Done! :D
<giteapc> Vhex-Kernel-Core/fxlibc: Configuring
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Vhex-Kernel-Core/fxlibc/build-gint
<giteapc> Vhex-Kernel-Core/fxlibc: Building
make[1] : on entre dans le répertoire « /home/dello3/.local/share/giteapc/Vhex-Kernel-Core/fxlibc/build-gint »
[100%] Built target fxlibcStatic
make[1] : on quitte le répertoire « /home/dello3/.local/share/giteapc/Vhex-Kernel-Core/fxlibc/build-gint »
<giteapc> Vhex-Kernel-Core/fxlibc: Installing
make[1] : on entre dans le répertoire « /home/dello3/.local/share/giteapc/Vhex-Kernel-Core/fxlibc/build-gint »
[100%] Built target fxlibcStatic
Install the project...
-- Install configuration: ""
make[1] : on quitte le répertoire « /home/dello3/.local/share/giteapc/Vhex-Kernel-Core/fxlibc/build-gint »
<giteapc> Vhex-Kernel-Core/fxlibc: Done! :D
<giteapc> Lephenixnoir/gint: Configuring
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Lephenixnoir/gint/build-fx
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Lephenixnoir/gint/build-cg
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Lephenixnoir/gint/build-fxg3a
<giteapc> Lephenixnoir/gint: Building
[100%] Built target gint-fx
[100%] Built target gint-cg
[100%] Built target gint-fxg3a
<giteapc> Lephenixnoir/gint: Installing
[100%] Built target gint-fx
Install the project...
-- Install configuration: ""
[100%] Built target gint-cg
Install the project...
-- Install configuration: ""
-- Installing: /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib/fxcg50.ld
-- Installing: /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib/fxcg50_fastload.ld
[100%] Built target gint-fxg3a
Install the project...
-- Install configuration: ""
-- Installing: /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib/fxcg50.ld
-- Installing: /home/dello3/.local/share/fxsdk/sysroot/sh3eb-elf/lib/fxcg50_fastload.ld
<giteapc> Lephenixnoir/gint: Done! :D
<giteapc> Lephenixnoir/JustUI: Configuring
-- The C compiler identification is GNU 14.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /home/dello3/.local/bin/sh-elf-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found Gint: TRUE (found suitable version "2.11.0", minimum required is "2.11")
-- Configuring done (0.5s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Lephenixnoir/JustUI/build-fx
-- The C compiler identification is GNU 14.1.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /home/dello3/.local/bin/sh-elf-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found Gint: TRUE (found suitable version "2.11.0", minimum required is "2.11")
-- Configuring done (0.3s)
-- Generating done (0.0s)
-- Build files have been written to: /home/dello3/.local/share/giteapc/Lephenixnoir/JustUI/build-cg
<giteapc> Lephenixnoir/JustUI: Building
[  5%] Building C object CMakeFiles/justui-fx.dir/src/jwidget.c.obj
[ 11%] Building C object CMakeFiles/justui-fx.dir/src/jlayout_box.c.obj
[ 16%] Building C object CMakeFiles/justui-fx.dir/src/jlayout_stack.c.obj
[ 22%] Building C object CMakeFiles/justui-fx.dir/src/jlayout_grid.c.obj
[ 27%] Building C object CMakeFiles/justui-fx.dir/src/jlabel.c.obj
/home/dello3/.local/share/giteapc/Lephenixnoir/JustUI/src/jlabel.c: Dans la fonction « jlabel_poly_render »:
/home/dello3/.local/share/giteapc/Lephenixnoir/JustUI/src/jlabel.c:308:38: erreur: « font_t » n'a pas de membre nommé « line_distance »
  308 |         int block_height = lines * (f->line_distance + l->line_spacing) -
      |                                      ^~
/home/dello3/.local/share/giteapc/Lephenixnoir/JustUI/src/jlabel.c:344:23: erreur: « font_t » n'a pas de membre nommé « line_distance »
  344 |                 y += f->line_distance + l->line_spacing;
      |                       ^~
make[3]: *** [CMakeFiles/justui-fx.dir/build.make:135: CMakeFiles/justui-fx.dir/src/jlabel.c.obj] Error 1
make[2]: *** [CMakeFiles/Makefile2:87: CMakeFiles/justui-fx.dir/all] Error 2
make[1]: *** [Makefile:136: all] Error 2
gmake: *** [/home/dello3/.local/share/giteapc/Lephenixnoir/JustUI/giteapc.make:10: build] Error 2
error: error 2 in command: g
Lephenixnoir Hors ligne Administrateur Points: 25566 Défis: 174 Message

Citer : Posté le 29/11/2025 22:52 | #


Mets-toi sur la branche dev du fxSDK et de gint: giteapc install fxsdk@dev gint@dev et ensuite relance la commande. Tant que t'y es mets aussi JustUI sur dev au cas où.
Mon graphe (27 Juin): (MQ || Rogue Life) ; serial gint ; passe gint 3 ; Azur ; ...) || (shoutbox v5 ; v5)
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 01/12/2025 10:55 | # | Fichier joint


À quoi sert les fichiers :
-Casio2RAMCPUInit.mem
-Casio2RAMInit.mem
-Casio2ROMInit.mem
et Casio2UserROMInit.mem
voici le lien pour y acéder
https://drive.google.com/file/d/11oXuh-vBpRbLAS3yNpOBX4LYTfc0UPD2/view?pli=1
pour ce qui est de la forge je ne voit pas de bouton "s'incrire" comme le montre la capture enpièce jointe comment faire si il n'y a pa de possibilité pour s'inscrire
Lephenixnoir Hors ligne Administrateur Points: 25566 Défis: 174 Message

Citer : Posté le 01/12/2025 11:38 | #


C'est des fichiers internes de l'émulateurs. Comme le nom l'indique, sans doute des données d'initialisation de la mémoire au début de l'émulation. Je ne vois pas du tout où tu veux en venir...

Pour la forge, on a dû rendre les inscriptions manuelles à cause des bots. Je peux te créer un compte moi-même. Si tu veux une adresse mail différente de ton compte PC dis-moi par MP, sinon je te le crée comme ça.
Mon graphe (27 Juin): (MQ || Rogue Life) ; serial gint ; passe gint 3 ; Azur ; ...) || (shoutbox v5 ; v5)
Invite Hors ligne Membre Points: 15 Défis: 0 Message

Citer : Posté le 01/12/2025 14:22 | #


Uillise le même mail que celui de mon compte pour la forge
en ce qu'est des fichiers de l'émulateur je me suis dit qu'on pourrait trouver d'ou vient la limitation de RAM pour améliorer les performances des ADD-ins (j'ai quelque idées) et nous pourraons peut-être créer quelque chose pour accéder au system de fichier (root) de la CASIO et modifier l'appli Python (mettre à jour MicroPython vers la version 1.26.1) ainsi que d'optimiser le system et ajouter des fonctionalité de manières intégrés. Peut-tu améliorer le fxSDK en ajoutant une commande qui à partir d'un fichier compiler (g1a,g3a) donne le code source ce qui peut-être pratique pour les programme non-testé ou si on perd son code source et qu'il nous reste que le fichier g1a , si on a cette fonction on pourrais les récipérer ce qui est très pratique .
Loieducode Hors ligne Membre Points: 220 Défis: 6 Message

Citer : Posté le 01/12/2025 16:19 | #


Invite a écrit :
Peut-tu améliorer le fxSDK en ajoutant une commande qui à partir d'un fichier compiler (g1a,g3a) donne le code source ce qui peut-être pratique pour les programme non-testé ou si on perd son code source et qu'il nous reste que le fichier g1a , si on a cette fonction on pourrais les récipérer ce qui est très pratique .

Je mets juste que, à part si tu copierais l'entiereté du code source au temps de build, chose qui fera perdre une quantité significante d'espace (l'un de mes projets fait déja 800K de code SANS ASSETS, ce qui est déja 200K de plus que le g3a lui-même!), une telle chose est quasi-impossible automatiquement, encore plus avec les optimisations à la LTO. Si t'as pas envie de perdre ton code, utilise une forge Git

Invite a écrit :
je me suis dit qu'on pourrait trouver d'ou vient la limitation de RAM

Pour le point original, on sait déja où se trouves les zones de mémoire dispo sur les modèles Prizm/monochrome, IIRC (je ne suis pas trop le dev de PyExtra), donc y'a pas trop d'utilité à cela j'assume
Looking for a steel cable
Lephenixnoir Hors ligne Administrateur Points: 25566 Défis: 174 Message

Citer : Posté le 01/12/2025 16:34 | #


Le compte arrive ce soir. Pour le reste, euh... pas trop vite. Tu as beaucoup de bonnes idées mais elles sont pas toujours bien ancrées dans la réalité.

je me suis dit qu'on pourrait trouver d'ou vient la limitation de RAM

Pas de problème de ce côté-là, on sait déjà d'où ça vient.

créer quelque chose pour accéder au system de fichier (root) de la CASIO

Il n'existe pas de "système de fichiers root" sur la calculatrice

et modifier l'appli Python (mettre à jour MicroPython vers la version 1.26.1)

ainsi que d'optimiser le system et ajouter des fonctionalité de manières intégrés

Les applications officielles ne sont pas dans le système de fichiers et ne peuvent être modifiées que par une mise à jour officielle de CASIO.

Peut-tu améliorer le fxSDK en ajoutant une commande qui à partir d'un fichier compiler (g1a,g3a) donne le code source

Il est impossible de régénérer le code source à partir du binaire et absurde de mettre tout le code dedans à cause de la place que ça prend, qu'on a déjà assez de mal à contrôler.
Mon graphe (27 Juin): (MQ || Rogue Life) ; serial gint ; passe gint 3 ; Azur ; ...) || (shoutbox v5 ; v5)
Bsmith Hors ligne Membre Points: 1 Défis: 0 Message

Citer : Posté le 18/12/2025 00:24 | #


Will PythonExtra work on the fxcg50 Os version 3.8? If so, is there a link to a compiled one? The g3a file.

Also, what about Ultimatepy.g3a? What is that, and will it work on the fxcg50 Os version 3.7 & 3.8? Is there a link to the files?

Is there any documentation on the gint module? For example, what are the arguments I can supply to the functions, especially those dealing with images?

I am not in a position to compile anything. Thanks for your help.
Précédente 1, 2, 3 ··· 10 ··· 20 ··· 27, 28, 29, 30

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
captcha
Rafraîchissez la page si vous souhaitez obtenir un nouveau CAPTCHA.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2025 | Il y a 179 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd