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),
371 [self.body[-1][0]+1,self.body[-1][1]])
372 self.update_bounce()
373
374
375 class ball(object):
376 def __init__(self, dir=-1, coef=0):
377 self.position = [HEIGHT/2, WIDTH/2]
378 self.dir = dir
379 self.coef = coef
380 win.addch(self.position[0], self.position[1], 'o')
381
382 def bounce(self, where):
383
384 if where == 0:
385 self.coef -= 1
386 elif where == 2:
387 self.coef += 1
388 self.dir *= -1
389
390 def bounce_segment(self):
391 self.coef *= -1
392
393 def reset(self, position=[HEIGHT/2, WIDTH/2], dir=-1, coef=0):
394 self.position = position
395 self.dir = dir
396 self.coef = coef
397
398 def input_key(name, direction):
399 k = raw_input("{}'s key {}: ".format(name, direction))
400 if k == 'up':
401 key = curses.KEY_UP
402 elif k=='down':
403 key = curses.KEY_DOWN
404 else:
405 key = ord(k)
406 return(key)
407
408 print('---------------------------')
409 print('Welcome to PONG multiplayer')
410 print('---------------------------')
411 choice = raw_input('Change timeout ? (default=50) ')
412 if 'y' in choice:
413 TIMEOUT = raw_input('timeout = ')
414
415 name1 = raw_input("left player's name: ")
416 print('Do not use the following keys: ESC, SPACE, p, n')
417 print('write "up" or "down" to use the arrows')
418 keyup1 = input_key(name1, 'up')
419 keydown1 = input_key(name1, 'down')
420
421 name2 = raw_input("right player's name: ")
422 print('Do not use the following keys: ESC, SPACE, p, n')
423 print('write "up" or "down" to use the arrows')
424 keyup2 = input_key(name2, 'up')
425 keydown2 = input_key(name2, 'down')
426
427 curses.initscr()
428 win = curses.newwin(HEIGHT, WIDTH, 0, 0)
429 win.keypad(1)
430 curses.noecho()
431 curses.curs_set(0)
432 win.border(0)
433 win.nodelay(1)
434 try:
435 win.timeout(int(TIMEOUT))
436 except TypeError:
437 win.timeout(50)
438
439
440 score1 = 0
441 body1 = [[HEIGHT/2-1, 1], [HEIGHT/2, 1], [HEIGHT/2+1, 1]]
442 player1 = player(name1, body1, keyup1, keydown1, 'left')
443
444 score2 = 0
445 body2 = [[HEIGHT/2-1,WIDTH-2], [HEIGHT/2,WIDTH-2], [HEIGHT/2+1,WIDTH-2]]
446 player2 = player(name2, body2, keyup2, keydown2, 'right')
447
448 ball = ball()
449
450 score_max = 3
451 new_round_message = 'press SPACE bar for another round'
452 new_round_message_erase = ' '
453 end_message = ' THE END\n - ESC to quit\n - n bar for another game'
454 key = 0
455 point = False
456
457 while key != 27:
458 win.border(0)
459 win.addstr(0, 3, ' {}'.format(player1.score))
460 win.addstr(0, WIDTH/2 - 4, ' PONG ')
461 win.addstr(0, WIDTH-15, '{}'.format(player2.score))
462 win.addstr(HEIGHT-1, WIDTH/2-12, ' ESC (quit), p (pause) ')
463
464 event = win.getch()
465 key = event
466
467
468 prevKey = key
469 event = win.getch()
470 key = key if event == -1 else event
471
472 if key == ord('p'):
473 key = -1
474 while key != ord('p'):
475 key = win.getch()
476 key = prevKey
477 continue
478
479
480 if key == player1.keyup:
481 player1.go_up()
482 if key == player1.keydown:
483 player1.go_down()
484 if key == player2.keyup:
485 player2.go_up()
486 if key == player2.keydown:
487 player2.go_down()
488
489
490 if ball.position in player1.bounce:
491 ball.bounce(player1.bounce.index(ball.position))
492 elif ball.position in player2.bounce:
493 ball.bounce(player2.bounce.index(ball.position))
494 elif ball.position[0] == 1 or ball.position[0] == HEIGHT-2:
495 ball.bounce_segment()
496
497 if ball.position[1] == WIDTH-2:
498 if player1.hit_score < score_max -1:
499 win.addstr(3, 10, new_round_message)
500 else:
501 win.addstr(3, 10, end_message)
502 win.addstr(7, 3, winer_message)
503
504 player1.make_a_point()
505 old = [ball.position[0], ball.position[1]]
506 ball.reset(dir=1)
507 point = True
508
509 elif ball.position[1] == 1:
510 if player2.hit_score < score_max -1:
511 win.addstr(3, 10, new_round_message)
512 else:
513 win.addstr(3, 10, end_message)
514 win.addstr(7, 3, winer_message)
515
516 player2.make_a_point()
517 old = [ball.position[0], ball.position[1]]
518 ball.reset(dir=-1)
519 point = True
520
521 if point:
522 if key == ord(' '):
523 win.addch(old[0], old[1], ' ')
524 win.addstr(3,10, new_round_message_erase)
525 point = False
526 elif key == ord('n'):
527 win.addch(old[0], old[1], ' ')
528 win.addstr(3, 2, ' ')
529 win.addstr(4, 2, ' ')
530 win.addstr(5, 2, ' ')
531 win.addstr(7, 2, ' ')
532 player1.hit_score = 0
533 player2.hit_score = 0
534 point = False
535 else:
536 continue
537 else:
538 win.addch(ball.position[0], ball.position[1], ' ')
539 ball.position = [ball.position[0]+ball.coef,
540 ball.position[1]+ball.dir]
541 if ball.position[0] < 1:
542 ball.position[0] = 1
543 elif ball.position[0] > HEIGHT-2:
544 ball.position[0] = HEIGHT-2
545 elif ball.position[1] < 1:
546 ball.position[1] = 1
547 elif ball.position[1] > WIDTH-2:
548 ball.position[1] = WIDTH-2
549 win.addch(ball.position[0], ball.position[1], 'o')
550
551 if player1.hit_score == score_max-1:
552 winer = player1
553 looser = player2
554 winer_message = '{} has defeated {} {}-{}'.format(winer.name,
555 looser.name,
556 winer.hit_score+1, looser.hit_score)
557 elif player2.hit_score == score_max-1:
558 winer = player2
559 looser = player1
560 winer_message =\
561 '{} has defeated{}{}-{}'.format(winer.name,looser.name,
562 winer.hit_score+1,
563 looser.hit_score)
564
565 curses.endwin()
566 print('---------------------------')
567 print('End game')
568 try:
569 print(winer_message)
570 except UnboundLocalError:
571 print('No one won the match')
572 sys.exit(0)
573
577 nom_fichier_scores = "scores"
578
579 menu = 5
580
581 jeu = 1
582 afficheScores = 2
583 quitte = 5
584 maz = 3
585 autreUtilisateur = 4
586
587 nombre_coups = 8
588
589 liste_mots = [
590 "armoire",
591 "boucle",
592 "buisson",
593 "bureau",
594 "chaise",
595 "carton",
596 "couteau",
597 "fichier",
598 "garage",
599 "glace",
600 "journal",
601 "kiwi",
602 "lampe",
603 "liste",
604 "montagne",
605 "remise",
606 "sandale",
607 "taxi",
608 "vampire",
609 "volant",
610 ]
611
612
613 def choix_nom_utilisateur():
614 """ Get the user's name """
615
616 return raw_input("What's your name? ")
617
618
619 def charger_scores():
620 """ Loading scores """
621
622 if os.path.exists(nom_fichier_scores):
623 with open(nom_fichier_scores, 'rb') as fichier:
624 scores = pickle.Unpickler(fichier).load()
625 else:
626 scores = {}
627
628 return scores
629
630
631 def sauvegarder_scores(scores):
632 """ Saving scores """
633
634 with open(nom_fichier_scores, 'wb') as fichier:
635 pickle.Pickler(fichier).dump(scores)
636
637
638
639 def maz_scores(scores):
640 """ Delete the scores' file """
641
642
643
644 scores = {}
645
646 sauvegarder_scores(scores)
647
648 print"Scores deleted"
649
650 return scores
651
652
653
654 def generation_mot():
655 """ Genere un mot aleatoire pour le jeu en fonction de la liste de
656 mots
657 """
658
659 return choice(liste_mots)
660
661
662
663 def masque_mot(mot_a_trouver, lettres_trouvees):
664 """Affiche le mot a trouver avec les lettres manquantes masquees"""
665
666 mot_masque = ''
667
668 for lettre in mot_a_trouver:
669 if lettre in lettres_trouvees:
670 mot_masque += lettre
671 else:
672 mot_masque += '*'
673
674 return mot_masque
675
676
677
678 def choix_lettre(lettres_trouvees):
679 """Recupere la lettre selectionnee par l'utilisateur"""
680
681 lettre = raw_input("What letter? ")
682 lettre = lettre.lower()
683
684 if len(lettre) > 1 or not lettre.isalpha():
685 print("You didn't pick a valid letter")
686 return choix_lettre(lettres_trouvees)
687 elif lettre in lettres_trouvees:
688 print("You've already found this letter")
689 return choix_lettre(lettres_trouvees)
690 else:
691 return lettre
692
693
694
695 def afficher_menu(utilisateur):
696 """Affiche un menu en debut de partie"""
697
698 print("*************************").center(20)
699 print("Pendu CocoPanda 2017\n".center(20))
700 print("Welcome {}".format(utilisateur))
701 print"{}. Play".format(jeu)
702 print"{}. Display scores".format(afficheScores)
703 print"{}. Delete scores".format(maz)
704 print"{}. Change user".format(autreUtilisateur)
705 print"{}. Quit".format(quitte)
706
707
708
709 def choix_utilisateur():
710 """Recuperation du choix de l'utilisateur"""
711
712 choix = raw_input("Select: ")
713 if not choix.isdigit():
714 print("You didn't select a valid input for the menu")
715 return choix_utilisateur
716 else:
717 choix = int(choix)
718 if choix > menu:
719 print("You didn't select a valid input for the menu")
720 return choix_utilisateur
721 else:
722 return choix
723
724
725 def afficher_scores(scores):
726 """ Display scores """
727
728 print("***********************************")
729 print"* ",
730 print"HALL OF FAME".center(29),
731 print" *"
732
733 for utilisateur, score in scores.items():
734 print"* ",
735 if score > 1:
736 print"{} : {} points".format(utilisateur, score).center(29),
737 else:
738 print"{} : {} point".format(utilisateur, score).center(29),
739 print(" *")
740 print("***********************************")
741
742
743
744 def afficher_score(utilisateur, scores):
745 """ Display the user's socre"""
746
747 if scores[utilisateur] > 1:
748 print("{} a {} points".format(utilisateur, scores[utilisateur]))
749 else:
750 print("{} a {} point".format(utilisateur, scores[utilisateur]))
751
752
753
754 def jouer(utilisateur, scores):
755 """ Call the game """
756
757 coups_restants = nombre_coups
758 lettres_trouvees = []
759
760 afficher_score(utilisateur, scores)
761
762
763 mot_a_trouver = generation_mot()
764
765
766
767 mot_trouve = masque_mot(mot_a_trouver, lettres_trouvees)
768
769
770 while coups_restants > 0 and mot_trouve != mot_a_trouver:
771
772
773 print(mot_trouve)
774
775 lettre = choix_lettre(lettres_trouvees)
776
777 if lettre in mot_a_trouver:
778 lettres_trouvees.append(lettre)
779 else:
780 coups_restants -= 1
781 if coups_restants > 1:
782 print('You screwed up! Try again! {} hits left'.format(
783 coups_restants))
784 elif coups_restants == 1:
785 print("You screwed up! Try again! Only 1 hit left")
786 else:
787 print("Too many tries! You totally screwed up!")
788
789 mot_trouve = masque_mot(mot_a_trouver, lettres_trouvees)
790
791
792 scores[utilisateur] += coups_restants
793 sauvegarder_scores(scores)
794
795 afficher_score(utilisateur, scores)
796
797 rejouer = raw_input("Would you like to play again? (Y/n) ")
798 rejouer = rejouer.lower()
799 if rejouer == '':
800 rejouer = 'y'
801
802 return rejouer
803
804
805
806 def effacer_entree_scores(scores, utilisateur):
807 """Permet d'effacer une entree du Hall of Fame en fonction du nom
808 d'utilsateur indique
809 """
810
811 del scores[utilisateur]
812
813 sauvegarder_scores(scores)
814
815 return scores
816
817
818 scores = charger_scores()
819
820
821 utilisateur = choix_nom_utilisateur()
822
823
824 if utilisateur not in scores.keys():
825 scores[utilisateur] = 0
826
827 while(1):
828 rejouer = 'y'
829
830 afficher_menu(utilisateur)
831
832 choix = choix_utilisateur()
833
834 if choix == jeu:
835 while rejouer == 'y':
836 rejouer = jouer(utilisateur, scores)
837
838 elif choix == afficheScores:
839 afficher_scores(scores)
840 supprimer_score = raw_input("Would like to delete a score? (y/N): ")
841 supprimer_score = supprimer_score.lower()
842 if supprimer_score == 'y':
843 utilisateur_a_supprimer = raw_input(
844 "Write the name of the player: ")
845 scores = effacer_entree_scores(scores, utilisateur_a_supprimer)
846 if utilisateur not in scores.keys():
847 scores[utilisateur] = 0
848
849 elif choix == maz:
850 maz_scores(scores)
851
852
853 scores[utilisateur] = 0
854
855 elif choix == autreUtilisateur:
856 utilisateur = choix_nom_utilisateur()
857 if utilisateur not in scores.keys():
858 scores[utilisateur] = 0
859
860 elif choix == quitte:
861 sys.exit(0)
862