# ----------------------------------------------------------------------------- # # Chain Reaction # Language - Python # Modules - pygame, sys, math # # Controls - Mouse Click # # By - Jatin Kumar Mandav # # Website - https://jatinmandav.wordpress.com # # YouTube Channel - https://www.youtube.com/channel/UCdpf6Lz3V357cIZomPwjuFQ # Twitter - @jatinmandav # # ----------------------------------------------------------------------------- import pygame import sys from math import * # Initialization of Pygame pygame.init() width = 400 height = 400 display = pygame.display.set_mode((width, height)) clock = pygame.time.Clock() # Colors background = (21, 67, 96) border = (208, 211, 212) red = (231, 76, 60) white = (244, 246, 247) violet = (136, 78, 160) yellow = (244, 208, 63) green = (88, 214, 141) playerColor = [red, green, violet, yellow] font = pygame.font.SysFont("Times New Roman", 30) blocks = 40 noPlayers = 4 pygame.display.set_caption("Chain Reaction %d Player" % noPlayers) score = [] for i in range(noPlayers): score.append(0) players = [] for i in range(noPlayers): players.append(playerColor[i]) d = blocks//2 - 2 cols = int(width//blocks) rows = int(height//blocks) grid = [] # Quit or Close the Game Window def close(): pygame.quit() sys.exit() # Class for Each Spot in Grid class Spot(): def __init__(self): self.color = border self.neighbors = [] self.noAtoms = 0 def addNeighbors(self, i, j): if i > 0: self.neighbors.append(grid[i - 1][j]) if i < rows - 1: self.neighbors.append(grid[i + 1][j]) if j < cols - 1: self.neighbors.append(grid[i][j + 1]) if j > 0: self.neighbors.append(grid[i][j - 1]) # Initializing the Grid with "Empty or 0" def initializeGrid(): global grid, score, players score = [] for i in range(noPlayers): score.append(0) players = [] for i in range(noPlayers): players.append(playerColor[i]) grid = [[]for _ in range(cols)] for i in range(cols): for j in range(rows): newObj = Spot() grid[i].append(newObj) for i in range(cols): for j in range(rows): grid[i][j].addNeighbors(i, j) # Draw the Grid in Pygame Window def drawGrid(currentIndex): r = 0 c = 0 for i in range(width//blocks): r += blocks c += blocks pygame.draw.line(display, players[currentIndex], (c, 0), (c, height)) pygame.draw.line(display, players[currentIndex], (0, r), (width, r)) # Draw the Present Situation of Grid def showPresentGrid(vibrate = 1): r = -blocks c = -blocks padding = 2 for i in range(cols): r += blocks c = -blocks for j in range(rows): c += blocks if grid[i][j].noAtoms == 0: grid[i][j].color = border elif grid[i][j].noAtoms == 1: pygame.draw.ellipse(display, grid[i][j].color, (r + blocks/2 - d/2 + vibrate, c + blocks/2 - d/2, d, d)) elif grid[i][j].noAtoms == 2: pygame.draw.ellipse(display, grid[i][j].color, (r + 5, c + blocks/2 - d/2 - vibrate, d, d)) pygame.draw.ellipse(display, grid[i][j].color, (r + d/2 + blocks/2 - d/2 + vibrate, c + blocks/2 - d/2, d, d)) elif grid[i][j].noAtoms == 3: angle = 90 x = r + (d/2)*cos(radians(angle)) + blocks/2 - d/2 y = c + (d/2)*sin(radians(angle)) + blocks/2 - d/2 pygame.draw.ellipse(display, grid[i][j].color, (x - vibrate, y, d, d)) x = r + (d/2)*cos(radians(angle + 90)) + blocks/2 - d/2 y = c + (d/2)*sin(radians(angle + 90)) + 5 pygame.draw.ellipse(display, grid[i][j].color, (x + vibrate, y, d, d)) x = r + (d/2)*cos(radians(angle - 90)) + blocks/2 - d/2 y = c + (d/2)*sin(radians(angle - 90)) + 5 pygame.draw.ellipse(display, grid[i][j].color, (x - vibrate, y, d, d)) pygame.display.update() # Increase the Atom when Clicked def addAtom(i, j, color): grid[i][j].noAtoms += 1 grid[i][j].color = color if grid[i][j].noAtoms >= len(grid[i][j].neighbors): overFlow(grid[i][j], color) # Split the Atom when it Increases the "LIMIT" def overFlow(cell, color): showPresentGrid() cell.noAtoms = 0 for m in range(len(cell.neighbors)): cell.neighbors[m].noAtoms += 1 cell.neighbors[m].color = color if cell.neighbors[m].noAtoms >= len(cell.neighbors[m].neighbors): overFlow(cell.neighbors[m], color) # Checking if Any Player has WON! def isPlayerInGame(): global score playerScore = [] for i in range(noPlayers): playerScore.append(0) for i in range(cols): for j in range(rows): for k in range(noPlayers): if grid[i][j].color == players[k]: playerScore[k] += grid[i][j].noAtoms score = playerScore[:] # GAME OVER def gameOver(playerIndex): while True: for event in pygame.event.get(): if event.type == pygame.QUIT: close() if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: close() if event.key == pygame.K_r: gameLoop() text = font.render("Player %d Won!" % (playerIndex + 1), True, white) text2 = font.render("Press \'r\' to Reset!", True, white) display.blit(text, (width/3, height/3)) display.blit(text2, (width/3, height/2 )) pygame.display.update() clock.tick(60) def checkWon(): num = 0 for i in range(noPlayers): if score[i] == 0: num += 1 if num == noPlayers - 1: for i in range(noPlayers): if score[i]: return i return 9999 # Main Loop def gameLoop(): initializeGrid() loop = True turns = 0 currentPlayer = 0 vibrate = .5 while loop: for event in pygame.event.get(): if event.type == pygame.QUIT: close() if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: close() if event.type == pygame.MOUSEBUTTONDOWN: x, y = pygame.mouse.get_pos() i = x/blocks j = y/blocks if grid[i][j].color == players[currentPlayer] or grid[i][j].color == border: turns += 1 addAtom(i, j, players[currentPlayer]) currentPlayer += 1 if currentPlayer >= noPlayers: currentPlayer = 0 if turns >= noPlayers: isPlayerInGame() display.fill(background) # Vibrate the Atoms in their Cells vibrate *= -1 drawGrid(currentPlayer) showPresentGrid(vibrate) pygame.display.update() res = checkWon() if res < 9999: gameOver(res) clock.tick(20) gameLoop()