def new_ai(self, diff): # For now, just start an AI game and store it in session, # which is what we'll end up doing for AI games pre-save. # We'll be hitting the database on versus game starts though, # or if the user decides to 'save' an AI game. # Only supporting same-sized edged boards for now board_size = 3 x_pos_bin = '000000000' o_pos_bin = '000000000' x_pos = 0 o_pos = 0 finished = False message = '' # AI difficulty from 0..2, with 0 being least difficult if diff == 'easy': ai_level = 0 elif diff == 'med': ai_level = 1 elif diff == 'hard': ai_level = 2 else: return redirect('/game/new/ai/') # An option to clear the session's game cache for a fresh start if 'reset' in request.POST and request.POST['reset'] == 'true': session.clear() session.save() return redirect('/game/new/ai/') # If there's a POST request or we see session variables from a # previous game, we're already mid-game. # TODO: if move and reset are both in POST, this breaks if ('move' in request.POST) or ('game' in session): board_size = session['size'] x_pos = session['x_pos'] o_pos = session['o_pos'] user_side = session['user_side'] ai_level = session['ai_level'] finished = session['finished'] message = session['message'] x_pos_bin = int_to_bin(x_pos, board_size) o_pos_bin = int_to_bin(o_pos, board_size) if (not finished) and ('move' in request.POST): if is_legal_move(x_pos, o_pos, request.POST['move']): if user_side == 'X': x_pos, x_pos_bin = add_move(x_pos, request.POST['move'], board_size) if game_over(x_pos): finished = True message = 'You win!' else: o_move = ai_move(ai_level, o_pos, x_pos, board_size) o_pos, o_pos_bin = add_move(o_pos, o_move, board_size) if game_over(o_pos): finished = True message = 'You lose!' else: o_pos, o_pos_bin = add_move(o_pos, request.POST['move'], board_size) if game_over(o_pos): finished = True message = 'You win!' else: x_move = ai_move(ai_level, x_pos, o_pos, board_size) x_pos, x_pos_bin = add_move(x_pos, x_move, board_size) if game_over(x_pos): finished = True message = 'You lose!' if not finished and (bit_count(x_pos | o_pos) == board_size**2): finished = True message = 'It\'s a tie!' else: # New games for now randomly pick between you or AI starting coin_toss = randrange(2) # 0: AI goes first, 1: You go first # X is for the player going first if coin_toss == 0: user_side = 'O' # Eventually use ai_move, for now assume always go center x_pos, x_pos_bin = add_move(x_pos, '000010000', board_size) else: user_side = 'X' x_pos = int(x_pos_bin, 2) o_pos = int(o_pos_bin, 2) session['game'] = True session['size'] = board_size session['x_pos'] = x_pos session['o_pos'] = o_pos session['user_side'] = user_side session['ai_level'] = ai_level session['finished'] = finished session['message'] = message session.save() positions = [] for i in range(board_size): positions.append([]) for j in range(board_size): if x_pos_bin[(i*board_size)+j] == '1': positions[i].append('X') elif o_pos_bin[(i*board_size)+j] == '1': positions[i].append('O') else: positions[i].append('') # Absolutely no idea if this is proper or not, but I'd rather # not fish through the entire function for declared context # variables, so I'm going with sticking them all at the end. c.board_size = board_size c.positions = positions c.user_side = user_side c.finished = finished c.message = message c.this_url = request.environ.get('PATH_INFO') if request.is_xhr: return self.json(positions) return render('/game/new.mako')
def cont_game(self, id): # Continue an existing Human Versus game game = self.game_q.filter_by(id=id).first() if not game: return redirect('/') message = '' user_side = '' finished = False board_size = game.size x_pos = game.x_pos o_pos = game.o_pos x_pos_bin = int_to_bin(x_pos, board_size) o_pos_bin = int_to_bin(o_pos, board_size) if 'move' in request.POST: if 'user_side' in session: user_side = session['user_side'] elif user_side == '': # Determine your side by the person whose turn it should be # Note: I have no idea what security issues this raises # should one user maliciously and purposfully clear their # cookies. if bit_count(x_pos) <= bit_count(o_pos): user_side = 'X' else: user_side = 'O' session['user_side'] = user_side session.save() if (not game_over(x_pos)) and (not game_over(o_pos)) and is_legal_move(x_pos, o_pos, request.POST['move'], user_side): if user_side == 'X': x_pos, x_pos_bin = add_move(x_pos, request.POST['move'], board_size) game.x_pos = x_pos Session.commit() else: o_pos, o_pos_bin = add_move(o_pos, request.POST['move'], board_size) game.o_pos = o_pos Session.commit() if game_over(x_pos): finished = True if user_side == 'X': message = 'You win!' elif user_side == 'O': message = 'You lose!' elif game_over(o_pos): finished = True if user_side == 'O': message = 'You win!' elif user_side == 'X': message = 'You lose!' elif bit_count(x_pos | o_pos) == (board_size**2): finished = True message = 'It\'s a tie!' positions = [] for i in range(board_size): positions.append([]) for j in range(board_size): if x_pos_bin[(i*board_size)+j] == '1': positions[i].append('X') elif o_pos_bin[(i*board_size)+j] == '1': positions[i].append('O') else: positions[i].append('') c.board_size = board_size c.positions = positions c.user_side = user_side c.finished = finished c.message = message c.this_url = request.environ.get('PATH_INFO') # c.this_url = url.current(qualified=False) if request.is_xhr: return self.json(positions) return render('/game/continue.mako')