home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 124 / cd-rom 124.iso / edu / tuxmath / tuxmathscrabble / asymptopia / Tux.py < prev    next >
Encoding:
Python Source  |  2003-10-04  |  17.1 KB  |  454 lines

  1. #!/usr/bin/env python
  2. """
  3. /***************************************************************************
  4.  
  5.     Author             :Charles B. Cosse 
  6.     
  7.     Email            :ccosse@asymptopia.com
  8.                     
  9.                     
  10.     Copyright        :(C) 2002,2003 Asymptopia Software.
  11.     
  12.  ***************************************************************************/
  13. /***************************************************************************
  14.                           Tux.py
  15.  
  16.     Description: The Tux object generates & submits Tux's options.
  17.  
  18.  ***************************************************************************/
  19.  
  20. /***************************************************************************
  21.  *                                                                         *
  22.  *   This program is free software; you can redistribute it and/or modify  *
  23.  *   it under the terms of the GNU General Public License as published by  *
  24.  *   the Free Software Foundation; either version 2 of the License, or     *
  25.  *   (at your option) any later version. (Please note that if you use this *
  26.  *   code you must give credit by including the Author and Copyright       *
  27.  *   info at the top of this file).                                        *
  28.  ***************************************************************************/
  29. """
  30.  
  31. import os, pygame
  32. from pygame.locals import *
  33. from random import random
  34.  
  35. from Board import *
  36. from Spot import *
  37. from myutil import *
  38. from Tile import *
  39. from Button import *
  40. from Validator import *
  41.  
  42. from Player import Player
  43.  
  44. class Tux(Player):
  45.     """Tux derives from asymptopia.Player
  46.     We could have called it "penguin manager"
  47.     or "Dealer", as in v.01.
  48.     Tux just get instantiated with a ptr->TuxMathScrabble, itself.
  49.     
  50.     Need to add/take-off from submissionspots from here.
  51.     Want to parallel same interface as player does, but can't use same
  52.     actual lines of code, since Tux knows what he's doing and the board
  53.     has yet to validate Tux's submission.
  54.     
  55.     Tux takes care of his own tray.
  56.     He uses same "draw_tiles" func that gets called from play() after 
  57.     win sound, upon successful validation and subsequent guest-exchange between
  58.     layers (submission vs board).
  59.     """
  60.     def __init__(self,game):
  61.         Player.__init__(self)
  62.         self.game=game
  63.         self.tray=game.tuxtray
  64.         self.LEVEL=game.LEVEL
  65.         self.current_submission_idx=None
  66.         
  67.         self.triplets=None
  68.         self.doublets=None
  69.         self.singlets=None
  70.         self.operator_doublets=None
  71.         self.operator_singlets=None
  72.         
  73.         self.triplet_expressions=None
  74.         self.doublet_expressions=None
  75.         self.singlet_expressions=None
  76.         self.wc_doublet_expressions=None
  77.         self.wc_singlet_expressions=None
  78.         
  79.         #print 'Tux.LEVEL=',self.LEVEL
  80.     
  81.     def getStringValues(self):
  82.         str_values=[]
  83.         spots=self.tray.get_spots()#not sorted 1-10,so sort:
  84.         nnumbers=self.game.NNUMBERS
  85.         newspots=[]
  86.         for spotidx in range(nnumbers):
  87.             newspots.append(0)#=[0,0,0,0,0,0]
  88.         
  89.         ntrayspots=self.game.NTRAYSPOTS
  90.         while len(spots)>ntrayspots-nnumbers:
  91.             for spot in spots:
  92.                 if spot.getMN()[1]<nnumbers:
  93.                     newspots[spot.getMN()[1]]=spot
  94.                     spots.remove(spot)
  95.                 #else:print spot.getMN()
  96.         
  97.         for dummy in range(len(newspots)):
  98.             str_values.append(newspots[dummy].guest.str_val)
  99.         return(str_values)
  100.     
  101.     def getAllStringValues(self):
  102.         str_values=[]
  103.         spots=self.tray.get_spots()#not sorted 1-10,so sort:
  104.         ntrayspots=self.game.NTRAYSPOTS
  105.         newspots=[]
  106.         for spotidx in range(ntrayspots):
  107.             newspots.append(0)#=[0,0,0,0,0,0,0,0,0,0]
  108.         while len(spots)>0:
  109.             for spot in spots:
  110.                 newspots[spot.getMN()[1]]=spot
  111.                 spots.remove(spot)
  112.         for dummy in range(len(newspots)):
  113.             str_values.append(newspots[dummy].guest.str_val)
  114.         return(str_values)
  115.  
  116.     def cycle_vals(self,vals):
  117.         tmp=vals.pop()
  118.         vals.insert(int(random()*len(vals)),tmp)
  119.         return(vals)
  120.     
  121.     def get3x2x1x(self,N):
  122.         #N=1,2,3 ~ singlets,doublets,tripplets
  123.         #all unique index-triplets in set of 6 Tiles:
  124.         #if 2 "5"'s in tiles, two "5"-singlets returned, etc..
  125.         plets=[]
  126.         num_times_cycled=0
  127.         str_vals=self.getStringValues()
  128.         #print str_vals
  129.         NumNumbers=6
  130.         while(num_times_cycled<1000):#print ratio when added vs idx on this before v2.0 release
  131.             for idx in range(0,NumNumbers-N):
  132.                 i_plet=[]
  133.                 s_plet=[]
  134.                 for jdx in range(N):
  135.                     i_plet.append(float(str_vals[idx+jdx]))#changed to "float" v2.0
  136.                 i_plet.sort()
  137.                 for jdx in range(N):
  138.                     s_plet.append(`i_plet[jdx]`)
  139.                 
  140.                 if plets.count(s_plet)==0:plets.append(s_plet)
  141.                 elif(N==1 and plets.count(s_plet)<str_vals.count(s_plet[0])):
  142.                     plets.append(s_plet)
  143.                 
  144.             str_vals=self.cycle_vals(str_vals)
  145.             num_times_cycled=num_times_cycled+1
  146.         return(plets)
  147.     
  148.     def evaluate(self,expr):    
  149.         #print expr
  150.         str=''
  151.         for idx in range(len(expr)):
  152.             str=str+expr[idx]
  153.         
  154.         try:
  155.             val=eval(str)
  156.             #print str,val
  157.         except:return(0)
  158.         return(val)
  159.  
  160.     def get3xPermutations(self,tripplet):#receives single triplet list of len=3
  161.         #print 'tripplet:',tripplet
  162.         p=[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
  163.         px3=[]#list of permuted "t"riplets
  164.         for pidx in range(len(p)):
  165.             tx3=[]#a permuted "t"riplet
  166.             for tidx in range(3):
  167.                 #print 'pidx:',pidx,'  tidx:',tidx,'  p[pidx][tidx]-1=',p[pidx][tidx]-1,'  tripplet[p[pidx][tidx]-1]=',tripplet[p[pidx][tidx]-1]
  168.                 tx3.append(tripplet[p[pidx][tidx]-1])
  169.             if px3.count(tx3)==0:px3.append(tx3)
  170.             #print 'px3:',px3
  171.         return(px3)    
  172.         
  173.     def get2xPermutations(self,doublet):
  174.         p=[[1,2],[2,1]]
  175.         px2=[]#list of permuted doublets
  176.         for pidx in range(len(p)):
  177.             dx2=[]#permuted doublet
  178.             for tidx in range(2):
  179.                 dx2.append(doublet[p[pidx][tidx]-1])
  180.             if px2.count(dx2)==0:px2.append(dx2)
  181.         return(px2)    
  182.             
  183.     #This needs modified to handle mult/div:
  184.     def get_operator_plets(self,N):
  185.         if(N==1):plets=[['+'],['-'],['*'],['/']]
  186.         elif N==2 and self.LEVEL<=4:plets=[
  187.             ['+','+'],['+','-'],['-','+'],['-','-'],
  188.             ['*','*'],['*','/'],['/','*'],['/','/'],
  189.             ['*','-'],['-','*'],['*','+'],['+','*'],
  190.             ['/','-'],['-','/'],['/','+'],['+','/']
  191.         ]
  192.         elif N==2 and self.LEVEL<3:plets=[
  193.             ['+','+'],['+','-'],['-','+'],['-','-'],]
  194.         return(plets)
  195.     
  196.     def generate_expressions(self):
  197.         triplets=self.get3x2x1x(3)#these currently rely on integer sort();could use sort.py on chars..?
  198.         doublets=self.get3x2x1x(2)
  199.         singlets=self.get3x2x1x(1)
  200.         operator_doublets=self.get_operator_plets(2)#a "2" here corresponds to 2 operators between a ("3") tripplet of numbers
  201.         operator_singlets=self.get_operator_plets(1)
  202.         current_submission_idx=0
  203.  
  204.         triplet_expressions=[]
  205.         for pdx in range(0,len(triplets)):
  206.             permutations=self.get3xPermutations(triplets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  207.             for perm in permutations:
  208.                 for odx in range(len(operator_doublets)):
  209.                     expr=[perm[0],operator_doublets[odx][0],perm[1],operator_doublets[odx][1],perm[2]]#save these
  210.                     value=self.evaluate(expr)
  211.                     triplet_expressions.append([pdx,odx,expr,value])
  212.         
  213.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  214.         """deactivating: this works, but takes too long (testing, not generating (here)) by brute force.
  215.  
  216.         #v2.0
  217.         wc_triplet_expressions=[]
  218.         
  219.         #wc_idx=0
  220.         for pdx in range(0,len(triplets)):
  221.             permutations=self.get3xPermutations(triplets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  222.             for perm in permutations:
  223.                 for odx in range(len(operator_doublets)):
  224.                     for val in range(16):
  225.                         expr=[`val`,operator_doublets[odx][0],perm[1],operator_doublets[odx][1],perm[2]]
  226.                         value=self.evaluate(expr)
  227.                         expr=['WC:'+`val`,operator_doublets[odx][0],perm[1],operator_doublets[odx][1],perm[2]]
  228.                         wc_triplet_expressions.append([pdx,odx,expr,value])
  229.         #wc_idx=1
  230.         for pdx in range(0,len(triplets)):
  231.             permutations=self.get3xPermutations(triplets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  232.             for perm in permutations:
  233.                 for odx in range(len(operator_doublets)):
  234.                     for val in range(16):
  235.                         expr=[perm[0],operator_doublets[odx][0],`val`,operator_doublets[odx][1],perm[2]]
  236.                         value=self.evaluate(expr)
  237.                         expr=[perm[0],operator_doublets[odx][0],'WC:'+`val`,operator_doublets[odx][1],perm[2]]
  238.                         wc_triplet_expressions.append([pdx,odx,expr,value])
  239.         #wc_idx=2
  240.         for pdx in range(0,len(triplets)):
  241.             permutations=self.get3xPermutations(triplets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  242.             for perm in permutations:
  243.                 for odx in range(len(operator_doublets)):
  244.                     for val in range(16):
  245.                         expr=[perm[0],operator_doublets[odx][0],perm[1],operator_doublets[odx][1],`val`]
  246.                         value=self.evaluate(expr)
  247.                         expr=[perm[0],operator_doublets[odx][0],perm[1],operator_doublets[odx][1],'WC:'+`val`]
  248.                         wc_triplet_expressions.append([pdx,odx,expr,value])
  249.         #wc_idx~operator[0]
  250.         for pdx in range(0,len(triplets)):
  251.             permutations=self.get3xPermutations(triplets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  252.             for perm in permutations:
  253.                 for odx in range(len(operator_doublets)):
  254.                     expr=[perm[0],operator_doublets[odx][0],perm[1],operator_doublets[odx][1],perm[2]]
  255.                     value=self.evaluate(expr)
  256.                     expr=[perm[0],'WC:'+operator_doublets[odx][0],perm[1],operator_doublets[odx][1],perm[2]]
  257.                     wc_triplet_expressions.append([pdx,odx,expr,value])
  258.         #wc_idx~operator[1]
  259.         for pdx in range(0,len(triplets)):
  260.             permutations=self.get3xPermutations(triplets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  261.             for perm in permutations:
  262.                 for odx in range(len(operator_doublets)):
  263.                     expr=[perm[0],operator_doublets[odx][0],perm[1],operator_doublets[odx][1],perm[2]]
  264.                     value=self.evaluate(expr)
  265.                     expr=[perm[0],operator_doublets[odx][0],perm[1],'WC:'+operator_doublets[odx][1],perm[2]]
  266.                     wc_triplet_expressions.append([pdx,odx,expr,value])
  267.         
  268.         print 'finished wc_triplet_expressions generation:',len(triplet_expressions),len(wc_triplet_expressions)
  269.         """
  270.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  271.         doublet_expressions=[]
  272.         for pdx in range(0,len(doublets)):
  273.             permutations=self.get2xPermutations(doublets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  274.             for perm in permutations:
  275.                 for odx in range(len(operator_singlets)):
  276.                     expr=[perm[0],operator_singlets[odx][0],perm[1]]
  277.                     value=self.evaluate(expr)
  278.                     doublet_expressions.append([pdx,odx,expr,value])
  279.         
  280.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  281.         wc_doublet_expressions=[]
  282.         #wc_idx=0
  283.         for pdx in range(0,len(singlets)):
  284.             for odx in range(len(operator_singlets)):
  285.                 for val in range(21):
  286.                     expr=[`val`+'.0',operator_singlets[odx][0],singlets[pdx][0]]
  287.                     value=self.evaluate(expr)
  288.                     expr=['WC:'+`val`+'.0',operator_singlets[odx][0],singlets[pdx][0]]
  289.                     wc_doublet_expressions.append([pdx,odx,expr,value])
  290.         #wc_idx=1
  291.         for pdx in range(0,len(singlets)):
  292.             for odx in range(len(operator_singlets)):
  293.                 for val in range(21):
  294.                     expr=[singlets[pdx][0],operator_singlets[odx][0],`val`+'.0']
  295.                     value=self.evaluate(expr)
  296.                     expr=[singlets[pdx][0],operator_singlets[odx][0],'WC:'+`val`+'.0']
  297.                     wc_doublet_expressions.append([pdx,odx,expr,value])
  298.  
  299.         #wc~operator:
  300.         for pdx in range(0,len(doublets)):
  301.             permutations=self.get2xPermutations(doublets[pdx])#permutations of idx+1 (i.e. 1,2,3 rather than 0,1,2)
  302.             for perm in permutations:
  303.                 for odx in range(len(operator_singlets)):
  304.                     expr=[perm[0],operator_singlets[odx][0],perm[1]]
  305.                     value=self.evaluate(expr)
  306.                     expr=[perm[0],'WC:'+operator_singlets[odx][0],perm[1]]
  307.                     wc_doublet_expressions.append([pdx,odx,expr,value])
  308.         #print 'wc_doublet_expressions=',wc_doublet_expressions
  309.         
  310.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  311.         #NEW: v2.0
  312.         #wc_idx=1 AND wc_idx=2
  313.         wc_wc_doublet_expressions=[]
  314.         for v1 in range(21):
  315.             for v2 in range(21):
  316.                 for odx in range(len(operator_singlets)):
  317.                     expr=[`v1`+'.0',operator_singlets[odx][0],`v2`+'.0']
  318.                     value=self.evaluate(expr)
  319.                     expr=['WC:'+`v1`+'.0',operator_singlets[odx][0],'WC:'+`v2`+'.0']
  320.                     wc_wc_doublet_expressions.append([0,odx,expr,value])#what did "pdx"(now "0") do?
  321.         
  322.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  323.         singlet_expressions=[]
  324.         for pdx in range(0,len(singlets)):
  325.             expr=[singlets[pdx][0]]
  326.             value=self.evaluate(expr[0])
  327.             singlet_expressions.append([pdx,None,expr,value])
  328.         #print 'singlet_expressions=',singlet_expressions
  329.         
  330.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  331.         wc_singlet_expressions=[]
  332.         #wc_idx=0
  333.         for pdx in range(0,21):#depends on game.LEVEL
  334.             expr=['WC:'+`pdx`+'.0']
  335.             value=pdx
  336.             wc_singlet_expressions.append([pdx,None,expr,value])
  337.         #print 'wc_singlet_expressions=',wc_singlet_expressions
  338.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  339.         self.triplet_expressions=triplet_expressions
  340.         self.doublet_expressions=doublet_expressions
  341.         self.singlet_expressions=singlet_expressions
  342.         #self.wc_triplet_expressions=wc_triplet_expressions
  343.         self.wc_doublet_expressions=wc_doublet_expressions
  344.         self.wc_wc_doublet_expressions=wc_wc_doublet_expressions
  345.         self.wc_singlet_expressions=wc_singlet_expressions
  346.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  347.         self.game.do_one_scratch()
  348.         
  349.  
  350.     def construct_submission(self,lhs_expressions,rhs_expressions):
  351.         #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$PERFECT
  352.         #doublet=wc_wc_doublet
  353.         #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$PERFECT
  354.         
  355.         stringValues=self.getAllStringValues()
  356.         
  357.         #print len(lhs_expressions)*len(rhs_expressions),' possible'
  358.         self.game.do_one_scratch()
  359.         for idx1 in range(len(lhs_expressions)):
  360.             for idx2 in range(len(rhs_expressions)):
  361.                 if lhs_expressions[idx1][3]==rhs_expressions[idx2][3]:
  362.                     #print 'combining:',lhs_expressions[idx1],rhs_expressions[idx2]
  363.                     combinedList=[]
  364.                     for idx in range(len(lhs_expressions[idx1][2])):
  365.                         #print 'idx1=',idx1,' idx=',idx
  366.                         combinedList.append(lhs_expressions[idx1][2][idx])
  367.                     combinedList.append('=')
  368.                     for idx in range(len(rhs_expressions[idx2][2])):
  369.                         combinedList.append(rhs_expressions[idx2][2][idx])
  370.                     ok=1
  371.                     for elem in combinedList:
  372.                             count=combinedList.count(elem)
  373.                             if elem.count('WC:'):#Then we don't want to check for it in stringValues!!
  374.                                 pass
  375.                             elif stringValues.count(elem)<count:
  376.                                 #print combinedList,elem,count,stringValues.count(elem)
  377.                                 ok=0
  378.                     if ok==1:
  379.                         rlist=self.game.localizer.localize(combinedList)
  380.                         if rlist:
  381.                             return(rlist)
  382.         return(None)
  383.                             
  384.     def generate_options(self):
  385.         triplet_expressions=self.triplet_expressions
  386.         doublet_expressions=self.doublet_expressions
  387.         singlet_expressions=self.singlet_expressions
  388.         #wc_triplet_expressions=self.wc_triplet_expressions
  389.         wc_doublet_expressions=self.wc_doublet_expressions
  390.         wc_wc_doublet_expressions=self.wc_wc_doublet_expressions
  391.         wc_singlet_expressions=self.wc_singlet_expressions
  392.         operator_doublets=self.operator_doublets
  393.         operator_singlets=self.operator_singlets
  394.         
  395.         LEVEL=self.LEVEL
  396.         #print 'tux generating options'    
  397.  
  398.         self.options=[]#the result of this function
  399.         tray=self.tray
  400.         spots=self.tray.get_spots()
  401.         
  402.         #board get 1 copy 1x str_val array in preparation of numerous brute-force localization attempts:
  403.         self.game.localizer.update_board_map()
  404.         
  405.         
  406.         num_commited=self.game.board.get_num_commited()
  407.         
  408.         if num_commited>3 and LEVEL>1:#SPARE LEVEL 1 BIG ENTRIES
  409.             rlist=self.construct_submission(triplet_expressions,wc_doublet_expressions)
  410.             if rlist:return(rlist)
  411.             rlist=self.construct_submission(wc_doublet_expressions,triplet_expressions)
  412.             if rlist:return(rlist)
  413.             rlist=self.construct_submission(triplet_expressions,wc_singlet_expressions)
  414.             if rlist:return(rlist)
  415.             rlist=self.construct_submission(wc_singlet_expressions,triplet_expressions)
  416.             if rlist:return(rlist)
  417.         
  418.         if num_commited>3:
  419.             rlist=self.construct_submission(doublet_expressions,wc_wc_doublet_expressions)
  420.             if rlist:return(rlist)
  421.             rlist=self.construct_submission(wc_wc_doublet_expressions,doublet_expressions)
  422.             if rlist:return(rlist)
  423.             rlist=self.construct_submission(wc_wc_doublet_expressions,singlet_expressions)
  424.             if rlist:return(rlist)
  425.             rlist=self.construct_submission(singlet_expressions,wc_wc_doublet_expressions)
  426.             if rlist:return(rlist)
  427.             rlist=self.construct_submission(wc_doublet_expressions,wc_doublet_expressions)
  428.             if rlist:return(rlist)
  429.             rlist=self.construct_submission(doublet_expressions,wc_doublet_expressions)
  430.             if rlist:return(rlist)
  431.             rlist=self.construct_submission(wc_doublet_expressions,doublet_expressions)
  432.             if rlist:return(rlist)
  433.         
  434.         rlist=self.construct_submission(wc_singlet_expressions,wc_doublet_expressions)
  435.         if rlist:return(rlist)
  436.         rlist=self.construct_submission(wc_doublet_expressions,wc_singlet_expressions)
  437.         if rlist:return(rlist)
  438.         rlist=self.construct_submission(doublet_expressions,wc_singlet_expressions)
  439.         if rlist:return(rlist)
  440.         rlist=self.construct_submission(wc_singlet_expressions,doublet_expressions)
  441.         if rlist:return(rlist)
  442.         rlist=self.construct_submission(singlet_expressions,wc_doublet_expressions)
  443.         if rlist:return(rlist)
  444.         rlist=self.construct_submission(wc_doublet_expressions,singlet_expressions)
  445.         if rlist:return(rlist)
  446.         rlist=self.construct_submission(wc_singlet_expressions,singlet_expressions)
  447.         if rlist:return(rlist)
  448.         rlist=self.construct_submission(singlet_expressions,wc_singlet_expressions)
  449.         if rlist:return(rlist)
  450.         else:return(None)
  451.  
  452.  
  453.     
  454.