1 '''Defines some additional spice for theia.'''
2
3
4
5
6 import sys
7 import os
8 import string
9 import random
10 import curses
11 import pickle
12 from random import choice
15 "Pick in the menu."
16 if '--magazzu' in menu:
17 magazzu()
18 elif '--hang' in menu:
19 hang()
20 elif '--schiaccia' in menu:
21 pong()
22 elif '--coco' in menu:
23 pendu()
24
27 """The whole hangman game, from welcome to exit."""
28
29
30 wordList = [
31 'feeling',
32 'sculptor',
33 'wonderful',
34 'sweetest',
35 'hedgerow',
36 'hacking',
37 'the',
38 'art',
39 'of',
40 'exploitation',
41 'python',
42 'press',
43 'starch',
44 'inside',
45 'descriptor',
46 'overflow',
47 'privilege',
48 'replace',
49 'interferometry',
50 'merger',
51 'coalescence',
52 'gravitation',
53 'computing',
54 'width',
55 'master',
56 'slave',
57 'difference',
58 'flag',
59 'c'
60 ]
61
62 maxTries = 8
63 scoreFile = 'scores'
64 newFileString = """# High scores for the hangman game.
65 # Have this file in the current directory from which you're playing
66 # to have access to the high scores.\n"""
67
68 def listScores():
69 """List all the names and scores listed in the high scores file."""
70
71 if not os.path.isfile(scoreFile):
72 print "There is no high scores file, would you like to create one?",
73 ans = raw_input()
74 if ans == '' or ans[0] == 'y' or ans[0] == 'Y':
75 print "Creating scores file."
76 newf = open(scoreFile, 'w')
77 newf.write(newFileString)
78 newf.close()
79 else:
80 print "Aborting file creation, exiting program."
81 raise SystemExit("Exit for refusal of scores file creation.")
82
83
84 toPrint = noComment(scoreFile)
85
86 if len(toPrint) == 0:
87 print "There are no scores registered yet."
88 else:
89 print "Here are the registered players and their scores:\n" + toPrint
90
91 def askName():
92 """Get name of player and corresponding score if any."""
93
94 print "What is your name?",
95 name = raw_input()
96 while True:
97 if name == '' or ' ' in name or name[0] not in string.letters:
98 print "%r is not a valid name, " % name,
99 print "the name must start with a letter and contain no spaces."
100 name = raw_input()
101 else:
102 break
103
104
105 print "Looking up your score..."
106 allStr = noComment(scoreFile)
107
108 if name not in allStr:
109 print "You have no score registered yet! Assigning you a score of 0..."
110 return (name, 0, False)
111 else:
112
113 beg = allStr.find(name, 0) + len(name) + 1
114 if allStr.find('\n', beg) != -1:
115 end = allStr.find('\n', beg)
116 else:
117 end = len(allStr) -1
118 return (name, int(allStr[beg:end]), True)
119
120 def updateScore(name, oldscore, newscore):
121 """Update the score of a registered player on the scores file."""
122 print "\nUpdating scores file..."
123 allStr = noComment(scoreFile)
124
125
126 olds = "%s %d" % (name, oldscore)
127 news = "%s %d" % (name, newscore)
128 allStr = allStr.replace(olds, news, 1)
129
130
131 with open(scoreFile, 'w') as sf:
132 sf.write(newFileString)
133 sf.write(allStr)
134
135 print "Wrote your new score to scores file."
136
137 def addScore(name, score):
138 """Add a non-registered player and his new score to the scores file."""
139 print "\nUpdating scores file..."
140 with open(scoreFile, 'a') as sf:
141 sf.write("%s %d\n" % (name,score))
142
143 print "Wrote your new score to the scores file."
144
145 def noComment(fileName, exclude = '#'):
146 """Return string of all the non-commented lines of the file.
147
148 This raises an IOError if the file is not found.
149
150 """
151 allStr = ""
152 if not os.path.isfile(fileName):
153 raise IOError("%r file not found while extracting non-comment lines.")
154 else:
155 with open(fileName, 'r') as sf:
156 for line in sf:
157 if not exclude in line:
158 allStr = allStr + line
159
160 return allStr
161
162 welcome = """
163 Welcome to the hangman game.
164 Learn your vocabulary and have fun, right from the command line!
165
166 Copyright (C) 2017 R. Duque
167 License: GNU GPLv3 <http://gnu.org/licenses/gpl.html>
168 This is free software: you are free to change and redistribute it.
169 There is NO WARRANTY, to the extent permitted by law.
170 For more information, please see the README file.
171 """
172
173 goodbye = "\nSee you later!"
174
175 rightLetter = "Congrats, %r is one of the letters of the word!"
176
177 wrongLetter = "Sorry, %r didn't work"
178
179 wholeWord = "Nice! You guessed the whole word %r!"
180
181 def askExit():
182 """Ask whether to exit the program or not."""
183 print "Would you like to continue playing?",
184 ans = raw_input()
185 if ans =='' or ans[0] == 'y' or ans[0] == 'Y':
186 print "\nGreat! New word please!"
187 return False
188 else:
189 return True
190
191 showTries = "You still have %d tries left."
192
193 scoreLine = "Your current score is %d points."
194
195 wins = "\nBravo! You guessed the word %r in %d tries!"
196
197 loss = "Sorry buddy you have not more tries left, the word was %r."
198
199 def chooseLetter(guessed):
200 print "Go ahead, guess a letter or a word!",
201 ans = raw_input()
202
203 while True:
204 if ans == '' or not set(ans).issubset(set(string.letters)):
205 print "%r is not valid input, type in just letters." % ans ,
206 ans = raw_input()
207 continue
208
209 if ans in guessed:
210 print "\nYou already tried %r! Pick another one." % ans ,
211 print "These are your previous tries: ",
212 for i in guessed:
213 print "%r, " % i,
214
215 ans = raw_input()
216 continue
217
218 else:
219 break
220
221 return ans
222
223 def printState(word, found):
224 """Prints the word with only the found letters."""
225 toPrint = ''
226 for i in word:
227 if i in found:
228 toPrint = toPrint + i
229 else:
230 toPrint = toPrint + '*'
231
232 print "\nHere's the word so far: %s" % toPrint
233
234 rules = """
235 This is hangman! I'm going to pick a word and you're going to have %d tries
236 to guess the letters in the word. You can also try to guess the entire
237 word. Along the way I'll show you the letters you've already tried and the
238 letters you've already guessed in the word.
239 """ % maxTries
240
241
242 print welcome
243 try:
244 listScores()
245
246 except SystemExit:
247 print goodbye
248 sys.exit(1)
249
250
251 (name, oldscore, hasName) = askName()
252 newscore = oldscore
253 print rules
254 print scoreLine % newscore
255
256
257 while True:
258
259 word = random.choice(wordList)
260 guessed = set()
261 found = set()
262 toFind = set(word)
263 triesLeft = maxTries
264 tries = 0
265
266
267 while triesLeft > 0 and not toFind.issubset(found):
268 printState(word, found)
269 print showTries % triesLeft
270 answer = chooseLetter(guessed)
271 guessed.add(answer)
272 tries = tries + 1
273
274 if answer == word:
275
276 found.add(answer)
277 print wholeWord % word
278 triesLeft = triesLeft - 1
279 break
280
281 if answer in word:
282
283 found.add(answer)
284 print rightLetter % answer
285 else:
286 triesLeft = triesLeft - 1
287 print wrongLetter % answer
288
289
290 if toFind.issubset(found) or word in found:
291 print wins % (word, tries)
292 toAdd = len(word) + triesLeft
293 else:
294 print loss % word
295 toAdd = 0
296
297
298 newscore = newscore + toAdd
299 print scoreLine % newscore
300
301 if askExit():
302
303 if hasName:
304
305 updateScore(name, oldscore, newscore)
306 else:
307
308 addScore(name, newscore)
309
310
311 print goodbye
312 sys.exit(0)
313
317
320 HEIGHT = 20
321 WIDTH = 60
322 TIMEOUT = 50
323
324 class player(object):
325 def __init__(self, name, body, keyup, keydown, side):
326 self.name = name
327 self.hit_score = 0
328 self.keyup = keyup
329 self.keydown = keydown
330 self.body = body
331 self.side = side
332 if side == 'left':
333 self.bounce = [[coord[0], coord[1]+1] for coord in self.body]
334 if side == 'right':
335 self.bounce = [[coord[0], coord[1]-1] for coord in self.body]
336 for part in self.body:
337 win.addch(part[0], part[1], '|')
338
339 @property
340 def score(self):
341 return ' {}: {} '.format(self.name, self.hit_score)
342
343 def make_a_point(self):
344 self.hit_score += 1
345
346 def update_bounce(self):
347 if self.side == 'left':
348 self.bounce = [[coord[0], coord[1]+1] for coord in self.body]
349 if self.side == 'right':
350 self.bounce = [[coord[0], coord[1]-1] for coord in self.body]
351 for part in self.body:
352 win.addch(part[0], part[1], '|')
353
354 def go_up(self):
355 win.addch(self.body[-1][0], self.body[-1][1], ' ')
356 del self.body[-1]
357 if self.body[0][0] == 1 :
358 self.body.insert(0, [HEIGHT-2, self.body[-1][1]])
359 else:
360 self.body.insert(0, [self.body[0][0]-1, self.body[-1][1]])
361 self.update_bounce()
362 win.addch(self.body[0][0], self.body[0][1], '|')
363
364 def go_down(self):
365 win.addch(self.body[0][0], self.body[0][1], ' ')
366 del self.body[0]
367 if self.body[-1][0] == HEIGHT-2 :
368 self.body.insert(len(self.body), [1, self.body[-1][1]])
369 else:
370 self.body.insert(len(self.body), [self.body[-1][0]+1, self.body[-1][1]])
371 self.update_bounce()
372
373
374 class ball(object):
375 def __init__(self, dir=-1, coef=0):
376 self.position = [HEIGHT/2, WIDTH/2]
377 self.dir = dir
378 self.coef = coef
379 win.addch(self.position[0], self.position[1], 'o')
380
381 def bounce(self, where):
382
383 if where == 0:
384 self.coef -= 1
385 elif where == 2:
386 self.coef += 1
387 self.dir *= -1
388
389 def bounce_segment(self):
390 self.coef *= -1
391
392 def reset(self, position=[HEIGHT/2, WIDTH/2], dir=-1, coef=0):
393 self.position = position
394 self.dir = dir
395 self.coef = coef
396
397 def input_key(name, direction):
398 k = raw_input("{}'s key {}: ".format(name, direction))
399 if k == 'up':
400 key = curses.KEY_UP
401 elif k=='down':
402 key = curses.KEY_DOWN
403 else:
404 key = ord(k)
405 return(key)
406
407 print('---------------------------')
408 print('Welcome to PONG multiplayer')
409 print('---------------------------')
410 choice = raw_input('Change timeout ? (default=50) ')
411 if 'y' in choice:
412 TIMEOUT = raw_input('timeout = ')
413
414 name1 = raw_input("left player's name: ")
415 print('Do not use the following keys: ESC, SPACE, p, n')
416 print('write "up" or "down" to use the arrows')
417 keyup1 = input_key(name1, 'up')
418 keydown1 = input_key(name1, 'down')
419
420 name2 = raw_input("right player's name: ")
421 print('Do not use the following keys: ESC, SPACE, p, n')
422 print('write "up" or "down" to use the arrows')
423 keyup2 = input_key(name2, 'up')
424 keydown2 = input_key(name2, 'down')
425
426 curses.initscr()
427 win = curses.newwin(HEIGHT, WIDTH, 0, 0)
428 win.keypad(1)
429 curses.noecho()
430 curses.curs_set(0)
431 win.border(0)
432 win.nodelay(1)
433 try:
434 win.timeout(int(TIMEOUT))
435 except TypeError:
436 win.timeout(50)
437
438
439 score1 = 0
440 body1 = [[HEIGHT/2-1, 1], [HEIGHT/2, 1], [HEIGHT/2+1, 1]]
441 player1 = player(name1, body1, keyup1, keydown1, 'left')
442
443 score2 = 0
444 body2 = [[HEIGHT/2-1,WIDTH-2], [HEIGHT/2,WIDTH-2], [HEIGHT/2+1,WIDTH-2]]
445 player2 = player(name2, body2, keyup2, keydown2, 'right')
446
447 ball = ball()
448
449 score_max = 3
450 new_round_message = 'press SPACE bar for another round'
451 new_round_message_erase = ' '
452 end_message = ' THE END\n - ESC to quit\n - n bar for another game'
453 key = 0
454 point = False
455
456 while key != 27:
457 win.border(0)
458 win.addstr(0, 3, ' {}'.format(player1.score))
459 win.addstr(0, WIDTH/2 - 4, ' PONG ')
460 win.addstr(0, WIDTH-15, '{}'.format(player2.score))
461 win.addstr(HEIGHT-1, WIDTH/2-12, ' ESC (quit), p (pause) ')
462
463 event = win.getch()
464 key = event
465
466
467 prevKey = key
468 event = win.getch()
469 key = key if event == -1 else event
470
471 if key == ord('p'):
472 key = -1
473 while key != ord('p'):
474 key = win.getch()
475 key = prevKey
476 continue
477
478
479 if key == player1.keyup:
480 player1.go_up()
481 if key == player1.keydown:
482 player1.go_down()
483 if key == player2.keyup:
484 player2.go_up()
485 if key == player2.keydown:
486 player2.go_down()
487
488
489 if ball.position in player1.bounce:
490 ball.bounce(player1.bounce.index(ball.position))
491 elif ball.position in player2.bounce:
492 ball.bounce(player2.bounce.index(ball.position))
493 elif ball.position[0] == 1 or ball.position[0] == HEIGHT-2:
494 ball.bounce_segment()
495
496 if ball.position[1] == WIDTH-2:
497 if player1.hit_score < score_max -1:
498 win.addstr(3, 10, new_round_message)
499 else:
500 win.addstr(3, 10, end_message)
501 win.addstr(7, 3, winer_message)
502
503 player1.make_a_point()
504 old = [ball.position[0], ball.position[1]]
505 ball.reset(dir=1)
506 point = True
507
508 elif ball.position[1] == 1:
509 if player2.hit_score < score_max -1:
510 win.addstr(3, 10, new_round_message)
511 else:
512 win.addstr(3, 10, end_message)
513 win.addstr(7, 3, winer_message)
514
515 player2.make_a_point()
516 old = [ball.position[0], ball.position[1]]
517 ball.reset(dir=-1)
518 point = True
519
520 if point:
521 if key == ord(' '):
522 win.addch(old[0], old[1], ' ')
523 win.addstr(3,10, new_round_message_erase)
524 point = False
525 elif key == ord('n'):
526 win.addch(old[0], old[1], ' ')
527 win.addstr(3, 2, ' ')
528 win.addstr(4, 2, ' ')
529 win.addstr(5, 2, ' ')
530 win.addstr(7, 2, ' ')
531 player1.hit_score = 0
532 player2.hit_score = 0
533 point = False
534 else:
535 continue
536 else:
537 win.addch(ball.position[0], ball.position[1], ' ')
538 ball.position = [ball.position[0]+ball.coef, ball.position[1]+ball.dir]
539 if ball.position[0] < 1:
540 ball.position[0] = 1
541 elif ball.position[0] > HEIGHT-2:
542 ball.position[0] = HEIGHT-2
543 elif ball.position[1] < 1:
544 ball.position[1] = 1
545 elif ball.position[1] > WIDTH-2:
546 ball.position[1] = WIDTH-2
547 win.addch(ball.position[0], ball.position[1], 'o')
548
549 if player1.hit_score == score_max-1:
550 winer = player1
551 looser = player2
552 winer_message = '{} has defeated {} {}-{}'.format(winer.name, looser.name,
553 winer.hit_score+1, looser.hit_score)
554 elif player2.hit_score == score_max-1:
555 winer = player2
556 looser = player1
557 winer_message = '{} has defeated {} {}-{}'.format(winer.name, looser.name,
558 winer.hit_score+1, looser.hit_score)
559
560 curses.endwin()
561 print('---------------------------')
562 print('End game')
563 try:
564 print(winer_message)
565 except UnboundLocalError:
566 print('No one won the match')
567 sys.exit(0)
568
572 nom_fichier_scores = "scores"
573
574 menu = 5
575
576 jeu = 1
577 afficheScores = 2
578 quitte = 5
579 maz = 3
580 autreUtilisateur = 4
581
582 nombre_coups = 8
583
584 liste_mots = [
585 "armoire",
586 "boucle",
587 "buisson",
588 "bureau",
589 "chaise",
590 "carton",
591 "couteau",
592 "fichier",
593 "garage",
594 "glace",
595 "journal",
596 "kiwi",
597 "lampe",
598 "liste",
599 "montagne",
600 "remise",
601 "sandale",
602 "taxi",
603 "vampire",
604 "volant",
605 ]
606
607
608 def choix_nom_utilisateur():
609 """ Get the user's name """
610
611 return raw_input("What's your name? ")
612
613
614 def charger_scores():
615 """ Loading scores """
616
617 if os.path.exists(nom_fichier_scores):
618 with open(nom_fichier_scores, 'rb') as fichier:
619 scores = pickle.Unpickler(fichier).load()
620 else:
621 scores = {}
622
623 return scores
624
625
626 def sauvegarder_scores(scores):
627 """ Saving scores """
628
629 with open(nom_fichier_scores, 'wb') as fichier:
630 pickle.Pickler(fichier).dump(scores)
631
632
633
634 def maz_scores(scores):
635 """ Delete the scores' file """
636
637
638
639 scores = {}
640
641 sauvegarder_scores(scores)
642
643 print"Scores deleted"
644
645 return scores
646
647
648
649 def generation_mot():
650 """ Genere un mot aleatoire pour le jeu en fonction de la liste de
651 mots
652 """
653
654 return choice(liste_mots)
655
656
657
658 def masque_mot(mot_a_trouver, lettres_trouvees):
659 """Affiche le mot a trouver avec les lettres manquantes masquees"""
660
661 mot_masque = ''
662
663 for lettre in mot_a_trouver:
664 if lettre in lettres_trouvees:
665 mot_masque += lettre
666 else:
667 mot_masque += '*'
668
669 return mot_masque
670
671
672
673 def choix_lettre(lettres_trouvees):
674 """Recupere la lettre selectionnee par l'utilisateur"""
675
676 lettre = raw_input("What letter? ")
677 lettre = lettre.lower()
678
679 if len(lettre) > 1 or not lettre.isalpha():
680 print("You didn't pick a valid letter")
681 return choix_lettre(lettres_trouvees)
682 elif lettre in lettres_trouvees:
683 print("You've already found this letter")
684 return choix_lettre(lettres_trouvees)
685 else:
686 return lettre
687
688
689
690 def afficher_menu(utilisateur):
691 """Affiche un menu en debut de partie"""
692
693 print("*************************").center(20)
694 print("Pendu CocoPanda 2017\n".center(20))
695 print("Welcome {}".format(utilisateur))
696 print"{}. Play".format(jeu)
697 print"{}. Display scores".format(afficheScores)
698 print"{}. Delete scores".format(maz)
699 print"{}. Change user".format(autreUtilisateur)
700 print"{}. Quit".format(quitte)
701
702
703
704 def choix_utilisateur():
705 """Recuperation du choix de l'utilisateur"""
706
707 choix = raw_input("Select: ")
708 if not choix.isdigit():
709 print("You didn't select a valid input for the menu")
710 return choix_utilisateur
711 else:
712 choix = int(choix)
713 if choix > menu:
714 print("You didn't select a valid input for the menu")
715 return choix_utilisateur
716 else:
717 return choix
718
719
720 def afficher_scores(scores):
721 """ Display scores """
722
723 print("***********************************")
724 print"* ",
725 print"HALL OF FAME".center(29),
726 print" *"
727
728 for utilisateur, score in scores.items():
729 print"* ",
730 if score > 1:
731 print"{} : {} points".format(utilisateur, score).center(29),
732 else:
733 print"{} : {} point".format(utilisateur, score).center(29),
734 print(" *")
735 print("***********************************")
736
737
738
739 def afficher_score(utilisateur, scores):
740 """ Display the user's socre"""
741
742 if scores[utilisateur] > 1:
743 print("{} a {} points".format(utilisateur, scores[utilisateur]))
744 else:
745 print("{} a {} point".format(utilisateur, scores[utilisateur]))
746
747
748
749 def jouer(utilisateur, scores):
750 """ Call the game """
751
752 coups_restants = nombre_coups
753 lettres_trouvees = []
754
755 afficher_score(utilisateur, scores)
756
757
758 mot_a_trouver = generation_mot()
759
760
761
762 mot_trouve = masque_mot(mot_a_trouver, lettres_trouvees)
763
764
765 while coups_restants > 0 and mot_trouve != mot_a_trouver:
766
767
768 print(mot_trouve)
769
770 lettre = choix_lettre(lettres_trouvees)
771
772 if lettre in mot_a_trouver:
773 lettres_trouvees.append(lettre)
774 else:
775 coups_restants -= 1
776 if coups_restants > 1:
777 print('You screwed up! Try again! {} hits left'.format(
778 coups_restants))
779 elif coups_restants == 1:
780 print("You screwed up! Try again! Only 1 hit left")
781 else:
782 print("Too many tries! You totally screwed up!")
783
784 mot_trouve = masque_mot(mot_a_trouver, lettres_trouvees)
785
786
787 scores[utilisateur] += coups_restants
788 sauvegarder_scores(scores)
789
790 afficher_score(utilisateur, scores)
791
792 rejouer = raw_input("Would you like to play again? (Y/n) ")
793 rejouer = rejouer.lower()
794 if rejouer == '':
795 rejouer = 'y'
796
797 return rejouer
798
799
800
801 def effacer_entree_scores(scores, utilisateur):
802 """Permet d'effacer une entree du Hall of Fame en fonction du nom
803 d'utilsateur indique
804 """
805
806 del scores[utilisateur]
807
808 sauvegarder_scores(scores)
809
810 return scores
811
812
813 scores = charger_scores()
814
815
816 utilisateur = choix_nom_utilisateur()
817
818
819 if utilisateur not in scores.keys():
820 scores[utilisateur] = 0
821
822 while(1):
823 rejouer = 'y'
824
825 afficher_menu(utilisateur)
826
827 choix = choix_utilisateur()
828
829 if choix == jeu:
830 while rejouer == 'y':
831 rejouer = jouer(utilisateur, scores)
832
833 elif choix == afficheScores:
834 afficher_scores(scores)
835 supprimer_score = raw_input("Would like to delete a score? (y/N) : ")
836 supprimer_score = supprimer_score.lower()
837 if supprimer_score == 'y':
838 utilisateur_a_supprimer = raw_input(
839 "Write the name of the player: ")
840 scores = effacer_entree_scores(scores, utilisateur_a_supprimer)
841 if utilisateur not in scores.keys():
842 scores[utilisateur] = 0
843
844 elif choix == maz:
845 maz_scores(scores)
846
847
848 scores[utilisateur] = 0
849
850 elif choix == autreUtilisateur:
851 utilisateur = choix_nom_utilisateur()
852 if utilisateur not in scores.keys():
853 scores[utilisateur] = 0
854
855 elif choix == quitte:
856 sys.exit(0)
857