-
Notifications
You must be signed in to change notification settings - Fork 0
/
CheatopolyClasses.py
2420 lines (2213 loc) · 96.2 KB
/
CheatopolyClasses.py
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import random
import os
import pygame
import pygame.locals as loc
class Game(object):
"""
This class contains all game constants.
"""
#Default values
player_cash = 1500 # Initial amount received by each player
money = 15140 # See https://en.wikibooks.org/wiki/Monopoly/Official_Rules
houses = 32 # See https://en.wikibooks.org/wiki/Monopoly/Official_Rules
hotels = 12 # See https://en.wikibooks.org/wiki/Monopoly/Official_Rules
start_wage = 200 # What you get when you pass Go
jail_fine = 50 # Cost to get out of jail
collect_fine = 50 # Amount to collect from players with the Collect card
chance_repairs = [25, 100] # Cost of Chance repairs
chest_repairs = [45, 115] # Cost of Community Chest repairs
#Counters
current_comm = 0
current_chance = 0
current_player = 0 # current player index
#Bank
bank = None
#Display
square_side = 0
height = 0
width = 0
background = None
display = None
#Trade
sell = []
buy = []
trade_cash = 0
#Player colors
player_cols = [(255, 51, 51), (153, 255, 51), (51, 153, 255),
(255, 153, 51), (51, 255, 153, ), (255, 51, 153)]
def __init__(self, height, width, background, display, line_height,
font_size):
self.neighborhoods = {}
self.community_chest = []
self.chances = []
self.players = []
self.board = []
self.height = height
self.width = width
self.background = background
self.display = display
self.line_height = line_height
self.font_size = font_size
def load(self, file_name):
""" Process file_name txt file
@param file_name: the file name
"""
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
ff = open(os.path.join(__location__, file_name))
with ff as f:
content = f.readlines()
for i in range(len(content)):
line = content[i].rstrip().split("\t")
if line[0] == "street":
self.board.append(
Street(line[12], int(line[1]), int(line[2]), int(line[3]),
int(line[4]), int(line[5]), int(line[6]),
int(line[7]), int(line[8]), int(line[9]),
int(line[10]), line[11]))
if line[11] in self.neighborhoods:
self.neighborhoods[line[11]].append(self.board[-1])
else:
self.neighborhoods[line[11]] = [self.board[-1]]
elif line[0] == "start":
self.board.append(Start())
elif line[0] == "chestL":
self.board.append(CommunityChest())
elif line[0] == "tax":
self.board.append(Tax(line[3], line[1], line[2], line[4]))
elif line[0] == "rail":
self.board.append(
Railroad(line[7], int(line[1]), int(line[2]), int(line[3]),
int(line[4]), int(line[5]), int(line[6])))
elif line[0] == "chanceL":
self.board.append(Chance())
elif line[0] == "jail":
self.board.append(Jail())
elif line[0] == "utility":
self.board.append(Utility(line[3], int(line[1]), int(line[2])))
elif line[0] == "park":
self.board.append(FreeParking())
elif line[0] == "gotojail":
self.board.append(GoToJail())
elif line[0] == "chest":
self.community_chest.append(
CommunityCard(line[7], int(line[1]), int(line[2]),
int(line[3]), int(line[4]), int(line[5]),
int(line[6])))
elif line[0] == "chance":
self.chances.append(
ChanceCard(line[9], int(line[1]), int(line[2]),
int(line[3]), int(line[4]), int(line[5]),
int(line[6]), int(line[7]), line[8]))
elif line[0] == "const":
if line[1] == "playerCash":
self.player_cash = int(line[2])
elif line[1] == "money":
self.money = int(line[2])
elif line[1] == "houses":
self.houses = int(line[2])
elif line[1] == "hotels":
self.hotels = int(line[2])
elif line[1] == "startWage":
self.start_wage = int(line[2])
elif line[1] == "jailFine":
self.jail_fine = int(line[2])
elif line[1] == "collectFine":
self.collect_fine = int(line[2])
elif line[1] == "chanceRepairsMin":
self.chance_repairs = [int(line[2])]
elif line[1] == "chanceRepairsMax":
self.chance_repairs.append(int(line[2]))
elif line[1] == "chestRepairsMin":
self.chest_repairs = [int(line[2])]
elif line[1] == "chestRepairsMax":
self.chest_repairs.append(int(line[2]))
if line[0] in ["street", "start", "chestL", "tax", "rail",
"chanceL", "jail", "utility", "park", "gotojail"]:
self.board[i].location = i
def choose_six(self):
#message
central = min(self.width, self.height)/2
message(self.display,
"Choose a number of players", self.background,
central, self.height/4)
blue = (0, 0, 255)
width = 60
step = 40
#buttons
two = self.button("2", blue, central - width/2,
self.height/4 + step, width, step - 10)
three = self.button("3", blue, central - width/2,
self.height/4 + 2*step, width, step - 10)
four = self.button("4", blue, central - width/2,
self.height/4 + 3*step, width, step - 10)
five = self.button("5", blue, central - width/2,
self.height/4 + 4*step, width, step - 10)
six = self.button("6", blue, central - width/2,
self.height/4 + 5*step, width, step - 10)
pygame.display.update()
#detect click and return
while True:
for event in pygame.event.get():
if event.type == loc.MOUSEBUTTONUP:
mouse_x, mouse_y = event.pos
if two.collidepoint(mouse_x, mouse_y):
return 2
if three.collidepoint(mouse_x, mouse_y):
return 3
if four.collidepoint(mouse_x, mouse_y):
return 4
if five.collidepoint(mouse_x, mouse_y):
return 5
if six.collidepoint(mouse_x, mouse_y):
return 6
def initialize_players(self):
self.cover()
num_players = self.choose_six()
self.cover()
list_of_names = ['']
green = (0, 255, 0)
red = (255, 0, 0)
middle = min(self.width, self.height)/2
for i in range(num_players):
self.button("", green, middle - 50, (i+1)*self.height/8 + 10, 100,
20)
pygame.display.update()
for i in range(num_players):
# draw name box and enter name
name = self.capture_word((i+1)*self.height/8 + 10)
# draw human/not human dialog
human = self.draw_yes_no("Human?", 20, green, red, middle + 90,
(i+1)*self.height/8 - 30)
if human == "yes":
self.players.append(Player(name, self.player_cash, True,
self.player_cols[i]))
else:
self.players.append(Cheatoid(name, self.player_cash, False,
self.player_cols[i]))
list_of_names.append(name)
def mock_players(self):
self.cover()
num_players = self.choose_six()
for i in range(num_players):
name = "Borg{0}".format(str(i + 1))
self.players.append(Cheatoid(name, self.player_cash, False,
self.player_cols[i]))
print self.players
def buy_or_auction(self, choose, player, place):
if choose == "yes":
if player.cash > place.price:
place.new_owner(player) # Assign new owner
self.bank.move_money(-place.price, player)
place.draw(self)
for person in self.players:
person.draw(self)
pygame.display.update()
self.cover_n_central(
player.name + ", you have bought " + place.name + ".")
self.visual_refresh()
else:
self.cover_n_central(
"Sorry, you do not have the required funds!")
a = random.randint(1, 4)
if a == 1:
self.cover_n_central("Beggar...!")
player.start_auction(self) # Launch auction
self.visual_refresh()
else:
player.start_auction(self) # Launch auction
self.visual_refresh()
def draw_players(self):
for player in self.players:
player.draw(self)
pygame.display.update()
def flag_upgradeable_places(self, player):
""" Flag upgradeable locations
"""
for neighborhood in self.neighborhoods.values():
min_upgrade = 5
for street in neighborhood:
if street.owned_by != player or street.mortgaged:
#restore to 5
for strt in neighborhood:
strt.min_upgrade = 5
min_upgrade = 5
break
else:
if street.hotels == 0:
min_upgrade = min(min_upgrade, street.houses)
for street in neighborhood:
if street.owned_by == player:
street.min_upgrade = min_upgrade
def tax_rate(self, option, player):
"""Function to calculate taxes for a certain player and one tax system
It returns None when fed with the "None" option.
"""
if option[-1] == "%":
tax_percent = int(option[:-1])
payment = player.cash * tax_percent / 100.0 # Add % of cash
for item in self.board:
if item.owned_by == player:
payment += item.price * tax_percent / 100.0
payment += item.hotels * item.hotel_cost + \
item.houses * item.house_cost
return int(payment)
elif option == "None":
return None
else:
return int(option)
def repairs(self, house_cost, hotel_cost, player):
repair_cost = 0
for item in self.board:
if item.owned_by == player:
repair_cost += item.houses * house_cost + \
item.hotels * hotel_cost
player.cash -= repair_cost
player.last_party = None
self.bank.card_payments += repair_cost # Money goes to table
self.cover_n_central(
"Your repair costs have amounted to $" + str(repair_cost) + ".")
def check_eliminate(self, player):
if player.cash < 0:
self.cover_n_central(player.name + " HAS BEEN ELIMINATED!")
self.liquidate_properties(player)
self.players.pop(self.current_player)
#no need to increment currentPlayer, but set to zero as needed
if self.current_player == len(self.players):
self.current_player = 0
else:
#currentPlayer += 1
self.current_player = self.add_one(self.current_player,
len(self.players))
def liquidate_properties(self, player):
for item in self.board:
if isinstance(item, (Street, Railroad, Utility)) and \
item.owned_by == player:
# give item to last trade partner or the bank
item.owned_by = player.last_party
#Demolish houses and hotels
if item.hotels == 1:
item.hotels = 0
self.bank.hotels += 1
item.houses = 0
else:
self.bank.houses += item.houses
item.houses = 0
#substract amount actually unpaid from last partner/bank
if isinstance(player.last_party, Player):
player.last_party.cash -= - player.cash
else:
self.bank.card_payments -= - player.cash
def eliminate_other_player(self, other_player):
#find other player's index
k = 0
j = 0
n = len(self.players)
for i in range(len(self.players)):
if self.players[i] == other_player:
k = i
if self.players[i] == self.players[self.current_player]:
j = i
self.players.pop(k)
if k < self.current_player:
self.current_player -= 1
if self.current_player == -1:
self.current_player = n-1
def game_end(self):
self.visual_refresh()
if len(self.players) == 1:
self.cover_n_central(self.players[0].name + " HAS WON THE GAME")
else:
best_score = 0
best_player = None
for person in self.players:
if person.cash > best_score:
best_player = person
best_score = person.cash
if best_player is not None:
self.cover_n_central(best_player.name + " HAS WON THE GAME")
else:
self.cover_n_central("INCREDIBLE BUNCH OF LOSERS.")
self.click_n_cover()
def set_places(self):
# Find the length of the side of the board
remainder = len(self.board) % 4
if remainder == 0:
side = len(self.board) / 4 + 1
else:
# increase the side of the square, with some empty places
side = (len(self.board) + remainder)/4 + 1
# Calculate place square size
self.square_side = min(self.width, self.height) / side
# Assign top/left positions for each Place
left = 0
up = 0
orientation = "right"
counter = 0
for item in self.board:
item.x = left
item.y = up
item.orientation = orientation
counter += 1
if counter == side:
orientation = "down"
elif counter == 2 * side - 1:
orientation = "left"
elif counter == 3 * side - 2:
orientation = "up"
if orientation == "right":
left += self.square_side
elif orientation == "down":
up += self.square_side
elif orientation == "left":
left -= self.square_side
elif orientation == "up":
up -= self.square_side
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
purple = (204, 0, 255)
teal = (0, 128, 128)
pink = (253, 221, 230)
orange = (255, 165, 0)
yellow = (255, 255, 0)
brown = (150, 113, 23)
army_green = (75, 83, 32)
dark_green = (0, 100, 0)
coldict = {'Black': black, 'White': white, 'Red': red, 'Green': green,
'Blue': blue, 'Purple': purple, 'Teal': teal, 'Pink': pink,
'Orange': orange, 'Yellow': yellow, 'Brown': brown,
'Army green': army_green, 'Dark_green': dark_green}
for item in self.board:
if isinstance(item, Street):
item.col = coldict[item.neighborhood]
elif isinstance(item, Railroad):
item.col = brown
elif isinstance(item, Utility):
item.col = army_green
elif isinstance(item, FreeParking):
item.col = dark_green
elif isinstance(item, GoToJail):
item.col = dark_green
else:
item.col = white
def draw_board(self):
for item in self.board:
item.draw(self)
for player in self.players:
player.draw(self)
def roll_dice(self, player):
a = random.randint(1, 6)
b = random.randint(1, 6)
text = "Dice roll for " + player.name + ": " + str(a) + " " + str(b)
self.central_message(text)
pygame.time.wait(1000)
return [a, b]
def write_left(self, display, font_size, text, font_color, background,
center_tuple, left):
font_obj = pygame.font.Font(None, font_size)
text_surface_obj = font_obj.render(text, True, font_color, background)
text_rect_obj = text_surface_obj.get_rect()
text_rect_obj.center = center_tuple
text_rect_obj.left = left
display.blit(text_surface_obj, text_rect_obj)
def draw_stats(self):
if self.width > self.height:
i = 0
#Draw player stats
for player in self.players:
if player.in_jail:
self.draw_doughnut(self.display, (0, 0, 0), (0, 0, 0),
self.height + 10, 10 + i*30, 10, 5, 1)
self.write_left(self.display, 25,
player.name + ": $" + str(player.cash),
player.col, self.background,
(self.height + 80, 10 + i*30),
self.height + 25)
i += 1
# Draw bank
i += 1
self.write_left(self.display, 20, "Bank: $" + str(self.bank.money),
(0, 0, 0), self.background, (self.height + 80,
10 + i*30),
self.height + 25)
i += 1
self.write_left(self.display, 20, "Houses: " +
str(self.bank.houses), (0, 0, 0),
self.background, (self.height + 80, 10 + i*30),
self.height + 25)
i += 1
self.write_left(self.display, 20, "Hotels: " +
str(self.bank.hotels), (0, 0, 0),
self.background, (self.height + 80, 10 + i*30),
self.height + 25)
# Money on table
i += 1
self.write_left(self.display, 20, "On table: " +
str(self.bank.card_payments),
(0, 0, 0), self.background, (self.height + 80,
10 + i*30),
self.height + 25)
def draw_cards(self, card_set, ind, display, background):
for i in range(len(card_set)):
self.write_left(display, 14, card_set[i].text, (0, 0, 0),
background, (self.square_side + 20,
self.square_side + 10 + i*12),
self.square_side + 20)
pygame.draw.circle(display, (255, 0, 0),
(self.square_side + 5,
self.square_side + 10 + ind*12),
5, 0)
def draw_doughnut(self, display, fill_col, edge_col, x, y, diam, thick_1,
thick_2):
pygame.draw.circle(display, fill_col, (x, y), diam, thick_1)
pygame.draw.circle(display, edge_col, (x, y), diam, thick_2)
def visual_refresh(self):
self.display.fill(self.background)
self.draw_board()
self.draw_stats()
pygame.display.update()
def start_turn(self, player):
message(self.display, "Hello, " + player.name +
", click to begin turn",
(255, 0, 255), self.height/2, self.height/2)
pygame.display.update()
self.click_n_cover()
def click_n_cover(self):
mouse_click = False
while True:
for event in pygame.event.get():
if event.type == loc.MOUSEBUTTONUP:
mouse_click = True
if mouse_click:
self.cover()
break
def wait_n_cover(self, milliseconds):
pygame.time.wait(milliseconds)
self.cover()
def cover(self):
remainder = len(self.board) % 4
side = (len(self.board) + remainder)/4 - 1
pygame.draw.rect(self.display, self.background,
(self.square_side + 1,
self.square_side + 1,
side*self.square_side - 1,
side*self.square_side - 1))
pygame.display.update()
def central_message(self, text):
message(self.display, text, self.background,
min(self.height, self.width)/2, min(self.height, self.width)/2)
def cover_n_central(self, text):
self.cover()
self.central_message(text)
pygame.time.wait(1000)
def choose_place(self):
choose = None
while True:
for event in pygame.event.get():
if event.type == loc.MOUSEBUTTONUP:
m_x, m_y = event.pos
for item in self.board:
if item.x <= m_x <= item.x + self.square_side and \
item.y <= m_y <= item.y + self.square_side:
choose = item.location
break
if choose is not None: # Need valid location
self.cover()
break
return choose
def add_one(self, location, length):
return (location + 1) % length
def draw_yes_no(self, text, button_size, col_yes, col_no, x, y):
message(self.display, text, self.background, x, y + 20)
yes_box = pygame.draw.rect(self.display, col_yes,
(x - int(button_size*1.5), y + 40,
button_size, button_size))
no_box = pygame.draw.rect(self.display, col_no,
(x + int(button_size*0.5), y + 40,
button_size, button_size))
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == loc.MOUSEBUTTONUP:
mouse_x, mouse_y = event.pos
#check click
if yes_box.collidepoint(mouse_x, mouse_y):
return "yes"
if no_box.collidepoint(mouse_x, mouse_y):
return "no"
def yes_no(self, text, button_size):
red = (255, 0, 0)
green = (0, 255, 0)
x = min(self.width, self.height)/2
y = x
#draw yes/no boxes
return self.draw_yes_no(text, button_size, green, red, x, y)
def button(self, text, box_color, left, up, width, thickness):
text_box = pygame.draw.rect(self.display, box_color,
(left, up, width, thickness))
message(self.display, text, box_color, left + width/2,
up + thickness/2)
pygame.display.update()
return text_box
def trade_board(self, sell, x, player_left, player_right):
message(self.display, "Time to trade!", self.background, x,
self.height/5 - 20)
message(self.display, player_left.name, self.background, x/2,
self.height/5)
message(self.display, player_right.name, self.background,
x + x/2, self.height/5)
message(self.display, "You give:", self.background,
x/2, self.height/5 + 20)
for i in range(len(sell)):
item = sell[i]
if isinstance(item, (Street, Railroad, Utility)):
message(self.display, item.name, self.background, x/2,
self.height/5 + 20*(2 + i))
else:
print "$" + str(item)
def sell_list(self, sell, x):
for i in range(len(sell)):
item = sell[i]
message(self.display, item.name, self.background, x,
self.height/5 + 20*(2 + i))
def player_arrows(self, player):
for item in self.board:
if item.owned_by == player and item.houses == 0:
item.draw_arrow(self)
def choose_places(self, central, seller, buyer, player, place_list, text):
red = (255, 0, 0)
button_w = 120
self.cover()
self.trade_board(self.sell, central, seller, buyer)
self.sell_list(self.sell, central/2)
self.sell_list(self.buy, central + central/2)
self.player_arrows(player)
enough = self.button(text, red, central - button_w/2,
self.height - 3*self.square_side, button_w, 30)
pygame.display.update()
while True:
exit_loop = False
for event in pygame.event.get():
if event.type == loc.MOUSEBUTTONUP:
mouse_x, mouse_y = event.pos
if enough.collidepoint(mouse_x, mouse_y):
exit_loop = True
break
for item in self.board:
if item.x <= mouse_x <= item.x + self.square_side and \
item.y <= mouse_y <= item.y + self.square_side:
if not item.in_trade and item.owned_by == player \
and item.houses == 0:
item.in_trade = True
place_list.append(item)
elif item.in_trade and item.owned_by == player:
item.in_trade = False
place_list.remove(item)
self.cover()
self.trade_board(self.sell, central, seller, buyer)
self.sell_list(self.sell, central/2)
self.sell_list(self.buy, central + central/2)
self.player_arrows(player)
enough = self.button(
text, red, central - button_w/2,
self.height - 3*self.square_side, button_w, 30)
pygame.display.update()
break
if exit_loop:
break
def move_table(self, player):
#player gets money on the table
self.cover_n_central("Congratulations, " + player.name +
"! You have landed on Free Parking!")
self.cover_n_central(
"You get ${0} from the community & chance card payments.".format(
str(self.bank.card_payments)))
player.cash += self.bank.card_payments
self.bank.card_payments = 0
def capture_word(self, y_pos):
name = ""
green = (0, 255, 0)
central = min(self.width, self.height)/2
while True:
for event in pygame.event.get():
if event.type == loc.KEYDOWN:
if event.unicode.isalpha():
name += event.unicode
self.button(name, green,
central - max(10*len(name), 100)/2, y_pos,
max(10*len(name), 100), 20)
elif event.key == loc.K_BACKSPACE:
#cover the button
self.button("", self.background,
central - max(10*len(name), 100)/2, y_pos,
max(10*len(name), 100), 20)
name = name[:-1]
self.button(name, green,
central - max(10*len(name), 100)/2, y_pos,
max(10*len(name), 100), 20)
elif event.key == loc.K_RETURN and len(name) > 0:
return name
def add_values(self, value, item_list):
for item in item_list:
if isinstance(item, Street):
value += item.rent_h
if isinstance(item, Railroad):
value += item.rent4
if isinstance(item, Utility):
value += 70
return value
def neighb_value(self, neighborhood):
value = 0
for street in neighborhood:
value += street.rent_h
return value
def display_trade_cash(self, player_1, player_2, central, button_w):
left = self.button(
"Gives: " + str(max(-self.trade_cash, 0)), player_1.col,
central/2 - button_w/4, self.height - 3*self.square_side,
button_w/2, 30)
right = self.button(
"Gives: " + str(max(self.trade_cash, 0)), player_2.col,
central + central/2 - button_w/4, self.height - 3*self.square_side,
button_w/2, 30)
def transfer_properties(self, initiator, chosen_one):
# Transfer properties
for item in self.sell:
item.owned_by = chosen_one
for item in self.buy:
item.owned_by = initiator
# Transfer cash
initiator.cash += self.trade_cash
chosen_one.cash -= self.trade_cash
self.cover_n_central("Processing trade...")
self.visual_refresh()
def robot_negotiate(self, receiver, sender):
receiver_value = 0
sender_value = 0
# Check for complete neighborhoods
for item in self.buy:
#find neighborhood
my_neighborhood = None
for neighborhood in self.neighborhoods.values():
for street in neighborhood:
if street == item:
my_neighborhood = neighborhood
if my_neighborhood is not None:
# 1. Do not dismantle own neighborhood
all_mine = True
for street in my_neighborhood:
if street.owned_by != receiver:
all_mine = False
if all_mine:
return False
# 2. Don't give streets used by opponent to finish neighborhood
# in 25% of the cases (sometimes the cheatoid is stubborn)
all_their = True
for street in my_neighborhood:
if street.owned_by != sender and street not in self.buy:
all_their = False
if all_their and random.randint(1, 4) == 1:
return False
# Calculate how many neighborhoods each player gains from exchange
old_mine_c, new_mine_c, old_theirs_c, new_theirs_c, receiver_value, \
sender_value = \
self.compute_neighborhoods(
receiver, sender, receiver_value, sender_value)
# Reject outright if other player gets more neighborhoods (1 vs 0 etc)
if new_mine_c - old_mine_c < new_theirs_c - old_theirs_c:
return False
# Parse sell/buy lists
receiver_value += self.add_values(receiver_value, self.sell)
sender_value += self.add_values(sender_value, self.buy)
# Add trade_cash
sender_value += self.trade_cash
# Compare values
result = receiver_value - sender_value
# Add some random element
result -= random.randint(0, int(receiver_value/4))
return result > 0
def show_trade(self, initiator, receiver):
central = min(self.width, self.height)/2
self.cover_n_central(
initiator.name + " wants to trade with " + receiver.name)
message(self.display, receiver.name + "would get:", self.background,
central - central/2, self.height/5 + 20)
self.sell_list(self.sell, central - central/2)
message(self.display, initiator.name + " would get:", self.background,
central + central/2, self.height/5 + 20)
self.sell_list(self.buy, central + central/2)
if self.trade_cash < 0:
message(self.display, receiver.name + " would also get $" +
str(-self.trade_cash), self.background, central,
self.height/3)
elif self.trade_cash > 0:
message(self.display, initiator.name + " would also get $" +
str(self.trade_cash), self.background, central,
self.height/3)
def compute_neighborhoods(self, receiver, sender, receiver_value,
sender_value):
old_mine_c = 0
new_mine_c = 0
old_theirs_c = 0
new_theirs_c = 0
for neighborhood in self.neighborhoods.values():
old_mine = True
new_mine = True
old_theirs = True
new_theirs = True
for strt in neighborhood:
if strt.owned_by != receiver:
old_mine = False
if strt.owned_by != sender:
old_theirs = False
if (strt.owned_by != receiver and strt not in self.sell) or \
(strt.owned_by == receiver and strt in self.buy):
new_mine = False
if (strt.owned_by != sender and strt not in self.buy) \
or (strt.owned_by == sender and strt in self.sell):
new_theirs = False
# Count how many new neighborhoods each player gets
old_mine_c += old_mine
old_theirs_c += old_theirs
new_mine_c += new_mine
new_theirs_c += new_theirs
# Add value of entire neighborhood to player estimations
receiver_value += \
self.neighb_value(neighborhood)*(new_mine - old_mine)/2
sender_value += \
self.neighb_value(neighborhood)*(new_theirs - old_theirs)/2
return old_mine_c, new_mine_c, old_theirs_c, new_theirs_c, \
receiver_value, sender_value
def compute_trade(self, receiver, sender):
old_mine_c, new_mine_c, old_theirs_c, new_theirs_c, receiver_value, \
sender_value = \
self.compute_neighborhoods(receiver, sender, 0, 0)
receiver_value += self.add_values(receiver_value, self.sell)
sender_value += self.add_values(sender_value, self.buy)
return sender_value, receiver_value
def send_trade(self, receiver, sender):
self.show_trade(sender, receiver)
pygame.time.wait(1000)
response = receiver.reply_negotiate(self, sender)
if response:
self.transfer_properties(sender, receiver)
else:
sender.other_players[receiver] = 2
def return_card_and_add(self, card_set, position, card):
card_set.insert(position, card)
return self.add_one(position, len(card_set))
class Bank(object):
"""
In standard editions of Monopoly the Bank has USD 15,140.
Source: http://boardgames.about.com/od/monopolyfaq/f/bank_money.htm
"""
#payments made by players as defined in community/chance cards are
#cumulated into this account and are paid to the first player getting to
#Free Parking
card_payments = 0
def __init__(self, game):
self.money = game.money
self.houses = game.houses
self.hotels = game.hotels
def move_money(self, amount, player):
#move money from/to player to/from bank
player.cash += amount
self.money -= amount
def move_money_to_table(self, amount, player):
#move money from player to table
player.cash += amount
self.card_payments -= amount
#if player pays money to the bank
if amount < 0:
player.last_party = None
class Place(object):
"""
There are several types of places on the Monopoly board:
- streets
- railroads
- utilities
- community chests
- chances
- taxes
- jail
- go to jail
- free parking
- Start
"""
location = None
owned_by = None
mortgaged = False
houses = 0
hotels = 0
hotel_cost = 0
house_cost = 0
x = 0
y = 0
orientation = None
col = None
txt = ""
in_trade = False
def write(self, text, font_size, col, background, lines, line_height,
display, game):
font_obj = pygame.font.Font(None, font_size)
text_surface_obj = font_obj.render(text, True, col, background)
text_rect_obj = text_surface_obj.get_rect()
text_rect_obj.center = (self.x + game.square_side/2,
self.y + lines*line_height)
display.blit(text_surface_obj, text_rect_obj)
def draw(self, game):
# Draw place rectangle
pygame.draw.rect(game.display, self.col,
(self.x, self.y, game.square_side, game.square_side))
# Draw street owner color, if any
if self.owned_by is not None and isinstance(self, Street):
pygame.draw.rect(game.display, self.owned_by.col,
(self.x,
self.y + game.square_side - game.square_side/2,
game.square_side, game.square_side/2))
# Draw central text
col = (0, 0, 0)
if isinstance(self, GoToJail) or isinstance(self, Jail) or \
isinstance(self, Chance):
col = (255, 0, 0)
if isinstance(self, Railroad) or isinstance(self, Utility):
y_pos = game.square_side/2 + 5
else:
y_pos = game.square_side/2
self.write(self.txt, 40, col, self.col, 1, y_pos, game.display, game)
# Draw railroad/utility owner color, if any
if self.owned_by is not None and isinstance(self, (Railroad, Utility)):
pygame.draw.rect(game.display, self.owned_by.col,
(self.x,
self.y + game.square_side - game.square_side/4,
game.square_side, game.square_side/4))
# Draw community chest symbol
if isinstance(self, CommunityChest):
pygame.draw.circle(game.display, (255, 247, 0),
(self.x + game.square_side/2,
self.y + game.square_side/2),
game.square_side/2, game.square_side/2)
# Draw place names and split it as necessary
background = self.col
owner_name = ""
if self.owned_by is not None:
#col = (180, 180, 180)
owner_name = self.owned_by.name
if isinstance(self, Street) or isinstance(self, Utility) or \
isinstance(self, Railroad):
name_split = self.name.split(" ")
name_end = name_split[-1]
name_begin = " ".join(name_split[:-1])
lines = 1
if len(name_begin) != 0:
self.write(name_begin, game.font_size, col, background, lines,
game.line_height, game.display, game)
lines += 1
self.write(name_end, game.font_size, col, background, lines,
game.line_height, game.display, game)
lines += 1
if isinstance(self, (Utility, Railroad)) and \
self.owned_by is not None:
lines += 4
background = self.owned_by.col
self.write(owner_name, game.font_size, col, background, lines,
game.line_height, game.display, game)
# Draw street houses and hotels
if isinstance(self, Street):
empty_col = self.col
full_col = (11, 255, 255)
for i in range(4):
if self.houses >= i + 1: