File indexing completed on 2024-04-21 04:01:52

0001 # -*- coding: utf-8 -*-
0002 
0003 """Copyright (C) 2009-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de>
0004 
0005 SPDX-License-Identifier: GPL-2.0
0006 
0007 """
0008 
0009 # See the user manual for a description of how to define rulesets.
0010 # Names and descriptions must be english and may only contain ascii chars.
0011 # The KDE translation teams will "automatically" translate name and
0012 # description into many languages.
0013 
0014 from rule import PredefinedRuleset
0015 from mi18n import i18nE, i18n
0016 
0017 
0018 class ClassicalChinese(PredefinedRuleset):
0019 
0020     """classical chinese rules, standard rules. Serves as a basis
0021     for local variants. This should be defined such that the
0022     sum of the differences to the local variants is minimized."""
0023 
0024     def __init__(self, name=None):
0025         PredefinedRuleset.__init__(
0026             self,
0027             name or i18nE('Classical Chinese standard'))
0028 
0029     def _initRuleset(self):
0030         """set the description"""
0031         self.description = i18n('Classical Chinese')
0032 
0033     def addManualRules(self):
0034         """those are actually winner rules but in the kajongg scoring mode they must be selected manually"""
0035         # applicable only if we have a concealed meld and a declared kong:
0036         self.winnerRules.createRule(
0037             'Last Tile Taken from Dead Wall',
0038             'FLastTileFromDeadWall||Olastsource=e', doubles=1,
0039             description=i18n('The dead wall is also called kong box: The last 16 tiles of the wall '
0040                              'used as source of replacement tiles'))
0041         self.winnerRules.createRule(
0042             'Last Tile is Last Tile of Wall',
0043             'FIsLastTileFromWall||Olastsource=z', doubles=1,
0044             description=i18n('Winner said Mah Jong with the last tile taken from the living end of the wall'))
0045         self.winnerRules.createRule(
0046             'Last Tile is Last Tile of Wall Discarded',
0047             'FIsLastTileFromWallDiscarded||Olastsource=Z', doubles=1,
0048             description=i18n('Winner said Mah Jong by claiming the last tile taken from the living end of the '
0049                              'wall, discarded by another player'))
0050         self.winnerRules.createRule(
0051             'Robbing the Kong', r'FRobbingKong||Olastsource=k', doubles=1,
0052             description=i18n('Winner said Mah Jong by claiming the 4th tile of a kong another player '
0053                              'just declared'), debug=True)
0054         self.winnerRules.createRule(
0055             'Mah Jongg with Original Call',
0056             'FMahJonggWithOriginalCall||Oannouncements=a', doubles=1,
0057             description=i18n(
0058                 'Just before the first discard, a player can declare Original Call meaning she needs only one '
0059                 'tile to complete the hand and announces she will not alter the hand in any way (except bonus tiles)'))
0060         self.winnerRules.createRule(
0061             'Dangerous Game', 'FDangerousGame||Opayforall',
0062             description=i18n('In some situations discarding a tile that has a high chance to help somebody to win '
0063                              'is declared to be dangerous, and if that tile actually makes somebody win, the discarder '
0064                              'pays the winner for all'))
0065         self.winnerRules.createRule(
0066             'Twofold Fortune', 'FTwofoldFortune||Oannouncements=t',
0067             limits=1, description=i18n('Kong after Kong: Declare Kong and a second Kong with the replacement '
0068                                        'tile and Mah Jong with the second replacement tile'))
0069         # limit hands:
0070         self.winnerRules.createRule(
0071             'Blessing of Heaven', 'FBlessingOfHeaven||Olastsource=1', limits=1,
0072             description=i18n('East says Mah Jong with the unmodified dealt tiles'))
0073         self.winnerRules.createRule(
0074             'Blessing of Earth', 'FBlessingOfEarth||Olastsource=1', limits=1,
0075             description=i18n('South, West or North says Mah Jong with the first tile discarded by East'))
0076         self.winnerRules.createRule(
0077             'East won nine times in a row', 'FEastWonNineTimesInARow||Orotate', limits=1,
0078             description=i18n('If that happens, East gets a limit score and the winds rotate'))
0079 
0080     def addPenaltyRules(self):
0081         """as the name says"""
0082         self.penaltyRules.createRule(
0083             'False Naming of Discard, Claimed for Mah Jongg and False Declaration of Mah Jongg',
0084             'Oabsolute payers=2 payees=2', points=-300)
0085 
0086     def addHandRules(self):
0087         """as the name says"""
0088         self.handRules.createRule(
0089             'Own Flower and Own Season',
0090             'FOwnFlowerOwnSeason',
0091             doubles=1)
0092         self.handRules.createRule('All Flowers', 'FAllFlowers', doubles=1)
0093         self.handRules.createRule('All Seasons', 'FAllSeasons', doubles=1)
0094         self.handRules.createRule(
0095             'Three Concealed Pongs',
0096             'FThreeConcealedPongs',
0097             doubles=1)
0098         self.handRules.createRule(
0099             'Long Hand', r'FLongHand||Oabsolute', points=0,
0100             description=i18n('The hand contains too many tiles'))
0101 
0102     def addParameterRules(self):
0103         """as the name says"""
0104         self.parameterRules.createRule(
0105             'Points Needed for Mah Jongg',
0106             'intminMJPoints',
0107             parameter=0)
0108         self.parameterRules.createRule(
0109             'Minimum number of doubles needed for Mah Jongg',
0110             'intminMJDoubles', parameter=0)
0111         self.parameterRules.createRule(
0112             'Points for a Limit Hand',
0113             'intlimit||Omin=1',
0114             parameter=500)
0115         self.parameterRules.createRule(
0116             'Play with the roof off', 'boolroofOff', parameter=False,
0117             description=i18n('Play with no upper scoring limit'))
0118         self.parameterRules.createRule(
0119             'Claim Timeout',
0120             'intclaimTimeout',
0121             parameter=10)
0122         self.parameterRules.createRule(
0123             'Size of Kong Box', 'intkongBoxSize', parameter=16,
0124             description=i18n('The Kong Box is used for replacement tiles when declaring kongs'))
0125         self.parameterRules.createRule(
0126             'Play with Bonus Tiles', 'boolwithBonusTiles', parameter=True,
0127             description=i18n('Bonus tiles increase the luck factor'))
0128         self.parameterRules.createRule(
0129             'Minimum number of rounds in game',
0130             'intminRounds',
0131             parameter=4)
0132         self.parameterRules.createRule(
0133             'number of allowed chows', 'intmaxChows', parameter=4,
0134             description=i18n('The number of chows a player may build'))
0135         self.parameterRules.createRule(
0136             'must declare calling hand',
0137             'boolmustDeclareCallingHand', parameter=False,
0138             description=i18n('Mah Jongg is only allowed after having declared to have a calling hand'))
0139         self.parameterRules.createRule(
0140             'Standard Rotation',
0141             'FStandardRotation||Orotate||Ointernal')
0142 
0143     def loadRules(self):
0144         """define the rules"""
0145         self.addParameterRules()  # must be first!
0146         self.addPenaltyRules()
0147         self.addHandRules()
0148         self.addManualRules()
0149         self.winnerRules.createRule(
0150             'Last Tile Completes Pair of 2..8',
0151             'FLastTileCompletesPairMinor',
0152             points=2)
0153         self.winnerRules.createRule(
0154             'Last Tile Completes Pair of Terminals or Honors',
0155             'FLastTileCompletesPairMajor', points=4)
0156         self.winnerRules.createRule(
0157             'Last Tile is Only Possible Tile',
0158             'FLastOnlyPossible',
0159             points=2)
0160         self.winnerRules.createRule(
0161             'Won with Last Tile Taken from Wall',
0162             'FLastFromWall',
0163             points=2)
0164 
0165         self.winnerRules.createRule(
0166             'Zero Point Hand', 'FZeroPointHand', doubles=1,
0167             description=i18n('The hand has 0 basis points excluding bonus tiles'))
0168         self.winnerRules.createRule('No Chow', 'FNoChow', doubles=1)
0169         self.winnerRules.createRule(
0170             'Only Concealed Melds',
0171             'FOnlyConcealedMelds',
0172             doubles=1)
0173         self.winnerRules.createRule(
0174             'False Color Game', 'FFalseColorGame', doubles=1,
0175             description=i18n('Only same-colored tiles (only bamboo/stone/character) '
0176                              'plus any number of winds and dragons'))
0177         self.winnerRules.createRule(
0178             'True Color Game', 'FTrueColorGame', doubles=3,
0179             description=i18n('Only same-colored tiles (only bamboo/stone/character)'))
0180         self.winnerRules.createRule(
0181             'Concealed True Color Game', 'FConcealedTrueColorGame',
0182             limits=1, description=i18n('All tiles concealed and of the same suit, no honors'))
0183         self.winnerRules.createRule(
0184             'Only Terminals and Honors', 'FOnlyMajors', doubles=1,
0185             description=i18n('Only winds, dragons, 1 and 9'))
0186         self.winnerRules.createRule('Only Honors', 'FOnlyHonors', limits=1,
0187                                     description=i18n('Only winds and dragons'))
0188         self.winnerRules.createRule(
0189             'Hidden Treasure', 'FHiddenTreasure', limits=1,
0190             description=i18n('Only hidden Pungs or Kongs, last tile from wall'))
0191         self.winnerRules.createRule(
0192             'Heads and Tails', 'FAllTerminals', limits=1,
0193             description=i18n('Only 1 and 9'))
0194         self.winnerRules.createRule(
0195             'Fourfold Plenty', 'FFourfoldPlenty', limits=1,
0196             description=i18n('4 Kongs'))
0197         self.winnerRules.createRule(
0198             'Three Great Scholars', 'FThreeGreatScholars', limits=1,
0199             description=i18n('3 Pungs or Kongs of dragons'))
0200         self.winnerRules.createRule('Four Blessings Hovering over the Door',
0201                                     'FFourBlessingsHoveringOverTheDoor', limits=1,
0202                                     description=i18n('4 Pungs or Kongs of winds'))
0203         self.winnerRules.createRule('Imperial Jade', 'FAllGreen', limits=1,
0204                                     description=i18n('Only green tiles: Green dragon and Bamboo 2,3,4,6,8'))
0205         self.winnerRules.createRule('Gathering the Plum Blossom from the Roof',
0206                                     'FGatheringPlumBlossomFromRoof', limits=1,
0207                                     description=i18n('Mah Jong with stone 5 from the dead wall'))
0208         self.winnerRules.createRule(
0209             'Plucking the Moon from the Bottom of the Sea', 'FPluckingMoon', limits=1,
0210             description=i18n('Mah Jong with the last tile from the wall being a stone 1'))
0211         self.winnerRules.createRule(
0212             'Scratching a Carrying Pole', 'FScratchingPole', limits=1,
0213             description=i18n('Robbing the Kong of bamboo 2'))
0214 
0215         # only hands matching an mjRule can win. Keep this list as short as
0216         # possible. If a special hand matches the standard pattern, do not put it here
0217         # All mjRule functions must have a winningTileCandidates() method
0218         self.mjRules.createRule(
0219             'Standard Mah Jongg',
0220             'FStandardMahJongg',
0221             points=20)
0222         # option internal makes it not show up in the ruleset editor
0223         self.mjRules.createRule(
0224             'Nine Gates', 'FNineGates', limits=1,
0225             description=i18n(
0226                 'A concealed hand in one color 1112345678999 plus last tile of this suit (from wall or discarded)'))
0227         self.mjRules.createRule(
0228             'Thirteen Orphans', 'FThirteenOrphans||Omayrobhiddenkong', limits=1,
0229             description=i18n('13 single tiles: All dragons, winds, 1, 9 and a 14th tile building a pair '
0230                              'with one of them'))
0231 
0232         # doubling melds:
0233         self.meldRules.createRule('Pung/Kong of Dragons', 'FDragonPungKong',
0234                                   explainTemplate='{meldName}', doubles=1)
0235         self.meldRules.createRule('Pung/Kong of Own Wind', 'FOwnWindPungKong',
0236                                   explainTemplate='{meldType} of Own Wind ({value})', doubles=1)
0237         self.meldRules.createRule(
0238             'Pung/Kong of Round Wind', 'FRoundWindPungKong',
0239             explainTemplate='{meldType} of Round Wind ({value})', doubles=1)
0240 
0241         # exposed melds:
0242         self.meldRules.createRule('Exposed Kong', 'FExposedMinorKong',
0243                                   explainTemplate='{meldName}', points=8)
0244         self.meldRules.createRule(
0245             'Exposed Kong of Terminals', 'FExposedTerminalsKong',
0246             explainTemplate='{meldName}', points=16)
0247         self.meldRules.createRule(
0248             'Exposed Kong of Honors', 'FExposedHonorsKong',
0249             explainTemplate='{meldName}', points=16)
0250 
0251         self.meldRules.createRule('Exposed Pung', 'FExposedMinorPung',
0252                                   explainTemplate='{meldName}', points=2)
0253         self.meldRules.createRule(
0254             'Exposed Pung of Terminals', 'FExposedTerminalsPung',
0255             explainTemplate='{meldName}', points=4)
0256         self.meldRules.createRule(
0257             'Exposed Pung of Honors', 'FExposedHonorsPung',
0258             explainTemplate='{meldName}', points=4)
0259 
0260         # concealed melds:
0261         self.meldRules.createRule('Concealed Kong', 'FConcealedMinorKong',
0262                                   explainTemplate='{meldName}', points=16)
0263         self.meldRules.createRule(
0264             'Concealed Kong of Terminals', 'FConcealedTerminalsKong',
0265             explainTemplate='{meldName}', points=32)
0266         self.meldRules.createRule(
0267             'Concealed Kong of Honors', 'FConcealedHonorsKong',
0268             explainTemplate='{meldName}', points=32)
0269 
0270         self.meldRules.createRule('Concealed Pung', 'FConcealedMinorPung',
0271                                   explainTemplate='{meldName}', points=4)
0272         self.meldRules.createRule(
0273             'Concealed Pung of Terminals', 'FConcealedTerminalsPung',
0274             explainTemplate='{meldName}', points=8)
0275         self.meldRules.createRule(
0276             'Concealed Pung of Honors', 'FConcealedHonorsPung',
0277             explainTemplate='{meldName}', points=8)
0278 
0279         self.meldRules.createRule('Pair of Own Wind', 'FOwnWindPair',
0280                                   explainTemplate='Pair of Own Wind ({value})', points=2)
0281         self.meldRules.createRule('Pair of Round Wind', 'FRoundWindPair',
0282                                   explainTemplate='Pair of Round Wind ({value})', points=2)
0283         self.meldRules.createRule('Pair of Dragons', 'FDragonPair',
0284                                   explainTemplate='{meldName}', points=2)
0285 
0286         # bonus tiles:
0287         self.meldRules.createRule('Flower', 'FFlower',
0288                                   explainTemplate='{meldName}', points=4)
0289         self.meldRules.createRule('Season', 'FSeason',
0290                                   explainTemplate='{meldName}', points=4)
0291 
0292 
0293 class ClassicalChineseDMJL(ClassicalChinese):
0294 
0295     """classical chinese rules, German rules"""
0296 
0297     def __init__(self, name=None):
0298         ClassicalChinese.__init__(
0299             self,
0300             name or i18nE('Classical Chinese DMJL'))
0301 
0302     def _initRuleset(self):
0303         """set the description"""
0304         ClassicalChinese._initRuleset(self)
0305         self.description = i18n(
0306             'Classical Chinese as defined by the Deutsche Mah Jongg Liga (DMJL) e.V.')
0307 
0308     def loadRules(self):
0309         ClassicalChinese.loadRules(self)
0310         # the squirming snake is only covered by standard mahjongg rule if
0311         # tiles are ordered
0312         self.mjRules.createRule(
0313             'Squirming Snake', 'FSquirmingSnake', limits=1,
0314             description=i18n('All tiles of same color. Pung or Kong of 1 and 9, pair of 2, 5 or 8 and two '
0315                              'Chows of the remaining values'))
0316         self.handRules.createRule(
0317             'Little Three Dragons', 'FLittleThreeDragons', doubles=1,
0318             description=i18n('2 Pungs or Kongs of dragons and 1 pair of dragons'))
0319         self.handRules.createRule(
0320             'Big Three Dragons', 'FBigThreeDragons', doubles=2,
0321             description=i18n('3 Pungs or Kongs of dragons'))
0322         self.handRules.createRule(
0323             'Little Four Joys', 'FLittleFourJoys', doubles=1,
0324             description=i18n('3 Pungs or Kongs of winds and 1 pair of winds'))
0325         self.handRules.createRule('Big Four Joys', 'FBigFourJoys', doubles=2,
0326                                   description=i18n('4 Pungs or Kongs of winds'))
0327 
0328         self.winnerRules['OnlyHonors'].doubles = 2
0329 
0330         self.penaltyRules.createRule(
0331             'False Naming of Discard, Claimed for Chow',
0332             points=-50)
0333         self.penaltyRules.createRule(
0334             'False Naming of Discard, Claimed for Pung/Kong',
0335             points=-100)
0336         self.penaltyRules.createRule(
0337             'False Declaration of Mah Jongg by One Player',
0338             'Oabsolute payees=3', points=-300)
0339         self.penaltyRules.createRule(
0340             'False Declaration of Mah Jongg by Two Players',
0341             'Oabsolute payers=2 payees=2', points=-300)
0342         self.penaltyRules.createRule(
0343             'False Declaration of Mah Jongg by Three Players',
0344             'Oabsolute payers=3', points=-300)
0345         self.penaltyRules.createRule(
0346             'False Naming of Discard, Claimed for Mah Jongg',
0347             'Oabsolute payees=3', points=-300)
0348 
0349 
0350 class ClassicalChineseBMJA(ClassicalChinese):
0351 
0352     """classical chinese rules, British rules"""
0353 
0354     def __init__(self, name=None):
0355         ClassicalChinese.__init__(
0356             self,
0357             name or i18nE('Classical Chinese BMJA'))
0358 
0359     def _initRuleset(self):
0360         """set the description"""
0361         ClassicalChinese._initRuleset(self)
0362         self.description = i18n(
0363             'Classical Chinese as defined by the British Mah-Jong Association')
0364 
0365     def addParameterRules(self):
0366         """those differ for BMJA from standard"""
0367         ClassicalChinese.addParameterRules(self)
0368         self.parameterRules['kongBoxSize'].parameter = 14
0369         self.parameterRules['maxChows'].parameter = 1
0370         self.parameterRules['limit'].parameter = 1000
0371         self.parameterRules['mustDeclareCallingHand'].parameter = True
0372 
0373     def loadRules(self):
0374         ClassicalChinese.loadRules(self)
0375         del self.winnerRules['ZeroPointHand']
0376         originalCall = self.winnerRules.pop('MahJonggwithOriginalCall')
0377         self.winnerRules.createRule(
0378             'Original Call', originalCall.definition, doubles=1,
0379             description=originalCall.description)
0380         del self.mjRules['NineGates']
0381         self.mjRules.createRule(
0382             'Gates of Heaven', 'FGatesOfHeaven', limits=1,
0383             description=i18n('All tiles concealed of same color: Values 1112345678999'
0384                              ' with one pair from 2 to 8 (last tile from wall or discarded)'))
0385         self.mjRules.createRule(
0386             'Wriggling Snake', 'FWrigglingSnake', limits=1,
0387             description=i18n('Pair of 1s and a run from 2 to 9 in the same suit with each of the winds'))
0388         self.mjRules.createRule(
0389             'Triple Knitting', 'FTripleKnitting', limits=0.5,
0390             description=i18n('Four sets of three tiles in the different suits and a pair: No Winds or Dragons'))
0391         self.mjRules.createRule('Knitting', 'FKnitting', limits=0.5,
0392                                 description=i18n('7 pairs of tiles in any 2 out of 3 suits; no Winds or Dragons'))
0393         self.mjRules.createRule(
0394             'All pair honors', 'FAllPairHonors', limits=0.5,
0395             description=i18n('7 pairs of 1s/9s/Winds/Dragons'))
0396         del self.handRules['OwnFlowerandOwnSeason']
0397         del self.handRules['ThreeConcealedPongs']
0398         self.meldRules.createRule('Own Flower', 'FOwnFlower', doubles=1)
0399         self.meldRules.createRule('Own Season', 'FOwnSeason', doubles=1)
0400         del self.winnerRules['LastTileTakenfromDeadWall']
0401         del self.winnerRules['HiddenTreasure']
0402         del self.winnerRules['FalseColorGame']
0403         del self.winnerRules['ConcealedTrueColorGame']
0404         del self.winnerRules['Eastwonninetimesinarow']
0405         del self.winnerRules['LastTileCompletesPairof28']
0406         del self.winnerRules['LastTileCompletesPairofTerminalsorHonors']
0407         del self.winnerRules['LastTileisOnlyPossibleTile']
0408         del self.winnerRules['TrueColorGame']
0409         del self.winnerRules['ThreeGreatScholars']
0410         self.winnerRules.createRule(
0411             'Buried Treasure', 'FBuriedTreasure', limits=1,
0412             description=i18n('Concealed pungs of one suit with winds/dragons and a pair'))
0413         self.winnerRules.createRule('Purity', 'FPurity', doubles=3,
0414                                     description=i18n('Only same-colored tiles (no chows, dragons or winds)'))
0415         self.winnerRules.createRule(
0416             'Three Great Scholars', 'FThreeGreatScholars||Onochow', limits=1,
0417             description=i18n('3 Pungs or Kongs of dragons plus any pung/kong and a pair'))
0418         orphans = self.mjRules.pop('ThirteenOrphans')
0419         self.mjRules.createRule(
0420             'The 13 Unique Wonders',
0421             orphans.definition,
0422             limits=1,
0423             description=orphans.description)
0424         self.handRules['AllFlowers'].score.doubles = 2
0425         self.handRules['AllSeasons'].score.doubles = 2
0426         self.penaltyRules.createRule(
0427             'False Naming of Discard, Claimed for Chow/Pung/Kong',
0428             points=-50)
0429         self.penaltyRules.createRule(
0430             'False Declaration of Mah Jongg by One Player',
0431             'Oabsolute payees=3', limits=-0.5)
0432         self.winnerRules.createRule(
0433             'False Naming of Discard, Claimed for Mah Jongg',
0434             'FFalseDiscardForMJ||Opayforall')
0435 
0436         self.loserRules.createRule(
0437             'Calling for Only Honors',
0438             'FCallingHand||Ohand=OnlyHonors',
0439             limits=0.4)
0440         self.loserRules.createRule(
0441             'Calling for Wriggling Snake',
0442             'FCallingHand||Ohand=WrigglingSnake',
0443             limits=0.4)
0444         self.loserRules.createRule(
0445             'Calling for Triple Knitting',
0446             'FCallingHand||Ohand=TripleKnitting',
0447             limits=0.2)
0448         self.loserRules.createRule(
0449             'Calling for Gates of Heaven', 'FCallingHand||Ohand=GatesofHeaven',
0450             limits=0.4)
0451         self.loserRules.createRule(
0452             'Calling for Knitting',
0453             'FCallingHand||Ohand=Knitting',
0454             limits=0.2)
0455         self.loserRules.createRule(
0456             'Calling for Imperial Jade',
0457             'FCallingHand||Ohand=ImperialJade',
0458             limits=0.4)
0459         self.loserRules.createRule(
0460             'Calling for The 13 Unique Wonders', 'FCallingHand||Ohand=The13UniqueWonders',
0461             limits=0.4)
0462         self.loserRules.createRule(
0463             'Calling for Three Great Scholars', 'FCallingHand||Ohand=ThreeGreatScholars',
0464             limits=0.4)
0465         self.loserRules.createRule(
0466             'Calling for All pair honors',
0467             'FCallingHand||Ohand=Allpairhonors',
0468             limits=0.2)
0469         self.loserRules.createRule(
0470             'Calling for Heads and Tails',
0471             'FCallingHand||Ohand=HeadsandTails',
0472             limits=0.4)
0473         self.loserRules.createRule(
0474             'Calling for Four Blessings Hovering over the Door',
0475             'FCallingHand||Ohand=FourBlessingsHoveringovertheDoor', limits=0.4)
0476         self.loserRules.createRule(
0477             'Calling for Buried Treasure',
0478             'FCallingHand||Ohand=BuriedTreasure',
0479             limits=0.4)
0480         self.loserRules.createRule(
0481             'Calling for Fourfold Plenty',
0482             'FCallingHand||Ohand=FourfoldPlenty',
0483             limits=0.4)
0484         self.loserRules.createRule(
0485             'Calling for Purity',
0486             'FCallingHand||Ohand=Purity',
0487             doubles=3)
0488 
0489 def load():
0490     """load predefined rulesets.
0491     add new predefined rulesets here.
0492     """
0493     assert not PredefinedRuleset.classes
0494     PredefinedRuleset.classes.add(ClassicalChineseDMJL)
0495     PredefinedRuleset.classes.add(ClassicalChineseBMJA)