Package Anomos :: Module PiecePicker
[hide private]
[frames] | no frames]

Source Code for Module Anomos.PiecePicker

  1  # This program is free software: you can redistribute it and/or modify 
  2  # it under the terms of the GNU General Public License as published by 
  3  # the Free Software Foundation, either version 3 of the License, or 
  4  # (at your option) any later version. 
  5  # 
  6  # This program is distributed in the hope that it will be useful, 
  7  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  8  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  9  # GNU General Public License for more details. 
 10  # 
 11  # You should have received a copy of the GNU General Public License 
 12  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 13   
 14  # Written by Bram Cohen 
 15   
 16  from random import randrange, shuffle, choice 
 17   
 18   
19 -class PiecePicker(object):
20
21 - def __init__(self, numpieces, config):
22 self.config = config 23 self.numpieces = numpieces 24 self.interests = [range(numpieces)] 25 self.pos_in_interests = range(numpieces) 26 self.numinterests = [0] * numpieces 27 self.have = [False] * numpieces 28 self.crosscount = [numpieces] 29 self.started = [] 30 self.seedstarted = [] 31 self.numgot = 0 32 self.scrambled = range(numpieces) 33 shuffle(self.scrambled)
34
35 - def got_have(self, piece):
36 numint = self.numinterests[piece] 37 self.crosscount[numint + self.have[piece]] -= 1 38 self.numinterests[piece] += 1 39 try: 40 self.crosscount[numint + 1 + self.have[piece]] += 1 41 except IndexError: 42 self.crosscount.append(1) 43 if self.have[piece]: 44 return 45 if numint == len(self.interests) - 1: 46 self.interests.append([]) 47 self._shift_over(piece, self.interests[numint], self.interests[numint + 1])
48
49 - def lost_have(self, piece):
50 numint = self.numinterests[piece] 51 self.crosscount[numint + self.have[piece]] -= 1 52 self.numinterests[piece] -= 1 53 self.crosscount[numint - 1 + self.have[piece]] += 1 54 if self.have[piece]: 55 return 56 self._shift_over(piece, self.interests[numint], self.interests[numint - 1])
57
58 - def _shift_over(self, piece, l1, l2):
59 p = self.pos_in_interests[piece] 60 l1[p] = l1[-1] 61 self.pos_in_interests[l1[-1]] = p 62 del l1[-1] 63 newp = randrange(len(l2) + 1) 64 if newp == len(l2): 65 self.pos_in_interests[piece] = len(l2) 66 l2.append(piece) 67 else: 68 old = l2[newp] 69 self.pos_in_interests[old] = len(l2) 70 l2.append(old) 71 l2[newp] = piece 72 self.pos_in_interests[piece] = newp
73
74 - def requested(self, piece, seed = False):
75 if piece not in self.started: 76 self.started.append(piece) 77 if seed and piece not in self.seedstarted: 78 self.seedstarted.append(piece)
79
80 - def complete(self, piece):
81 assert not self.have[piece] 82 self.have[piece] = True 83 self.crosscount[self.numinterests[piece]] -= 1 84 try: 85 self.crosscount[self.numinterests[piece] + 1] += 1 86 except IndexError: 87 self.crosscount.append(1) 88 self.numgot += 1 89 l = self.interests[self.numinterests[piece]] 90 p = self.pos_in_interests[piece] 91 l[p] = l[-1] 92 self.pos_in_interests[l[-1]] = p 93 del l[-1] 94 try: 95 self.started.remove(piece) 96 self.seedstarted.remove(piece) 97 except ValueError: 98 pass
99
100 - def next(self, havefunc, seed = False):
101 bests = None 102 bestnum = 2 ** 30 103 if seed: 104 s = self.seedstarted 105 else: 106 s = self.started 107 for i in s: 108 if havefunc(i): 109 if self.numinterests[i] < bestnum: 110 bests = [i] 111 bestnum = self.numinterests[i] 112 elif self.numinterests[i] == bestnum: 113 bests.append(i) 114 if bests: 115 return choice(bests) 116 if self.numgot < self.config['rarest_first_cutoff']: 117 for i in self.scrambled: 118 if havefunc(i): 119 return i 120 return None 121 for i in xrange(1, min(bestnum, len(self.interests))): 122 for j in self.interests[i]: 123 if havefunc(j): 124 return j 125 return None
126
127 - def am_I_complete(self):
128 return self.numgot == self.numpieces
129
130 - def bump(self, piece):
131 l = self.interests[self.numinterests[piece]] 132 pos = self.pos_in_interests[piece] 133 del l[pos] 134 l.append(piece) 135 for i in range(pos,len(l)): 136 self.pos_in_interests[l[i]] = i 137 try: 138 self.started.remove(piece) 139 self.seedstarted.remove(piece) 140 except ValueError: 141 pass
142