1
+ import time
2
+ import numpy as np
3
+ import pygame as pg
4
+ from collections import Counter
5
+
6
+ # COLOURS
7
+ WHITE = (255 , 255 , 255 )
8
+ BLACK = (0 , 0 , 0 )
9
+ GREY = (175 , 175 , 175 )
10
+ GENTIAN = (100 , 25 , 255 )
11
+ BRIGHTER_GENTIAN = (150 , 25 , 255 )
12
+ BROWN1 = (170 , 90 , 5 )
13
+ BROWN2 = (150 , 110 , 10 )
14
+ DULL_RED = (200 , 0 , 0 )
15
+ RED = (255 , 0 , 0 )
16
+ BLUE = (70 , 210 , 255 )
17
+ BRIGHT_GREEN = (0 , 255 , 0 )
18
+ GREEN = (0 , 200 , 0 )
19
+
20
+
21
+ class Pad :
22
+ def __init__ (self , colour , radius , x , y , hide = True ):
23
+ self .colour = colour
24
+ self .radius = int (round (radius ))
25
+ self .x = int (round (x ))
26
+ self .y = int (round (y ))
27
+ self .hide = hide
28
+
29
+ def mark (self ):
30
+ a = Pad (WHITE , self .radius , self .x , self .y , False )
31
+ return a
32
+
33
+
34
+ class Table :
35
+ def __init__ (self , s , colour , radius , x , y , pc ):
36
+ self .size = s
37
+ self .colour = colour
38
+ self .radius = int (round (radius ))
39
+ self .angle = 0
40
+ self .x = int (round (x ))
41
+ self .y = int (round (y ))
42
+ self .pads = list (Pad (pc [j ], self .radius * pow (4 , 0.75 )/ (3 * pow (size , 0.75 )), self .x + self .radius * 2 / 3 *
43
+ np .cos (self .angle + j * np .pi * 2 / size ),
44
+ self .y + self .radius * 2 / 3 * np .sin (self .angle + j
45
+ * np .pi * 2 / size )) for j in range (size ))
46
+ self .spin_count = 0
47
+ self .choices = 0
48
+
49
+ def shift (self , n , m ):
50
+ colours = [pad .colour for pad in self .pads ]
51
+ for i in range (self .size ):
52
+ self .pads [(i + m ) % self .size ].colour = colours [(i + n ) % self .size ]
53
+
54
+ def spin (self ):
55
+ self .choices = 0
56
+ self .angle = np .random .uniform (0 , 2 * np .pi )
57
+ for j in range (self .size ):
58
+ self .pads [j ].x = int (round (self .x + self .radius * 2 / 3 * np .cos (self .angle + j * np .pi * 2 / self .size )))
59
+ self .pads [j ].y = int (round (self .y + self .radius * 2 / 3 * np .sin (self .angle + j * np .pi * 2 / self .size )))
60
+ self .spin_count += 1
61
+ for pad in self .pads :
62
+ pad .hide = True
63
+
64
+ def switch (self , pad ):
65
+ i = self .pads .index (pad )
66
+ if self .pads [i ].colour == RED :
67
+ self .pads [i ].colour = BLUE
68
+ else :
69
+ self .pads [i ].colour = RED
70
+
71
+
72
+ def random_colour ():
73
+ if np .random .randint (2 ) == 0 :
74
+ return RED
75
+ else :
76
+ return BLUE
77
+
78
+
79
+ # game prep (must be done in terminal)
80
+ size = int (input ('Enter number of pads: ' ))
81
+ hands = int (input ('Enter number of hands: ' ))
82
+ # SIZE AT LEAST 4 FOR GOOD SPACING
83
+ # size = 4
84
+ # hands = 2
85
+
86
+ # START PYGAME
87
+ pg .init ()
88
+
89
+ display_width = 1000
90
+ display_height = 600
91
+
92
+ game_display = pg .display .set_mode ((display_width , display_height ))
93
+ pg .display .set_caption ("Table Spin" )
94
+ pg.display .update ()
95
+ clock = pg .time .Clock ()
96
+
97
+ pad_colours = [0 ] * size
98
+ table = Table (size , 0 , 0 , 0 , 0 , pad_colours )
99
+ win = False
100
+ click = False
101
+ reveal = False
102
+ adversary = False
103
+
104
+
105
+ def see ():
106
+ global reveal
107
+ reveal = True
108
+
109
+
110
+ def set_up ():
111
+ # create random pad colours
112
+ global pad_colours
113
+ pad_colours = [random_colour () for j in range (size )]
114
+ # initialize table
115
+ global table
116
+ table = Table (size , BROWN1 , display_height * 3 / 8 , display_width / 2 , display_height * 4 / 9 , pad_colours )
117
+
118
+
119
+ def draw (obj , hidden = False , white = False ):
120
+ if white :
121
+ pg .draw .circle (game_display , WHITE , (obj .x , obj .y ), obj .radius )
122
+ elif hidden :
123
+ pg .draw .circle (game_display , GREY , (obj .x , obj .y ), obj .radius )
124
+ else :
125
+ pg .draw .circle (game_display , obj .colour , (obj .x , obj .y ), obj .radius )
126
+
127
+
128
+ def show_button (pad , ic , ac ):
129
+ mouse = pg .mouse .get_pos ()
130
+
131
+ if np .sqrt (np .square (pad .x - mouse [0 ]) + np .square (pad .y - mouse [1 ])) < pad .radius :
132
+ pg .draw .circle (game_display , ac , (pad .x , pad .y ), pad .radius )
133
+
134
+ if click and table .choices < hands :
135
+ pad .hide = False
136
+ draw (pad , white = True )
137
+ table .choices += 1
138
+
139
+ else :
140
+ pg .draw .circle (game_display , ic , (pad .x , pad .y ), pad .radius )
141
+
142
+
143
+ def switch_button (pad ):
144
+ mouse = pg .mouse .get_pos ()
145
+ # click = pg.mouse.get_pressed()
146
+
147
+ draw (pad , pad .hide )
148
+ if np .sqrt (np .square (pad .x - mouse [0 ]) + np .square (pad .y - mouse [1 ])) < pad .radius and click :
149
+ if not pad .hide :
150
+ table .switch (pad )
151
+ draw (pad , pad .hide )
152
+
153
+
154
+ def game_spin ():
155
+ game_display .fill (BLACK )
156
+ pg .display .update ()
157
+ time .sleep (0.5 )
158
+ global reveal , win , adversary
159
+ adversary = False
160
+ reveal = False
161
+ table .spin ()
162
+
163
+
164
+ def spin_button ():
165
+ square_button ("SPIN" , display_width / 2 - 112 , 540 , 100 , 50 , GENTIAN , BRIGHTER_GENTIAN , game_spin )
166
+
167
+
168
+ def reveal_button ():
169
+ square_button ("REVEAL" , display_width / 2 + 12 , 540 , 100 , 50 , GENTIAN , BRIGHTER_GENTIAN , see )
170
+
171
+
172
+ def menu_button ():
173
+ square_button ("MENU" , 875 , 540 , 100 , 50 , DULL_RED , RED , game_intro )
174
+
175
+
176
+ def buttons ():
177
+ spin_button ()
178
+ reveal_button ()
179
+ menu_button ()
180
+
181
+
182
+ def draw_pads1 ():
183
+ for pad in table .pads :
184
+ if pad .hide :
185
+ show_button (pad , GREY , WHITE )
186
+ else :
187
+ draw (pad .mark ())
188
+
189
+
190
+ def draw_pads2 ():
191
+ global adversary
192
+ if not adversary :
193
+ chosen = [not a .hide for a in table .pads ]
194
+ ids = [i for i , x in enumerate (chosen ) if not x ]
195
+ n = len (ids )
196
+ skips = []
197
+ for i in range (n ):
198
+ if n == 1 :
199
+ break
200
+ elif i == n - 1 :
201
+ skip = table .size % (ids [i ] - ids [0 ])
202
+ else :
203
+ skip = ids [i + 1 ] - ids [i ]
204
+ if Counter (a [0 ] for a in skips )[str (skip )] == 0 :
205
+ skips .append ([skip , ids [i ]])
206
+ for skip in skips :
207
+ for i in range (table .size ):
208
+ if table .pads [i ].colour != table .pads [(i + skip [0 ]) % table .size ].colour :
209
+ # if (ids[0] + skip) % table.size == ids[1]:
210
+ # n = ids[0]
211
+ # else:
212
+ # n = ids[1]
213
+ table .shift (i , skip [1 ])
214
+ adversary = True
215
+ break
216
+ for pad in table .pads :
217
+ if pad .hide :
218
+ draw (pad , hidden = True )
219
+ else :
220
+ draw (pad .mark ())
221
+
222
+
223
+ def draw_pads3 ():
224
+ for pad in table .pads :
225
+ if pad .hide :
226
+ draw (pad , hidden = True )
227
+ else :
228
+ switch_button (pad )
229
+
230
+
231
+ def text_object (text , font ):
232
+ text_surface = font .render (text , True , WHITE )
233
+ return text_surface , text_surface .get_rect ()
234
+
235
+
236
+ def message_display (text , s , x , y ):
237
+ normal_text = pg .font .Font ('freesansbold.ttf' , s )
238
+ text_surf , text_rect = text_object (text , normal_text )
239
+ text_rect .center = (round (x ), round (y ))
240
+ game_display .blit (text_surf , text_rect )
241
+
242
+ pg .display .update ()
243
+
244
+
245
+ def win_msg ():
246
+ for pad in table .pads :
247
+ draw (pad )
248
+ pg .display .update ()
249
+ time .sleep (1 )
250
+ game_display .fill (BLACK )
251
+ message_display ("Congratulations," , 80 , display_width / 2 , display_height / 3 )
252
+ if table .spin_count == 0 :
253
+ message_display ("you won without spinning!" , 65 , display_width / 2 , display_height / 2 )
254
+ elif table .spin_count == 1 :
255
+ message_display ("you won after a single spin!" , 65 , display_width / 2 , display_height / 2 )
256
+ else :
257
+ message_display ("you won after " + str (table .spin_count ) + " spins!" , 80 , display_width / 2 , display_height / 2 )
258
+ pg .display .update ()
259
+ time .sleep (3 )
260
+ game_intro ()
261
+
262
+
263
+ def square_button (msg , x , y , w , h , ic , ac , action = None ):
264
+ global click
265
+ x = int (round (x ))
266
+ y = int (round (y ))
267
+ w = int (round (w ))
268
+ h = int (round (h ))
269
+ mouse = pg .mouse .get_pos ()
270
+ click = pg .mouse .get_pressed ()
271
+
272
+ if x + w > mouse [0 ] > x and y + h > mouse [1 ] > y :
273
+ pg .draw .rect (game_display , ac , (x , y , w , h ))
274
+
275
+ if click [0 ] == 1 and action is not None :
276
+ action ()
277
+ else :
278
+ pg .draw .rect (game_display , ic , (x , y , w , h ))
279
+
280
+ small_text = pg .font .Font ("freesansbold.ttf" , 20 )
281
+ text_surf , text_rect = text_object (msg , small_text )
282
+ text_rect .center = (int (x + (w / 2 )), int (y + (h / 2 )))
283
+ game_display .blit (text_surf , text_rect )
284
+
285
+
286
+ def game_loop ():
287
+ global win , click , reveal
288
+ win = False
289
+ reveal = False
290
+ game_display .fill (BLACK )
291
+ while not win :
292
+ click = False
293
+ for event in pg .event .get ():
294
+ if event .type == pg .QUIT :
295
+ pg .quit ()
296
+ quit ()
297
+ elif event .type == pg .MOUSEBUTTONDOWN :
298
+ click = True
299
+ draw (table )
300
+ if reveal :
301
+ draw_pads3 ()
302
+ elif table .choices < hands :
303
+ draw_pads1 ()
304
+ elif table .choices == hands :
305
+ draw_pads2 ()
306
+ message_display ("Spin Count: " + str (table .spin_count ), 30 , display_width / 2 , 515 )
307
+ buttons ()
308
+ if all (table .pads [i ].colour == table .pads [0 ].colour for i in range (1 , size )):
309
+ win = True
310
+ pg .display .update ()
311
+ clock .tick (60 )
312
+ win_msg ()
313
+ time .sleep (2 )
314
+ game_intro ()
315
+
316
+
317
+ def game_intro ():
318
+ set_up ()
319
+ if all (pad_colours [0 ] == pad_colours [i ] for i in range (1 , size )):
320
+ table .switch (table .pads [size - 1 ])
321
+ game_display .fill (BLACK )
322
+ while True :
323
+ for event in pg .event .get ():
324
+ print (event )
325
+ if event .type == pg .QUIT :
326
+ pg .quit ()
327
+ quit ()
328
+
329
+ message_display ("Table Spin" , 100 , display_width / 2 , display_height / 3 )
330
+
331
+ square_button ("Play" , 250 , 450 , 100 , 50 , GREEN , BRIGHT_GREEN , game_loop )
332
+ square_button ("Quit" , 650 , 450 , 100 , 50 , DULL_RED , RED , quit )
333
+ pg .display .update ()
334
+ clock .tick (60 )
335
+
336
+
337
+ game_intro ()
0 commit comments