def play(need_load_game=False, data=None): """ This is the main play function, the game essentially takes place here """ # Initial game object initialisations if need_load_game: p1_c1 = data["p1_c1"] p1_c2 = data["p1_c2"] p2_c1 = data["p2_c1"] p2_c2 = data["p2_c2"] die = data["die"] # Update the rects for the counters and die p1_c1.from_load() p1_c2.from_load() p2_c1.from_load() p2_c2.from_load() die.from_load() # Game play variables names = data["names"] p1_c1_move = data["p1_c1_move"] p1_c2_move = data["p1_c2_move"] p2_c1_move = data["p2_c1_move"] p2_c2_move = data["p2_c2_move"] die_result = data["die_result"] die_rolled = data["die_rolled"] move_by = data["move_by"] turn = data["turn"] # 1 or 2 scores = data["scores"] else: p1_c1 = Entities.Counter(1, 1) p1_c2 = Entities.Counter(1, 2) p2_c1 = Entities.Counter(2, 1) p2_c2 = Entities.Counter(2, 2) die = Entities.Die() # Game play variables names = display_enter_player_names() p1_c1_move = True, None p1_c2_move = True, None p2_c1_move = True, None p2_c2_move = True, None die_result = 0 die_rolled = False move_by = 0 turn = 1 # 1 or 2 scores = [0, 0] # Player 1 score, Player 2 score # Set up text and button objects current_player = Entities.Text(small_font, "Current Player", Colours.WHITE, 430, 135) txt_player_one = Entities.Text(small_font, names[0], Colours.WHITE, 430, 150) txt_player_two = Entities.Text(small_font, names[1], Colours.WHITE, 430, 150) txt_hint = Entities.Text(small_font, "Test", Colours.WHITE, width / 2, 380) btn_load = Entities.Button(small_font, "Load", Colours.WHITE, 430, 214) btn_save = Entities.Button(small_font, "Save", Colours.WHITE, 430, 246) btn_rules = Entities.Button(small_font, "Rules", Colours.WHITE, 430, 278) btn_return = Entities.Button(small_font, "Return to\nMenu", Colours.WHITE, 430, 305) # Draw to the screen def render_board(): renderer.update_display(display) renderer.add(p1_c1) renderer.add(p1_c2) renderer.add(p2_c1) renderer.add(p2_c2) renderer.add(die) renderer.add(current_player) renderer.add(txt_player_one if turn == 1 else txt_player_two) renderer.add(btn_load) renderer.add(btn_save) renderer.add(btn_rules) renderer.add(btn_return) renderer.add(txt_hint) renderer.draw("bg_play", Colours.BLACK) def end_turn(): """ Handle end of turn information such as switching of turns, die image reset etc. """ new_turn = 1 if turn == 2 else 2 die.update_image(0) check_winner() return new_turn, False, 0, 1 def check_winner(): """ Check if a player has both of their counters on row 11 (FINISH) """ if p1_c1.get_row() == 11 and p1_c2.get_row() == 11: display_winner(names[0], scores[0]) if p2_c1.get_row() == 11 and p2_c2.get_row() == 11: display_winner(names[1], scores[1]) def calculate_move_by(result): """ Calculate the move_by variable based on the die result, essentially convert the die result into the movement distance as specified by the rules """ movement = 0 if result in [1, 2, 3]: return result elif result == 4: movement = -1 elif result == 5: movement = "available" return movement def get_move_text(movement): """ Return the text to display to the user based on their movement result """ if movement == 1: return "select counter to move 1 space closer to FINISH!" elif movement in [2, 3]: return "select counter to move " + str( movement) + " spaces closer to FINISH!" elif movement == -1: return "select counter to move 1 space closer to START!" elif movement == "available": return "select counter to move to next EMPTY row!" # Main game loop while True: # Handle events (beginning of game logic - i.e clicks on the window) for e in pygame.event.get(): if e.type == pygame.QUIT: quit_game() die_event = die.event(e, die_rolled) # Check if the die was clicked if die_event[0]: if not die_rolled: die_result = die_event[1] die_rolled = True move_by = calculate_move_by(die_result) if turn == 1: p1_c1_move = p1_c1.can_move(move_by, p1_c2.get_row(), p2_c1.get_row(), p2_c2.get_row()) p1_c2_move = p1_c2.can_move(move_by, p1_c1.get_row(), p2_c1.get_row(), p2_c2.get_row()) elif turn == 2: p2_c1_move = p2_c1.can_move(move_by, p2_c2.get_row(), p1_c1.get_row(), p1_c2.get_row()) p2_c2_move = p2_c2.can_move(move_by, p2_c1.get_row(), p1_c1.get_row(), p1_c2.get_row()) else: txt_hint.update_text("You can only roll once!", 2) # Game logic for each player turn if turn == 1: if p2_c1.event(e) or p2_c2.event(e): txt_hint.update_text("This isn't your counter!", 2) elif die_rolled: if not p1_c1_move[0] and p1_c1.event(e): txt_hint.update_text("This counter cannot be moved!", 2) elif p1_c1_move[0] and p1_c1.event(e): p1_c1.move(p1_c1_move[1]) scores[0] += p2_c1.counter_moved(p1_c1.get_row()) scores[0] += p2_c2.counter_moved(p1_c1.get_row()) turn, die_rolled, die_result, txt_hint.get_text_manager( ).priority = end_turn() elif not p1_c2_move[0] and p1_c2.event(e): txt_hint.update_text("This counter cannot be moved!", 2) elif p1_c2_move[0] and p1_c2.event(e): p1_c2.move(p1_c2_move[1]) scores[0] += p2_c1.counter_moved(p1_c2.get_row()) scores[0] += p2_c2.counter_moved(p1_c2.get_row()) turn, die_rolled, die_result, txt_hint.get_text_manager( ).priority = end_turn() elif not p1_c1_move[0] and not p1_c2_move[0]: txt_hint.update_text( "No counter can move, ending turn...", 3) render_board() time.sleep(5) turn, die_rolled, die_result, txt_hint.get_text_manager( ).priority = end_turn() elif p1_c1.event(e) or p1_c2.event(e): txt_hint.update_text( names[turn - 1] + ", you need to roll the die first!", 2) elif turn == 2: if p1_c1.event(e) or p1_c2.event(e): txt_hint.update_text("This isn't your counter!", 2) elif die_rolled: if not p2_c1_move[0] and p2_c1.event(e): txt_hint.update_text("This counter cannot be moved!", 2) elif p2_c1_move[0] and p2_c1.event(e): p2_c1.move(p2_c1_move[1]) scores[1] += p1_c1.counter_moved(p2_c1.get_row()) scores[1] += p1_c2.counter_moved(p2_c1.get_row()) turn, die_rolled, die_result, txt_hint.get_text_manager( ).priority = end_turn() if not p2_c2_move[0] and p2_c2.event(e): txt_hint.update_text("This counter cannot be moved!", 2) elif p2_c2_move[0] and p2_c2.event(e): p2_c2.move(p2_c2_move[1]) scores[1] += p1_c1.counter_moved(p2_c2.get_row()) scores[1] += p1_c2.counter_moved(p2_c2.get_row()) turn, die_rolled, die_result, txt_hint.get_text_manager( ).priority = end_turn() elif not p2_c1_move[0] and not p2_c2_move[0]: txt_hint.update_text( "No counter can move, ending turn...", 2) render_board() time.sleep(5) turn, die_rolled, die_result, txt_hint.get_text_manager( ).priority = end_turn() elif p2_c1.event(e) or p2_c2.event(e): txt_hint.update_text( names[turn - 1] + ", you need to roll the die first!", 2) # Current data - used if user clicks save from side menu current_data = { "p1_c1": p1_c1, "p1_c2": p1_c2, "p2_c1": p2_c1, "p2_c2": p2_c2, "die": die, "names": names, "p1_c1_move": p1_c1_move, "p1_c2_move": p1_c2_move, "p2_c1_move": p2_c1_move, "p2_c2_move": p2_c2_move, "die_result": die_result, "die_rolled": die_rolled, "move_by": move_by, "turn": turn, "scores": scores } display_saved_games("play") if btn_load.event(e) else False display_save_screen(current_data) if btn_save.event(e) else False display_rules("play") if btn_rules.event(e) else False display_main_menu() if btn_return.event(e) else False # Remaining game logic if not die_rolled: txt_hint.update_text(names[turn - 1] + ", click the die to roll!") elif die_result != 0: txt_hint.update_text(names[turn - 1] + " rolled a " + str(die_result) + ", " + get_move_text(move_by)) # Render the game board to the screen render_board() # Pause loop for a time so that we can get the TARGET_FPS clock.tick(TARGET_FPS)