-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathRulesEngine.py
More file actions
109 lines (93 loc) · 3.26 KB
/
RulesEngine.py
File metadata and controls
109 lines (93 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python
from collections import namedtuple
import random
import sys
from bots.SampleBot import SampleBot
Tile = namedtuple('Tile','value color')
bots = [SampleBot('1'),SampleBot('2'),SampleBot('3'),SampleBot('4')]
class RulesEngine:
"""
Implementation of a Rummikub rules engine for testing strategy bots
Attributes:
colors (set): possible colors for a tile
values (set): possible numbers for a tile
instances (int): number of tile instances
tiles (list): available tiles
bots (list): bots playing in the tournament
"""
def __init__(self,bots):
self.bots = bots
random.shuffle(self.bots)
self.make_tiles()
self.public_space = []
self.winner = None
def deal(self,tile_count=14):
"""Deal the appropriate number of tiles to each bot"""
for b in self.bots:
hand = self.tiles[-tile_count:]
self.tiles = self.tiles[:-tile_count]
b.hand = hand
def draw(self,bot):
"""Draw a tile if unable or unwilling to play"""
try:
tile = self.tiles.pop()
bot.hand.append(tile)
except:
print("No more tiles")
def play(self,bot):
"""Test bot strategy"""
self.public_space = bot.play(self.public_space)
for block in self.public_space:
if not self.validate_block(block):
print("%s is disqualified for returning an illegal configuration" % bot.name)
sys.exit()
if bot.ending_tiles >= bot.starting_tiles:
print("Player %s draws a tile." % bot.name)
self.draw(bot)
else:
print("Player: %s, starting_hand: %s, ending_tiles: %s." % (bot.name, str(bot.starting_tiles), str(bot.ending_tiles)))
pass
if bot.ending_tiles == 0:
self.winner = bot.name
print("Player",bot.name,'wins')
def validate_block(self,block):
"""Validate block of tiles as a run(straight flush) or group(same value color combination)"""
if len(block) < 3:
return False
vals = []
colors = []
for tile in block:
colors.append(tile.color)
vals.append(tile.value)
if len(set(colors)) > 1:
return len(set(vals)) == 1 and len(vals) == len(set(colors))
vals.sort()
for i in range(len(vals) - 1):
if vals[i] + 1 <> vals[i + 1]:
return False
return True
def make_tiles(self):
"""Create the tiles to be used in the game"""
self.colors = {'Red','Yellow','Blue','Black'}
self.values = {x + 1 for x in range(13)}
self.instances = 2
tiles = []
for v in self.values:
for c in self.colors:
tiles.append(Tile(v,c))
tiles.append(Tile(0,'Wild'))
self.tiles = self.instances * tiles
random.shuffle(self.tiles)
def main():
g = RulesEngine(bots)
g.deal()
while g.winner is None and g.tiles:
for b in g.bots:
g.play(b)
if g.winner:
break
if len(g.tiles) == 0:
print('Out of tiles!')
break
if __name__ == '__main__':
main()