# mille

committed 27f76fb

Save/restore now works at any user prompt!

# mille.py

` #	* if he can't play any of his cards but safeties,`
` #	  then at the end of the game he sees you discard,`
` #	  he'll play all his safeties.`
`-#   * when deciding to continue, if by not continuing`
`-#	  we will win the entire game, DON'T CONTINUE`
`+#   * when deciding to continue,`
`+#		* if by not continuing we will win the entire game, DON'T CONTINUE`
`+#		* consider how many safeties we/they have, Right Of Way counts 2x (3x?)`
`+#		* consider the delta in miles`
` #`
` # smart computer player`
` #	* calculates odds on whether a card is still in the deck / in opponent's hand`
` 	def mileage(self):`
` 		return 0`
` `
`-	def keep_playing(self):`
`-		return True`
`-`
` 	def turn(self):`
` 		pass`
` 	`
`-	def hand_end(self):`
`+	def game_end(self, winner):`
`+		pass`
`+`
`+	def hand_end(self, winner):`
` 		pass`
` `
` `
` 		self.players = []`
` 		self.games_played = 0`
` 		self.hands_played = 0`
`-`
`-	attributes = "hands_played games_played".split()`
`+		self.state = None`
`+		self.winner = None`
`+`
`+	attributes = "hands_played games_played state winner".split()`
` `
` 	def __getstate__(self):`
` 		global savegame_revision`
` `
` 		try:`
` 			while True:`
`+				if self.state == "game end":`
`+					winner = unpickle_player(self.winner)`
`+					assert self.game`
`+					for player in self.game.players:`
`+						player.game_end(winner)`
`+					self.state = None`
`+					self.winner = None`
`+					self.game = None`
`+					continue`
`+`
` 				self.start_game()`
` 				winner = self.game.play()`
`+`
`+				self.state = "game end"`
`+				self.winner = pickle_player(winner)`
`+`
`+				series.games_played += 1`
` 				for p, game_player in zip(self.players, self.game.players):`
` 					p.total_score += game_player.total_score`
` 					p.highest_score = max(p.highest_score, game_player.total_score)`
` 					if game_player == winner:`
` 						p.games_won += 1`
`-					print(game_player.name, "lifetime games won: {} total score: {}".format(p.games_won, p.total_score))`
`-				self.game = None`
`-				print()`
`+				continue`
`+`
` `
` 		except KeyboardInterrupt as e:`
` 			self.save_game()`
` 		self.players = []`
` 		self.hand = None`
` 		self.round = 0`
`+		self.state = None`
`+		self.winner = None`
` `
` 	def add_player(self, player):`
` 		self.players.append(player)`
` `
`+	attributes = "round state winner".split()`
`+`
` 	def __getstate__(self):`
`-		players = [pickle.dumps(p) for p in self.players]`
`-`
`-		return {`
`+		d = {`
` 			"random" : random.getstate(),`
`-			"players" : players,`
`+			"players" : [pickle.dumps(p) for p in self.players],`
` 			"hand" : pickle.dumps(self.hand),`
`-			"round" : self.round,`
` 			}`
`+		for attr in self.attributes:`
`+			d[attr] = getattr(self, attr)`
`+		return d`
` `
` 	def __setstate__(self, state):`
` 		random.setstate(state["random"])`
` 		self.players = [pickle.loads(p) for p in state["players"]]`
` 		self.hand = pickle.loads(state["hand"])`
`-		self.hand.game = self`
`-		self.round = state["round"]`
`+		if self.hand:`
`+			self.hand.game = self`
`+		for attr in self.attributes:`
`+			setattr(self, attr, state[attr])`
` `
` 	def unpickle(self):`
` 		if self.hand:`
` 		self.original_players = list(self.players)`
` `
` 		while True:`
`+			if self.state == "hand end":`
`+				winner = unpickle_player(self.winner)`
`+`
`+				for player in self.original_players:`
`+					player.hand_end(winner)`
`+`
`+				self.round += 1`
`+				self.hand = None`
`+`
`+				self.state = None`
`+				self.winner = None`
`+`
`+				if any((p for p in self.players if p.total_score >= 5000)):`
`+					p1, p2 = self.players`
`+					if p1.total_score == p2.total_score:`
`+						# a tie game! play another hand!`
`+						continue`
`+					return winner`
`+`
`+				continue`
`+`
` 			self.start_hand()`
` 			self.hand.play()`
` `
`-			if any((p for p in self.players if p.total_score >= 5000)):`
`-				break`
`-			for player in self.original_players:`
`-				player.hand_end()`
`-`
`-			self.round += 1`
`-			self.hand = None`
`-`
`-		print()`
`-`
`-		winner = None`
`-		p1, p2 = self.players`
`-		if p1.total_score == p2.total_score:`
`-			print("Game is a tie!  Golly, that's unusual!")`
`-		else:`
`-			winner = p1 if p1.total_score > p2.total_score else p2`
`-			screed = """`
`-Gentlemen!  You've both worked very hard.  And in a way you're both winners.`
`-But--in another, more accurate way--{winner.name} is the winner.`
`-			""".format(winner=winner)`
`-			print(screed)`
`-			series.games_played += 1`
`-`
`-		print()`
`-		return winner`
`+			p1, p2 = self.players`
`+			if p1.total_score == p2.total_score:`
`+				winner = None`
`+			elif p1.total_score > p2.total_score:`
`+				winner = p1`
`+			else:`
`+				winner = p2`
`+`
`+			self.winner = pickle_player(winner)`
`+			self.state = "hand end"`
`+			series.hands_played += 1`
` `
` `
` class Hand:`
` 				assert len(player.cards) == 5`
` 			else:`
` 				assert len(player.cards) <= 5`
`+`
` 		winner = None`
` 		if not self.current_player:`
` 			self.current_player = next(players)`
` 			# go to next player`
` 			self.current_player = next(players)`
` `
`-		winner, lost_by_points = self.print_scores()`
`-		for p in self.game.original_players:`
`+		if winner and (not winner.other().mileage()):`
`+			series.players[series.game.players.index(winner)].shutouts += 1`
`+`
`+		for p in self.game.players:`
` 			p.total_score += p.score().score`
` `
`-		if winner:`
`-			extra = ""`
`-			if lost_by_points:`
`-				extra = " Which is weird, because " + winner.other().name + " got more points."`
`-			print(winner.name, "wins the hand!", extra)`
`-			if not winner.other().mileage():`
`-				series.players[series.game.players.index(winner)].shutouts += 1`
`-				print("And it's a shutout, #{} for {}!".format(series.players[series.game.players.index(winner)].shutouts, winner.name))`
`-		else:`
`-			print("Nobody won the hand.")`
`-`
`-		series.hands_played += 1`
`-`
` 	ScoresResult = namedtuple("ScoresResult", "winner lost_by_points")`
` 	def print_scores(self):`
` 		scores = {}`
` 			totals = [divider]`
` 			totals.append("             hand total ... " + str(score).rjust(4))`
` 			scores[p] = score`
`-			totals.append("             game total ... " + str(p.total_score + score).rjust(4))`
`+			totals.append("             game total ... " + str(p.total_score).rjust(4))`
` 			all_comments.append(comments)`
` 			all_totals.append(totals)`
` 			if p.won():`
` 	sys.stdout.flush()`
` 	return c`
` `
`-def yes_no(prompt):`
`-	return getch(prompt + " [y]es or [n]o>", "yn") == "y"`
`-`
` `
` def pile_repr(pile):`
` 	s = repr(pile[-1]) if pile else ''`
` 		super().__init__(*a, **kw)`
` 		self.last_drawn = None`
` 		self.name = getpass.getuser()`
`+		self.state = None`
` `
` 	def __getstate__(self):`
` 		return {`
` 			"super" : super().__getstate__(),`
` 			"last_drawn" : card_to_string.get(self.last_drawn),`
`+			"state" : self.state,`
` 		}`
` `
` 	def __setstate__(self, state):`
` 		super().__setstate__(state["super"])`
` 		self.last_drawn = string_to_card.get(state["last_drawn"])`
`-`
`-	def keep_playing(self):`
`-		return yes_no("Keep playing?")`
`-`
`-	def hand_end(self):`
`-		print()`
`+		self.state = state["state"]`
`+`
`+	def space_to_continue(self):`
` 		print()`
` 		getch("Press [space] to continue > ", " ")`
` `
`+	def hand_end(self, winner):`
`+		series.game.hand.print_scores()`
`+		if winner:`
`+			extra = ""`
`+			lost_by_points = winner.score() < winner.other().score()`
`+			if lost_by_points:`
`+				extra = " Which is weird, because " + winner.other().name + " got more points."`
`+			print(winner.name, "wins the hand!", extra)`
`+			if not winner.other().mileage():`
`+				print("And it's a shutout, #{} for {}!".format(series.players[series.game.players.index(winner)].shutouts, winner.name))`
`+		else:`
`+			print("Nobody won the hand.")`
`+`
`+		self.space_to_continue()`
`+`
`+	def game_end(self, winner):`
`+		if not winner:`
`+			print("Game is a tie!  Golly, that's unusual!")`
`+		else:`
`+			screed = """`
`+Gentlemen!  You've both worked very hard.  And in a way you're both winners.`
`+But--in another, more accurate way--{winner.name} is the winner.`
`+			""".format(winner=winner)`
`+			print(screed)`
`+		for p, game_player in zip(series.players, series.game.players):`
`+			print(game_player.name, "lifetime games won: {} total score: {}".format(p.games_won, p.total_score))`
`+		self.space_to_continue()`
`+`
` 	def turn(self):`
` 		hand = self.hand`
` 		other = self.other()`
` `
`-		while self.cards:`
`-			print("deck", str(len(hand.deck)).rjust(3) + "/" + str(len(hand.original_deck)), "       discard |" + pile_repr(hand.discard.pile) + "|")`
`-			print("         total|hand    miles|battlepile|speed pile|safeties")`
`-			def stats(player):`
`-				strings = [player.name.ljust(8)[:8]]`
`-				add = strings.append`
`-`
`-				score = player.score()[0]`
`-`
`-				add(" ")`
`-				add(str(score + player.total_score).rjust(5))`
`-`
`-				add("|")`
`-				add(str(score).rjust(4))`
`-`
`-				add("    ")`
`-				add(str(player.mileage()).rjust(4))`
`-`
`-				add(" .:"[player.two_hundreds()])`
`-`
`-				add("|")`
`-				add(pile_repr(player.battle_pile))`
`-`
`-				add("|")`
`-				add(pile_repr(player.speed_pile))`
`-`
`-				add("|")`
`-				add(safeties_repr(player))`
`-`
`-				print("".join(strings))`
`-`
`-			stats(other)`
`-			stats(self)`
`-`
`-			line1 = []`
`-			line2 = []`
`-			highlight = self.last_drawn`
`-			before = fill = after = " "`
`-			just_before = " "`
`-			for i, card in enumerate(self.cards, 1):`
`-				line1.append(after)`
`-				line2.append(after)`
`-				after = " "`
`-				if card == highlight:`
`-					before = ">"`
`-					after = "<"`
`-					before = after = fill = ":"`
`-					highlight = None`
`-				else:`
`-					before = " "`
`-`
`-				line1.append((just_before + "[" + str(i) + "]").rjust(10, fill))`
`-				line2.append((just_before + repr(card)).rjust(10, fill)[:10])`
`-				fill = " "`
`-`
`-			if after:`
`-				line1.append(after)`
`-				line2.append(after)`
`-`
`-			print()`
`-			print("   ", ''.join(line1))`
`-			print("   ", ''.join(line2))`
`-`
`-			c = None`
`-			valid_cards = "123456"[:len(self.cards)]`
`-			valid = valid_cards + '!' + chr(27)`
`-			prompt = "    play [1-" + str(len(self.cards)) + "]"`
`-`
`-			if hand.deck and (len(self.cards) < 6):`
`-				prompt += " or [d]raw?> "`
`-				valid += "d"`
`-			else:`
`-				prompt += " or [.]discard?> "`
`-				valid += "."`
`-			c = getch(prompt, valid)`
`-`
`-			if c == chr(27):`
`-				sys.exit("ESC")`
`-			if c == '!':`
`-				played_so_far()`
`-				continue`
`-			if c == 'd':`
`-				card = hand.deck.pop()`
`-				self.cards.append(card)`
`-				self.cards.sort(reverse=True)`
`-				self.last_drawn = card`
`-				print()`
`-				print("    drew", card)`
`-				print()`
`-				continue`
`-			if c == '.':`
`-				c2 = getch("    Discard which card? " + valid_cards + " >")`
`-				if c2 not in valid_cards:`
`-					continue`
`-				i = int(c2) - 1`
`-			else:`
`-				assert '1' <= c <= str(len(self.cards))`
`-				i = int(c) - 1`
`-`
`-			card = self.cards[i]`
`-			player = self`
`-			if c == '.':`
`-				playee = hand.discard`
`-			elif isinstance(card, Hazard):`
`-				playee = other`
`-			else:`
`-				playee = self`
`-`
`-			# print("    Playing", card, "on", playee.name)`
`-			try:`
`-				player.play(card, playee)`
`-				self.last_drawn = None`
`-			except IllegalMove as response:`
`-				bangs = "!" * len(str(response))`
`-				print()`
`-				print("   ", bangs)`
`-				print("   ", response)`
`-				print("   ", bangs)`
`-				print()`
`-				c = None`
`-				continue`
`-			break`
`-`
`-		if (self.mileage() == 700) and not hand.extended:`
`-			while True:`
`+		while True:`
`+`
`+			if self.state == "prompt for extend":`
` 				c = getch("    You reached 700!  Extend? >", "yn!")`
` 				if c == '!':`
` 					played_so_far()`
` 					continue`
`+				hand.extended = c == "y"`
`+				self.state = None`
`+				return`
`+`
`+			while self.cards:`
`+				print("deck", str(len(hand.deck)).rjust(3) + "/" + str(len(hand.original_deck)), "       discard |" + pile_repr(hand.discard.pile) + "|")`
`+				print("         total|hand    miles|battlepile|speed pile|safeties")`
`+				def stats(player):`
`+					strings = [player.name.ljust(8)[:8]]`
`+					add = strings.append`
`+`
`+					score = player.score()[0]`
`+`
`+					add(" ")`
`+					add(str(score + player.total_score).rjust(5))`
`+`
`+					add("|")`
`+					add(str(score).rjust(4))`
`+`
`+					add("    ")`
`+					add(str(player.mileage()).rjust(4))`
`+`
`+					add(" .:"[player.two_hundreds()])`
`+`
`+					add("|")`
`+					add(pile_repr(player.battle_pile))`
`+`
`+					add("|")`
`+					add(pile_repr(player.speed_pile))`
`+`
`+					add("|")`
`+					add(safeties_repr(player))`
`+`
`+					print("".join(strings))`
`+`
`+				stats(other)`
`+				stats(self)`
`+`
`+				line1 = []`
`+				line2 = []`
`+				highlight = self.last_drawn`
`+				before = fill = after = " "`
`+				just_before = " "`
`+				for i, card in enumerate(self.cards, 1):`
`+					line1.append(after)`
`+					line2.append(after)`
`+					after = " "`
`+					if card == highlight:`
`+						before = ">"`
`+						after = "<"`
`+						before = after = fill = ":"`
`+						highlight = None`
`+					else:`
`+						before = " "`
`+`
`+					line1.append((just_before + "[" + str(i) + "]").rjust(10, fill))`
`+					line2.append((just_before + repr(card)).rjust(10, fill)[:10])`
`+					fill = " "`
`+`
`+				if after:`
`+					line1.append(after)`
`+					line2.append(after)`
`+`
`+				print()`
`+				print("   ", ''.join(line1))`
`+				print("   ", ''.join(line2))`
`+`
`+				c = None`
`+				valid_cards = "123456"[:len(self.cards)]`
`+				valid = valid_cards + '!' + chr(27)`
`+				prompt = "    play [1-" + str(len(self.cards)) + "]"`
`+`
`+				if hand.deck and (len(self.cards) < 6):`
`+					prompt += " or [d]raw?> "`
`+					valid += "d"`
`+				else:`
`+					prompt += " or [.]discard?> "`
`+					valid += "."`
`+				c = getch(prompt, valid)`
`+`
`+				if c == chr(27):`
`+					sys.exit("ESC")`
`+				if c == '!':`
`+					played_so_far()`
`+					continue`
`+				if c == 'd':`
`+					card = hand.deck.pop()`
`+					self.cards.append(card)`
`+					self.cards.sort(reverse=True)`
`+					self.last_drawn = card`
`+					print()`
`+					print("    drew", card)`
`+					print()`
`+					continue`
`+				if c == '.':`
`+					c2 = getch("    Discard which card? " + valid_cards + " >")`
`+					if c2 not in valid_cards:`
`+						continue`
`+					i = int(c2) - 1`
`+				else:`
`+					assert '1' <= c <= str(len(self.cards))`
`+					i = int(c) - 1`
`+`
`+				card = self.cards[i]`
`+				player = self`
`+				if c == '.':`
`+					playee = hand.discard`
`+				elif isinstance(card, Hazard):`
`+					playee = other`
`+				else:`
`+					playee = self`
`+`
`+				# print("    Playing", card, "on", playee.name)`
`+				try:`
`+					player.play(card, playee)`
`+					self.last_drawn = None`
`+				except IllegalMove as response:`
`+					bangs = "!" * len(str(response))`
`+					print()`
`+					print("   ", bangs)`
`+					print("   ", response)`
`+					print("   ", bangs)`
`+					print()`
`+					c = None`
`+					continue`
` 				break`
`-			hand.extended = c == "y"`
`-`
`-`
`+`
`+			if (self.mileage() == 700) and not hand.extended:`
`+				self.state = "prompt for extend"`
`+				continue`
`+			return`
` `
` if __name__ == "__main__":`
` `
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.