home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 124 / cd-rom 124.iso / edu / tuxmath / tuxmathscrabble / asymptopia / Validator.py < prev    next >
Encoding:
Python Source  |  2003-11-09  |  10.4 KB  |  324 lines

  1. """
  2. /***************************************************************************
  3.  
  4.     Author             :Charles B. Cosse 
  5.     
  6.     Email            :ccosse@asymptopia.com
  7.                     
  8.                     
  9.     Copyright        :(C) 2002,2003 Asymptopia Software.
  10.     
  11.  ***************************************************************************/
  12. /***************************************************************************
  13.                           Validator.py
  14.  
  15.  ***************************************************************************/
  16.  
  17. /***************************************************************************
  18.  *                                                                         *
  19.  *   This program is free software; you can redistribute it and/or modify  *
  20.  *   it under the terms of the GNU General Public License as published by  *
  21.  *   the Free Software Foundation; either version 2 of the License, or     *
  22.  *   (at your option) any later version. (Please note that if you use this *
  23.  *   code you must give credit by including the Author and Copyright       *
  24.  *   info at the top of this file).                                        *
  25.  ***************************************************************************/
  26. """
  27.  
  28. import os, pygame
  29. from pygame.locals import *
  30.  
  31. class Validator:
  32.     """Validator has game model.
  33.     
  34.     """
  35.     def __init__(self,board,game):
  36.         self.board=board
  37.         self.game=game#only for playerscore update
  38.         
  39.     def validate(self,submission):
  40.         if len(submission)==0:return(0)
  41.         board=self.board
  42.         #print submission
  43.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  44.         #need to find head,row,col,len and set spot variables accordingly:
  45.         
  46.         MinM=board.M;MinN=board.N
  47.         
  48.         #this handles row/col both:(we want smallest M,N)
  49.         for spot in submission:
  50.             if spot.M<=MinM and spot.N<=MinN:
  51.                 MinM=spot.M
  52.                 MinN=spot.N
  53.         #print 'preliminary: MinM,MinN=',MinM,MinN
  54.         
  55.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  56.         #Check if anything to LHS or Above
  57.         try_above=1
  58.         #LHS
  59.         while 1:
  60.             if MinN==0:break
  61.             elif board.get_spotMN(MinM,MinN-1).guest !=None:
  62.                 MinN=MinN-1
  63.                 try_above=0
  64.             else:break
  65.         #Above:
  66.         while 1:
  67.             if not try_above:break
  68.             elif MinM==0:break
  69.             elif board.get_spotMN(MinM-1,MinN).guest !=None:
  70.                 MinM=MinM-1
  71.             else:break
  72.         #print 'final MinM,MinN=',MinM,MinN
  73.             
  74.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  75.         #Get MaxM,N of submission (so can check RHS and Below):
  76.         
  77.         MaxM=0;MaxN=0
  78.     
  79.         #this handles row/col both:(we want largest M,N)
  80.         for spot in submission:
  81.             if spot.M>=MaxM and spot.N>=MaxN:
  82.                 MaxM=spot.M
  83.                 MaxN=spot.N
  84.         #print 'preliminary: MaxM,MaxN=',MaxM,MaxN
  85.         
  86.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  87.         #*************NOTE: MaxM,N possible=board.M-1,N-1******************
  88.         #Check if anything to RHS or Below
  89.         #RHS:
  90.         try_below=1
  91.         while 1:
  92.             #print 'checking RHS: MaxM,MaxN,board.M,N=',MaxM,MaxN,board.M,board.N
  93.             if MaxN==board.N-1:break
  94.             elif board.get_spotMN(MaxM,MaxN+1).guest !=None:
  95.                 MaxN=MaxN+1
  96.                 try_below=0
  97.             else:break
  98.         #Below:
  99.         while 1:
  100.             #print 'checking Below: MaxM,MaxN,board.M,N=',MaxM,MaxN,board.M,board.N
  101.             if not try_below:break
  102.             elif MaxM==board.M-1 :break
  103.             elif board.get_spotMN(MaxM+1,MaxN).guest !=None:
  104.                 MaxM=MaxM+1
  105.             else:break
  106.         #print 'final MaxM,MaxN=',MaxM,MaxN
  107.         
  108.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  109.         #can put exprtype determination here, no?
  110.         if MaxM-MinM>0 and MaxN-MinN>0:return(0)#can't be both types
  111.         elif MaxM-MinM>0:exprtype='col'
  112.         elif MaxN-MinN>0:exprtype='row'
  113.         elif MaxN-MinN==0:
  114.             #print 'That\'s Not An Equation!'
  115.             return(0)
  116.         else:
  117.             #print 'THIS SHOULD NOT HAPPEN(and this else clause should be able to be removed)!!!!!!!!!!!'
  118.             return(0)
  119.         #print 'exprtype=',exprtype
  120.         
  121.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  122.         #Check continuous between Min/Max
  123.         if exprtype=='row':
  124.             #print 'row row row row row row row'
  125.             for idx in range(MinN,MaxN+1):
  126.                 this_idx_okay=0
  127.                 #print ' idx=',idx,
  128.                 #one of either (submission[*].N==idx) or (board[Min/MaxM][idx].guest !=None) must be true:
  129.                 for spot in submission:
  130.                     if spot.N==idx:this_idx_okay=1
  131.                 if board.get_spotMN(MinM,idx).guest!=None:this_idx_okay=1
  132.                 if this_idx_okay==0:
  133.                     #print 'ROWGAPROWGAPROWGAPROWGAPROWGAPROWGAPROWGAPROWGAP: ->',idx
  134.                     return(0)
  135.                 
  136.         elif exprtype=='col':
  137.             #print 'col col col col col col col'
  138.             for idx in range(MinM,MaxM+1):
  139.                 this_idx_okay=0
  140.                 #print ' idx=',idx,
  141.                 #one of either (submission[*].N==idx) or (board[Min/MaxM][idx].guest !=None) must be true:
  142.                 for spot in submission:
  143.                     if spot.M==idx:this_idx_okay=1
  144.                 if board.get_spotMN(idx,MinN).guest!=None:this_idx_okay=1
  145.                 if this_idx_okay==0:
  146.                     #print 'COLGAPCOLGAPCOLGAPCOLGAPCOLGAPCOLGAPCOLGAPCOLGAP: ->',idx
  147.                     return(0)
  148.             
  149.         """
  150.         At this point, if this_idx_okay==0 then we can throw submission back -> tray because you can't
  151.         do two separate equations in a turn. One point that we might ought to have handled already: What
  152.         if the submission involved a row and a column? (Can't think of example where possible, but not 
  153.         sure its not) Hence above "if not valid, return(0)". Okay, i guess the gut-feelings i'm having
  154.         that such cases exist are if we enter something into a corner (which would necessarily be an
  155.         equal sign!), but would then be working 2 equations at once -- what we/i decided not to support,
  156.         at least at first.
  157.         """
  158.         
  159.         
  160.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  161.         #Build the expression -> string
  162.         expr=''
  163.         if exprtype=='row':
  164.             for idx in range(MinN,MaxN+1):
  165.                 if board.get_spotMN(MinM,idx).guest!=None:
  166.                     expr=expr+board.get_spotMN(MinM,idx).guest.str_val
  167.                     continue
  168.                 else:
  169.                     for spot in submission:
  170.                         if spot.N==idx:
  171.                             expr=expr+spot.guest.str_val
  172.                             continue
  173.         elif exprtype=='col':
  174.             for idx in range(MinM,MaxM+1):
  175.                 if board.get_spotMN(idx,MinN).guest!=None:
  176.                     expr=expr+board.get_spotMN(idx,MinN).guest.str_val
  177.                     #continue
  178.                 else:
  179.                     for spot in submission:
  180.                         if spot.M==idx:
  181.                             #print 'requesting idx,MinN=',idx,MinN
  182.                             expr=expr+spot.guest.str_val
  183.                             #continue
  184.         
  185.         
  186.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  187.         #Verify 1)N is odd 2)alternating operators 3) at least one equals sign 4) replace = w/ ==
  188.         #this is interpreting "10" as length(10)=2 -> odd,bailing...fixme!
  189.         #fixed to handle 10,11,12,13...can add more if desired.
  190.         
  191.         #v2.0: allowing division, but 3/9=0 for integers, so fixing...
  192.         
  193.         if expr.count('=')==0:
  194.             #print 'bailing because no = sign found'
  195.             return(0)
  196.         
  197.         #print expr
  198.         for even_value in [0,2,4,6,8,10,12,14,16,18,20]:
  199.             length=len(expr)#-expr.count('.0')#division fix -- didn't work. current problem is here <-
  200.             if expr.count('10'):length=length-expr.count('10')
  201.             if expr.count('11'):length=length-expr.count('11')
  202.             if expr.count('12'):length=length-expr.count('12')
  203.             if expr.count('13'):length=length-expr.count('13')
  204.             if expr.count('14'):length=length-expr.count('14')
  205.             if expr.count('15'):length=length-expr.count('15')
  206.             if expr.count('20'):length=length-expr.count('20')
  207.             #print 'length_02=',length
  208.             if length==even_value:
  209.                 #print 'bailing because even value'
  210.                 return(0)
  211.         
  212.         
  213.         #alternating ops, no first/last opps
  214.         #commenting-out this section: still fails to evaluate, so okay.
  215.         """
  216.         list_expr=list(expr)
  217.         ops=['+','-','*','/','=']
  218.         should_be_op=0
  219.         for idx in range(len(list_expr)):
  220.             if should_be_op==0:
  221.                 try:rval=eval(list_expr[idx])
  222.                 except:
  223.                     print 'bail 1'
  224.                     return(0)
  225.             else:
  226.                 if ops.count(list_expr[idx])==0:
  227.                     print 'bail 2'
  228.                     return(0)
  229.             if should_be_op==0:should_be_op=1
  230.             else:should_be_op=0
  231.         """
  232.         
  233.         expr=expr.replace('=','==')#last step before evaluating!
  234.         
  235.         #evaluate it:
  236.         #print 'EXPRESSION=',expr
  237.         try:rval=eval(expr)
  238.         except:return(0)
  239.         if rval==0:return(0)
  240.         
  241.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  242.         head_spot=None
  243.         for spot in submission:#was head in submission?
  244.             if spot.M==MinM and spot.N==MinN:head_spot=spot
  245.         if not head_spot:#then head must have been on board.
  246.             head_spot=board.get_spotMN(MinM,MinN)
  247.                 
  248.         head_spot.AMHEAD=1
  249.         if exprtype=='row':
  250.             head_spot.AMROWEXPR=1
  251.             head_spot.ROWEXPRLENGTH=MaxN-MinN+1
  252.         if exprtype=='col':
  253.             head_spot.AMCOLEXPR=1
  254.             head_spot.COLEXPRLENGTH=MaxM-MinM+1
  255.         
  256.         #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  257.         #did this submission affect any HEADS in it's range? Check-and-update!
  258.         if exprtype=='row':
  259.             #self.game.playerscore=self.game.playerscore+(MaxN-MinN+1)
  260.             multiplier=1
  261.             score=0
  262.             for nidx in range(MinN,MaxN+1):
  263.                     spot2check=board.get_spotMN(MinM,nidx)
  264.                     if spot2check.TYPE=='2XL':score=score+2
  265.                     elif spot2check.TYPE=='2XW':
  266.                         score=score+1
  267.                         multiplier=multiplier*2
  268.                     elif spot2check.TYPE=='3XL':score=score+3
  269.                     elif spot2check.TYPE=='3XW':
  270.                         score=score+1
  271.                         multiplier=multiplier*3
  272.                     else:score=score+1
  273.  
  274.             score=score*multiplier
  275.             #print 'score=',score
  276.             self.game.playerscore=self.game.playerscore+score
  277.  
  278.             for n in range(MinN+1,MaxN+1):#don't overwrite new head (hence * MinN+1 *)
  279.                 #only bother if on board
  280.                 if board.check4guest(MinM,n):
  281.                     spot2check=board.get_spotMN(MinM,n)
  282.                     
  283.                     if spot2check.AMHEAD and spot2check.AMROWEXPR:
  284.                         spot2check.AMROWEXPR=0
  285.                         spot2check.ROWEXPRLENGTH=0
  286.                         #if also COLHEAD then don't unset AMHEAD, else do!
  287.                         if spot2check.AMCOLEXPR:pass
  288.                         else:spot2check.AMHEAD=0
  289.             
  290.                         
  291.         if exprtype=='col':
  292.             #self.game.playerscore=self.game.playerscore+(MaxN-MinN+1)
  293.             multiplier=1
  294.             score=0
  295.             for midx in range(MinM,MaxM+1):
  296.                     spot2check=board.get_spotMN(midx,MinN)
  297.                     if spot2check.TYPE=='2XL':score=score+2
  298.                     elif spot2check.TYPE=='2XW':
  299.                         score=score+1
  300.                         multiplier=multiplier*2
  301.                     elif spot2check.TYPE=='3XL':score=score+3
  302.                     elif spot2check.TYPE=='3XW':
  303.                         score=score+1
  304.                         multiplier=multiplier*3
  305.                     else:score=score+1
  306.                     
  307.             score=score*multiplier
  308.             #print 'score=',score
  309.             self.game.playerscore=self.game.playerscore+score
  310.             
  311.             for m in range(MinM+1,MaxM+1):#don't overwrite new head (hence * MinN+1 *)
  312.                 #only bother if on board
  313.                 if board.check4guest(m,MinN):
  314.                     spot2check=board.get_spotMN(m,MinN)
  315.                     
  316.                     if spot2check.AMHEAD and spot2check.AMCOLEXPR:
  317.                         spot2check.AMCOLEXPR=0
  318.                         spot2check.COLEXPRLENGTH=0
  319.                         #if also ROWHEAD then don't unset AMHEAD, else do!
  320.                         if spot2check.AMROWEXPR:pass
  321.                         else:spot2check.AMHEAD=0
  322.             
  323.         return(1)
  324.