Ludo Game Python
Ludo Game Python
Computer Engineering
Submitted By
Kranti Shinde
Roll no : 60[FS]
Gramin Polytechnic,
Vishnupuri, Nanded - 431606
Maharashtra, India
2021-22
CERTIFICATE
This is certify that the project entitled “Ludo Game” being submitted by
“Kranti Shinde “ to Maharashtra State Board Of Technical Education, Mumbai as
a partial fulfilment of award of diploma in Computer Engineering is record of
bonafide work carried out by them under my supervision and guidance. The matter
contained in this project work has not been submitted to any other institute for
award of any degree or diploma.
Dr.V.S.Pawar
Principal
ACKNOWLEDGEMENT
We are thankful to our Hon. Principal Dr. V. S. Pawar he has co-operated us
by providing the needful resources in our college laboratories and giving us the
permission for extra time in college laboratories. He has provided computer labs for
getting information and data of different things which helps to develop our project.
We owe sense of deep gratitude to our Vice-Principal for their constant
inspiring encouragement.
Needless to mention that Mr. Mr. Maske P. S who has been a source of
inspiration and for his timely guidance in conduct of our project.
We express our profound thanks to the Head of the Computer Engineering
Department Mr. Wahi G. S. & Mr. Maske P. S. for providing us necessary resources
in department. A very special thanks to his for suggesting us for this project work.
We materialized is precious idea into a working project. He has been greatly helped
us in solving our problems during the department of our project. Whenever we
approached him he was always there for us and ready with his solutions. He was
always humble and kind for our requests. He has clarified our difficulties and
problems.
We all are very thankful to all the college, staff and students for the kind support.
- Kranti Shinde
Micro Project Report
1.0 Rationale:
This is a Ludo game which is very easy to understand and use. Talking
about the gameplay, all the playing rules are the same just like we play in real
time ludo. Here at first, the user has to select players i.e. either human or
computer. After selecting human, the player has to enter details such as name
and select colour (red, green, yellow and blue). the player can also start the
game within two players if he/she wants.After starting the game, a console
based ludo board appears, other rules are the same. First, the computer or the
The main thing in this console based game is that the player just has to
press “Enter Key” to roll the dice. At the top of the board, it displays a dice
with the number. The system keeps on rolling until there’s a possible pawn to
move. All the game movements are performed automatically. Whenever the
player tries to end the game, there’s an option available to save the unfinished
game so that he/she can continue it later. A simple console GUI is provided
How to Play
1. Ludo player path.
2. Ludo Home.
3. Start area.
5. No resting squares.
Game Rules
1. Four pieces are placed in the start area of their colour.
8. No doubling rules.
cli.py
from .game import Player, Game
from .painter import present_6_die_name
from .recorder import RunRecord, MakeRecord
from os import linesep
class CLIGame():
def __init__(self):
self.prompt_end = "> "
self.game = Game()
# used for nicer print
self.prompted_for_pawn = False
# saving game data
self.record_maker = MakeRecord()
# getting game data
self.record_runner = None
def does_user_want_save_game(self):
text = linesep.join(["Save game?",
"0 - No",
"1 - Yes"])
choice = self.validate_input(text, int, (0, 1))
return choice == 1
def prompt_for_player(self):
available_colours = self.game.get_available_colours()
text = linesep.join(["choose type of player",
"0 - computer",
"1 - human"])
choice = self.validate_input(text, int, (0, 1))
if choice == 1:
name = self.validate_input("Enter name for player",
str, str_len=(1, 30))
available_options = range(len(available_colours))
if len(available_options) > 1:
# show available colours
options = ["{} - {}".format(index, colour)
for index, colour in
zip(available_options,
available_colours)]
text = "choose colour" + linesep
text += linesep.join(options)
choice = self.validate_input(text, int, available_options)
colour = available_colours.pop(choice)
else
colour = available_colours.pop()
player = Player(colour, name, self.prompt_choose_pawn)
elif choice ==
colour = available_colours.pop()
player = Player(colour)
self.game.add_palyer(player)
def prompt_for_players(self):
counts = ("first", "second", "third", "fourth last")
text_add = "Add {} player"
for i in range(2):
print(text_add.format(counts[i]))
self.prompt_for_player()
print("Player added")
def prompt_choose_pawn(self):
text = present_6_die_name(self.game.rolled_value,
str(self.game.curr_player))
text += linesep + "has more than one possible pawns to move."
text += " Choose pawn" + linesep
pawn_options = ["{} - {}".format(index + 1, pawn.id)
for index, pawn
in enumerate(self.game.allowed_pawns)]
text += linesep.join(pawn_options)
index = self.validate_input(
text, int, range(1, len(self.game.allowed_pawns) + 1))
self.prompted_for_pawn = True
return index - 1
def prompt_to_continue(self):
text = "press Enter to continue" + linesep
input(text)
def print_players_info(self):
word = "start" if self.game.rolled_value is None else "continue"
print("Game {} with {} players:".format(
word,
len(self.game.players)))
for player in self.game.players:
print(player)
print()
def print_info_after_turn(self):
pawns_id = [pawn.id for pawn in self.game.allowed_pawns]
message = present_6_die_name(self.game.rolled_value,
str(self.game.curr_player))
message += linesep
if self.game.allowed_pawns:
message_moved = "{} is moved. ".format(
self.game.picked_pawn.id)
if self.prompted_for_pawn:
self.prompted_for_pawn = False
print(message_moved)
return
message += "{} possible pawns to move.".format(
" ".join(pawns_id))
message += " " + message_moved
if self.game.jog_pawns:
message += "Jog pawn "
message += " ".join([pawn.id for pawn in self.game.jog_pawns])
else:
message += "No possible pawns to move."
print(message)
def print_standing(self):
standing_list = ["{} - {}".format(index + 1, player)
for index, player in enumerate(self.game.standing)]
message = "Standing:" + linesep + linesep.join(standing_list)
print(message)
def print_board(self):
print(self.game.get_board_pic())
def run_recorded_game(self):
self.load_recorded_players()
self.print_players_info()
self.prompt_to_continue()
for rolled_value, index in self.record_runner:
self.game.play_turn(index, rolled_value)
self.print_info_after_turn()
self.print_board()
self.prompt_to_continue()
self.print_board()
def continue_recorded_game(self):
self.load_recorded_players()
self.record_players()
for rolled_value, index in self.record_runner:
self.game.play_turn(index, rolled_value)
self.record_maker.add_game_turn(
self.game.rolled_value, self.game.index)
self.print_players_info()
self.print_info_after_turn()
self.print_board()
def record_players(self):
for player in self.game.players:
self.record_maker.add_player(player)
def load_recorded_players(self):
if self.record_runner is None:
file_descr = self.prompt_for_file()
self.record_runner = RunRecord(file_descr)
file_descr.close()
for player in self.record_runner.get_players(
self.prompt_choose_pawn):
self.game.add_palyer(player)
def load_players_for_new_game(self):
self.prompt_for_players()
self.print_players_info()
self.record_players()
def play_game(self):
try:
while not self.game.finished:
self.game.play_turn()
self.print_info_after_turn()
self.print_board()
self.record_maker.add_game_turn(
self.game.rolled_value, self.game.index)
self.prompt_to_continue()
print("Game finished")
self.print_standing()
self.offer_save_game()
except (KeyboardInterrupt, EOFError):
print(linesep +
"Exiting game. " +
"Save game and continue same game later?")
self.offer_save_game()
raise
def offer_save_game(self):
'''offer user save game'''
if self.does_user_want_save_game():
file_descr = self.prompt_for_file(mode="wb")
self.record_maker.save(file_descr)
file_descr.close()
print("Game is saved")
def start(self):
'''main method, starting cli'''
print()
try:
choice = self.get_user_initial_choice()
if choice == 0: # start new game
self.load_players_for_new_game()
self.play_game()
elif choice == 1: # continue game
self.continue_recorded_game()
if self.game.finished:
print("Could not continue.",
"Game is already finished",
linesep + "Exit")
else:
self.prompt_to_continue()
self.play_game()
elif choice == 2: # review played game
self.run_recorded_game()
except (KeyboardInterrupt, EOFError):
print(linesep + "Exit Game")
if __name__ == '__main__':
CLIGame().start()
Recorder.py
import pickle
from .game import Player
class RunRecord():
def get_game_history(self):
return self.game_history
def __iter__(self):
return iter(self.game_history)
class MakeRecord():
def __init__(self):
self.players = []
self.game_history = []
if player_obj.choose_pawn_delegate is None:
is_computer = True
else:
is_computer = False
self.players.append((player_obj.colour,
player_obj.name, is_computer))
class Player():
def __init__(self, colour, name=None, choose_pawn_delegate=None):
self.colour = colour
self.choose_pawn_delegate = choose_pawn_delegate
self.name = name
if self.name is None and self.choose_pawn_delegate is None:
self.name = "computer"
self.finished = False
def __str__(self):
return "{}({})".format(self.name, self.colour)
if len(pawns) == 1:
index = 0
elif len(pawns) > 1:
if self.choose_pawn_delegate is None:
index = random.randint(0, len(pawns) - 1)
else:
index = self.choose_pawn_delegate()
return index
class Board():
BOARD_SIZE = 56
BOARD_COLOUR_SIZE = 7
COLOUR_DISTANCE = 14
def __init__(self):
Board.COLOUR_START = {
colour: 1 + index * Board.COLOUR_DISTANCE for
index, colour in enumerate(Board.COLOUR_ORDER)}
Board.COLOUR_END = {
colour: index * Board.COLOUR_DISTANCE
for index, colour in enumerate(Board.COLOUR_ORDER)}
Board.COLOUR_END['yellow'] = Board.BOARD_SIZE
self.pawns_possiotion = {}
self.painter = PaintBoard()
self.board_pool_position = (0, 0)
def paint_board(self):
positions = {}
for pawn, position in self.pawns_possiotion.items():
common, private = position
if not private == Board.BOARD_COLOUR_SIZE:
positions.setdefault(position, []).append(pawn)
return self.painter.paint(positions)
class Die():
MIN = 1
MAX = 6
@staticmethod
def throw():
return random.randint(Die.MIN, Die.MAX)
class Game():
def __init__(self):
self.players = deque()
self.standing = []
self.board = Board()
# is game finished
self.finished = False
# last rolled value from die (dice)
self.rolled_value = None
# player who last rolled die
self.curr_player = None
# curr_player's possible pawn to move
self.allowed_pawns = []
# curr_player's chosen pawn to move
self.picked_pawn = None
# chosen index from allowed pawn
self.index = None
# jog pawn if any
self.jog_pawns = []
def get_available_colours(self):
'''if has available colour on boards'''
used = [player.colour for player in self.players]
available = set(self.board.COLOUR_ORDER) - set(used)
return sorted(available)
def _get_next_turn(self):
allowed_pawns = []
if rolled_value == Die.MAX:
pawn = self.get_pawn_from_board_pool(player)
if pawn:
allowed_pawns.append(pawn)
for pawn in player.pawns:
if not self.board.is_pawn_on_board_pool(pawn) and\
self.board.can_pawn_move(pawn, rolled_value):
allowed_pawns.append(pawn)
return sorted(allowed_pawns, key=lambda pawn: pawn.index)
def get_board_pic(self):
return self.board.paint_board()
self.jog_pawns = []
self.curr_player = self._get_next_turn()
if rolled_val is None:
self.rolled_value = Die.throw()
else:
self.rolled_value = rolled_val
self.allowed_pawns = self.get_allowed_pawns_to_move(
self.curr_player, self.rolled_value)
if self.allowed_pawns:
if ind is None:
self.index = self.curr_player.choose_pawn(
self.allowed_pawns)
else:
self.index = ind
self.picked_pawn = self.allowed_pawns[self.index]
self._make_move(self.curr_player, self.picked_pawn)
else:
self.index = -1
self.picked_pawn = None
Painter.py
from copy import deepcopy
from os import linesep
CODE_COMMON_SQUARES = [
(), # 0 index not used
(14, 2), (14, 8), (14, 14), (14, 20), (14, 26), (14, 32), (14, 38),
(12, 38), (10, 38), (8, 38), (6, 38), (4, 38), (2, 38), (2, 44),
(2, 50), (4, 50), (6, 50), (8, 50), (10, 50), (12, 50), (14, 50),
(14, 56), (14, 62), (14, 68), (14, 74), (14, 80), (14, 86), (16, 86),
(18, 86), (18, 80), (18, 74), (18, 68), (18, 62), (18, 56), (18, 50),
(20, 50), (22, 50), (24, 50), (26, 50), (28, 50), (30, 50), (30, 44),
(30, 38), (28, 38), (26, 38), (24, 38), (22, 38), (20, 38), (18, 38),
(18, 32), (18, 26), (18, 20), (18, 14), (18, 8), (18, 2), (16, 2)
]
CODE_COLOUR_SQUARES = {
'yellow': [(), (16, 8), (16, 14), (16, 20), (16, 26), (16, 32), (16, 38)],
'blue': [(), (4, 44), (6, 44), (8, 44), (10, 44), (12, 44), (14, 44)],
'red': [(), (16, 80), (16, 74), (16, 68), (16, 62), (16, 56), (16, 50)],
'green': [(), (28, 44), (26, 44), (24, 44), (22, 44), (20, 44), (18, 44)]
}
CODE_POOL_PLACES = {
'yellow': [(), (6, 14), (6, 19), (8, 14), (8, 19)],
'blue': [(), (6, 71), (6, 76), (8, 71), (8, 76)],
'red': [(), (24, 71), (24, 76), (26, 71), (26, 76)],
'green': [(), (24, 14), (24, 19), (26, 14), (26, 19)]
}
class PaintBoard():
def __init__(self):
self.board_tmpl_curr = deepcopy(BOARD_TMPL)
run.py
from ludo.cli import CLIGame
CLIGame().start()
Output :
CONCLUSION