"""Rule and strategic-policy regressions on the installed RLCard 1.2.0 engine.""" import importlib.util import pathlib import sys import unittest import rlcard from rlcard.games.doudizhu.judger import DoudizhuJudger ROOT = pathlib.Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / 'referee')) from play import points spec = importlib.util.spec_from_file_location('strategic', ROOT / 'field/strategic/agent.py') strategy = importlib.util.module_from_spec(spec) spec.loader.exec_module(strategy) def state(hand, legal, trace=(), me=1, left=(5, 5, 5)): return {'raw_legal_actions': legal, 'raw_obs': { 'self': me, 'landlord': 0, 'current_hand': hand, 'others_hand': '3456789TJQKA2BR', 'num_cards_left': list(left), 'trace': list(trace), 'actions': legal}} class Rules(unittest.TestCase): def test_fixed_landlord_and_pass_reset(self): env = rlcard.make('doudizhu') env.seed(23) s, p = env.reset() self.assertEqual(p, 0) self.assertEqual(s['raw_obs']['num_cards_left'], [20, 17, 17]) self.assertNotIn('pass', s['raw_legal_actions']) move = s['raw_obs']['current_hand'][0] s, p = env.step(move, raw_action=True) self.assertIn('pass', s['raw_legal_actions']) s, p = env.step('pass', raw_action=True) s, p = env.step('pass', raw_action=True) self.assertEqual(p, 0) self.assertNotIn('pass', s['raw_legal_actions']) def test_engine_combinations(self): legal = DoudizhuJudger.playable_cards_from_hand('3334445566TJQKA2BR') self.assertIn('3334445566', legal) self.assertIn('TJQKA', legal) self.assertIn('BR', legal) self.assertNotIn('JQKA2', legal) self.assertNotIn('333444BR', legal) # this RLCard variant excludes both jokers as wings def test_bombs_spring_and_zero_sum(self): scores, bombs, spring = points([(0, '3333'), (1, 'pass'), (2, 'pass'), (0, 'BR')], True) self.assertEqual((scores, bombs, spring), ([16, -8, -8], 2, True)) scores, _, spring = points([(0, '3'), (1, '4')], False) self.assertEqual(scores, [-4, 2, 2]) self.assertTrue(spring) self.assertEqual(sum(scores), 0) def test_farmer_does_not_overtake_partner_after_pass(self): s = state('5A', ['5', 'A', 'pass'], [(2, '4'), (0, 'pass')], me=1) self.assertEqual(strategy.Agent().step(s), 'pass') self.assertEqual(strategy.target(s['raw_obs']['trace']), (2, '4')) def test_finish_takes_priority_over_partner(self): self.assertEqual(strategy.Agent().step(state('AA', ['AA', 'pass'], [(2, '44')], me=1)), 'AA') def test_guard_landlord_with_one_card(self): s = state('3AR', ['A', 'R', 'pass'], [(1, 'K')], me=2, left=(1, 3, 3)) self.assertEqual(strategy.Agent().step(s), 'R') def test_plan_keeps_straight_and_plays_attachments(self): hand = '3334456789' s = state(hand, sorted(DoudizhuJudger.playable_cards_from_hand(hand)), me=0, left=(10, 17, 17)) self.assertIn(strategy.Agent().step(s), ['33344', '56789']) def test_nibble_subset_check_does_not_borrow(self): self.assertTrue(strategy.contains(strategy.mask('33344'), strategy.mask('334'))) self.assertFalse(strategy.contains(strategy.mask('344'), strategy.mask('334'))) if __name__ == '__main__': unittest.main()