def setUp(self): self.char1 = Character({'max_hp': 18, 'type': CharType.main, 'side': SqState.light, 'pos': Pos(0, 0)}) self.char2 = Character({'max_hp': 19, 'type': CharType.main, 'side': SqState.dark, 'pos': Pos(6, 6)}) self.pos = Pos(5, 6) self.b1 = Board({}) self.b2 = Board({'name': 'ruins', 'board_type': BoardType.dais})
def __init__(self, kwargs): """Initializer for Engine""" self.num_players = kwargs.get('num_players', 0) self.turn = kwargs.get('turn', 0) self.round_num = kwargs.get('round', 0) self.phase = kwargs.get('phase', None) self.active_action = kwargs.get('action', None) self.active_char = kwargs.get('active_char', None) self.target_char = kwargs.get('target_char', None) self.target_squad = kwargs.get('target_squad', None) self.active_card = kwargs.get('active_card', None) self.def_card = kwargs.get('def_card', None) self.board = Board({'board_type': kwargs.get('board_type', None)}) self.squads = kwargs.get('squads') self.num_squads = kwargs.get('num_squads', 0) self.dice = Dice()
class TestBoard(unittest.TestCase): def setUp(self): self.char1 = Character({'max_hp': 18, 'type': CharType.main, 'side': SqState.light, 'pos': Pos(0, 0)}) self.char2 = Character({'max_hp': 19, 'type': CharType.main, 'side': SqState.dark, 'pos': Pos(6, 6)}) self.pos = Pos(5, 6) self.b1 = Board({}) self.b2 = Board({'name': 'ruins', 'board_type': BoardType.dais}) # ############################# __str__ ################################# def test_string_method(self): self.b2.set_sqr_state(Pos(0, 0), SqState.light) self.b2.set_sqr_state(Pos(0, 1), SqState.dark) self.assertEqual(self.b2.__str__(), 'BoardType.dais\n' ' 0123456789\n' '--------------\n' '0 | LOOOOOEEEE\n' '1 | DOEEEEEHEH\n' '2 | EEEEEEHHEH\n' '3 | EEEEEEEEEE\n' '4 | EEEEEEHHEH\n' '5 | OOEEEEEHEH\n' '6 | OOOOOOEEEE\n') # ######################## square_state ################################## def test_square_state_board_empty_true(self): self.assertEqual(self.b1.get_sqr_state(self.pos), SqState.empty) def test_square_state_board_empty_false(self): self.assertNotEqual(self.b1.get_sqr_state(self.pos), SqState.light) # ######################## is_diagonal #################################### def test_if_square_is_diagonal_true(self): self.assertTrue((self.char1.pos, self.char2.pos)) def test_if_square_is_diagonal_false(self): self.char2.pos = self.pos self.assertFalse(self.char1.pos.is_diagonal(self.char2.pos)) # ######################## is_parallel #################################### def test_if_squares_are_parallel_false(self): self.assertFalse(self.char1.pos.is_parallel(self.char2.pos)) def test_if_squares_are_parallel_true(self): self.char2.pos = Pos(0, 6) self.assertTrue(self.char1.pos.is_parallel(self.char2.pos)) # ####################### is_adj #################################### def test_if_squares_are_adj_false(self): self.assertFalse(self.char1.pos.is_adj(self.char2.pos)) def test_if_squares_are_adj_true(self): self.char2.pos = Pos(0, 1) self.assertTrue(self.char1.pos.is_adj(self.char2.pos)) # ######################## is_parallel_clear ############################## def test_if_parallel_squares_clear_false_not_parallel(self): self.assertFalse(self.b1.is_parallel_clr(self.char1.pos, self.char2.pos)) def test_parallel_squares_clear_on_x_axis_orig_lt_target_true(self): self.assertTrue(self.b1.is_parallel_clr(Pos(2, 2), Pos(2, 5))) def test_parallel_squares_clear_on_x_axis_orig_gt_target_true(self): self.assertTrue(self.b1.is_parallel_clr(Pos(2, 5), Pos(2, 2))) def test_parallel_squares_clear_on_x_axis_target_lt_orig_true(self): self.assertTrue(self.b1.is_parallel_clr(Pos(2, 2), Pos(2, 5))) def test_parallel_squares_clear_on_x_axis_target_gt_orig_true(self): self.assertTrue(self.b1.is_parallel_clr(Pos(2, 2), Pos(5, 2))) def test_parallel_squares_clear_on_x_axis_adj_true(self): self.assertTrue(self.b1.is_parallel_clr(Pos(2, 2), Pos(2, 3))) def test_parallel_squares_clear_on_y_axis_orig_gt_target_true(self): self.assertTrue(self.b1.is_parallel_clr(Pos(5, 2), Pos(2, 2))) def test_parallel_squares_are_clear_on_x_plane_adj_false(self): self.b1.board[0][3]['state'] = SqState.obstacle self.assertFalse(self.b1.is_parallel_clr(Pos(0, 0), Pos(0, 6))) def test_parallel_squares_are_clear_on_y_plane_adj_false(self): self.b1.board[3][0]['state'] = SqState.obstacle self.assertFalse(self.b1.is_parallel_clr(Pos(0, 0), Pos(6, 0))) # ######################## is_diagonal_clear ############################## def test_board_is_diagonal_clear_true(self): self.assertTrue(self.b1.is_diagonal_clr(Pos(1, 3), Pos(4, 0))) def test_board_is_diagonal_clear_true_inverse(self): self.assertTrue(self.b1.is_diagonal_clr(Pos(1, 3), Pos(4, 0))) def test_board_is_diagonal_clear_false(self): self.b1.board[2][2]['state'] = SqState.dark self.assertFalse(self.b1.is_diagonal_clr(Pos(1, 3), Pos(4, 0))) # ####################### is_obstructed ############################## def test_is_obstructed_surrounded_true(self): self.char1.pos = Pos(3, 5) self.b1.board[3][6]['state'] = SqState.dark self.b1.board[4][5]['state'] = SqState.dark self.b1.board[2][5]['state'] = SqState.dark self.b1.board[3][4]['state'] = SqState.dark self.assertTrue(self.b1.is_obstructed(self.char1)) def test_is_obstructed_obstacles_true(self): self.char1.pos = Pos(3, 5) self.b1.board[3][6]['state'] = SqState.obstacle self.b1.board[4][5]['state'] = SqState.obstacle self.b1.board[2][5]['state'] = SqState.obstacle self.b1.board[3][4]['state'] = SqState.obstacle self.assertTrue(self.b1.is_obstructed(self.char1)) def test_is_obstructed_false_one_friendly(self): self.char1.pos = Pos(3, 5) self.b1.board[3][6]['state'] = SqState.light self.b1.board[4][5]['state'] = SqState.dark self.b1.board[2][5]['state'] = SqState.dark self.b1.board[3][4]['state'] = SqState.dark self.assertFalse(self.b1.is_obstructed(self.char1)) def test_is_obstructed_false_one_empty(self): self.char1.pos = Pos(3, 5) self.b1.board[3][6]['state'] = SqState.dark self.b1.board[4][5]['state'] = SqState.dark self.b1.board[2][5]['state'] = SqState.dark self.b1.board[3][4]['state'] = SqState.empty self.assertFalse(self.b1.is_obstructed(self.char1)) # ######################## is_out_of_bounds ############################## def test_is_out_of_bounds_true_x(self): self.assertTrue(self.b1.out_of_bounds(Pos(10, 6))) def test_is_out_of_bounds_true_y(self): self.assertTrue(self.b1.out_of_bounds(Pos(7, 9))) def test_is_out_of_bounds_false(self): self.assertFalse(self.b1.out_of_bounds(Pos(9, 6))) # ######################## can_move_through ############################## def test_can_move_through_true_empty(self): self.b1.board[3][5]['state'] = SqState.empty self.assertTrue(self.b1.can_move_through(self.char1, Pos(3, 5))) def test_can_move_through_true_ally(self): self.b1.board[3][5]['state'] = SqState.light self.assertTrue(self.b1.can_move_through(SqState.light, Pos(3, 5))) def test_can_move_through_false_enemy(self): self.b1.board[3][5]['state'] = SqState.dark self.assertFalse(self.b1.can_move_through(self.char1, Pos(3, 5))) def test_can_move_through_false_hole(self): self.b1.board[3][5]['state'] = SqState.hole self.assertFalse(self.b1.can_move_through(self.char1, Pos(3, 5))) def test_can_move_through_false_obstacle(self): self.b1.board[3][5]['state'] = SqState.obstacle self.assertFalse(self.b1.can_move_through(self.char1, Pos(3, 5))) # ######################## is_valid_move ############################## # already covered out_of_bounds and can_move_through methods # ######################## can_target ############################## def test_can_target_attack_ally_adj(self): self.char2.pos = Pos(0, 1) self.assertTrue(self.b1.can_target(self.char1, self.char2)) def test_can_target_attack_false(self): self.char1.is_range = False self.assertFalse(self.b1.can_target(self.char1, self.char2)) def test_can_target_attack_true(self): self.char1.is_range = True self.assertTrue(self.b1.can_target(self.char1, self.char2)) # ######################## find_moves ############################## def test_find_moves_roll_1_true(self): self.char1.pos = Pos(3, 4) self.assertEqual(len(self.b1.find_moves(self.char1, 1)), 5) def test_find_moves_roll_2_true(self): self.char1.pos = Pos(3, 4) self.assertEqual(len(self.b1.find_moves(self.char1, 2)), 13) def test_find_moves_roll_3_true(self): self.char1.pos = Pos(3, 4) self.assertEqual(len(self.b1.find_moves(self.char1, 3)), 24) def test_find_moves_roll_4_true(self): self.char1.pos = Pos(3, 4) self.assertEqual(len(self.b1.find_moves(self.char1, 4)), 36) def test_find_moves_roll_5_true(self): self.char1.pos = Pos(3, 4) self.assertEqual(len(self.b1.find_moves(self.char1, 5)), 47) # ######################## get_adj_empty ############################## def test_get_adj_empty_pos_out_of_bounds(self): self.assertEqual(self.b1.get_adj_empty_pos(Pos(-1, -1)), []) def test_get_adj_empty_pos_none(self): self.b1.board[4][3]['state'] = SqState.light self.b1.board[4][5]['state'] = SqState.light self.b1.board[3][4]['state'] = SqState.light self.b1.board[5][4]['state'] = SqState.light self.b1.board[3][3]['state'] = SqState.light self.b1.board[3][5]['state'] = SqState.light self.b1.board[5][3]['state'] = SqState.light self.b1.board[5][5]['state'] = SqState.light self.assertEqual(self.b1.get_adj_empty_pos(Pos(4, 4)), []) def test_get_adj_empty_pos_4(self): self.b1.board[3][3]['state'] = SqState.light self.b1.board[3][5]['state'] = SqState.light self.b1.board[5][3]['state'] = SqState.light self.b1.board[5][5]['state'] = SqState.light self.assertEqual(self.b1.get_adj_empty_pos(Pos(4, 4)), [Pos(4, 3), Pos(4, 5), Pos(3, 4), Pos(5, 4)]) # ######################## get_adj_empty ############################## def test_print_board_state(self): self.b2.set_sqr_state(Pos(0, 0), SqState.light) self.b2.set_sqr_state(Pos(0, 1), SqState.dark) self.assertEqual( self.b2.print_board_coordinates(), 'BoardType.dais\n' ' 0 1 2 3 4 5 6 7 8 9 \n' '------------------------------------------------------\n' '0 | (0,0)(1,0)(2,0)(3,0)(4,0)(5,0)(6,0)(7,0)(8,0)(9,0)\n' '1 | (0,1)(1,1)(2,1)(3,1)(4,1)(5,1)(6,1)(7,1)(8,1)(9,1)\n' '2 | (0,2)(1,2)(2,2)(3,2)(4,2)(5,2)(6,2)(7,2)(8,2)(9,2)\n' '3 | (0,3)(1,3)(2,3)(3,3)(4,3)(5,3)(6,3)(7,3)(8,3)(9,3)\n' '4 | (0,4)(1,4)(2,4)(3,4)(4,4)(5,4)(6,4)(7,4)(8,4)(9,4)\n' '5 | (0,5)(1,5)(2,5)(3,5)(4,5)(5,5)(6,5)(7,5)(8,5)(9,5)\n' '6 | (0,6)(1,6)(2,6)(3,6)(4,6)(5,6)(6,6)(7,6)(8,6)(9,6)\n')
class Engine(object): def __init__(self, kwargs): """Initializer for Engine""" self.num_players = kwargs.get('num_players', 0) self.turn = kwargs.get('turn', 0) self.round_num = kwargs.get('round', 0) self.phase = kwargs.get('phase', None) self.active_action = kwargs.get('action', None) self.active_char = kwargs.get('active_char', None) self.target_char = kwargs.get('target_char', None) self.target_squad = kwargs.get('target_squad', None) self.active_card = kwargs.get('active_card', None) self.def_card = kwargs.get('def_card', None) self.board = Board({'board_type': kwargs.get('board_type', None)}) self.squads = kwargs.get('squads') self.num_squads = kwargs.get('num_squads', 0) self.dice = Dice() def __repr__(self): return 'Num Players:{0}\tRound: {1}\tTurn: {2}\tDice: {3}' \ '\tSquads: {4}\n{5}'.format(self.num_players, self.round_num, self.turn, self.dice, self.squads, self.board) ########################################################################## ###################################################### def active_squad(self): return self.squads[self.turn] def target_squad(self): return self.squads[self.target_squad] ########################################################################## # ###################### Board Init functions ############################ ########################################################################## def shuffle_all_decks(self): for squad in self.squads: squad.deck_shuffle() def randomly_place_minor_characters(self): # place secondary characters for squad in self.squads: pos = self.find_minor_placement(squad) # print(pos) shuffle(pos) # hard coding the first two positions for the minor chars self.move_char(squad.chars['minor1'], pos[0]) self.move_char(squad.chars['minor2'], pos[1]) ########################################################################## # Game Rules ########################################################################## def is_game_over(self): """returns true if all main dark or light side characters are dead""" return (sum(squad.chars['main'].hp for squad in self.squads if squad.side == Sqr.light) == 0) or \ (sum(squad.chars['main'].hp for squad in self.squads if squad.side == Sqr.dark) == 0) # TODO : decrement number of squads as they are defeated def can_attack(self, char, target): """verify if legal target""" if not char.is_range and not char.is_adj(target): return False return char.side != target.side # def can_melee_attack(self, char): # """verify if target can be melee attacked""" # return self.active_char().is_legal_target(char) and self.is_adj(char) ########################################################################### # Movement and Placement ########################################################################### def move_char(self, char, pos): self.board.board[pos.x][pos.y]['state'] = char.side if char.pos is not None: self.board.make_empty(char.pos) char.pos = pos logging.info("{0} moved to {1}".format(char.name, pos)) def remove_char(self, char): if char.pos: self.board.make_empty(char.pos) char.pos = None logging.info("{0} removed from the board".format(char.name)) def find_squad_moves(self, active_chars): """returns dictionary of active characters in a squad and all their possible moves based on the current dice state """ squad_moves = {} for key in active_chars: squad_moves[key] = self.get_possible_moves( self.active_squad().chars[key]) return squad_moves def move_squad(self, squad_pos, squad_num=None): """takes in dictionary of squad moves {'main': Pos, """ # get list of active characters to know how many loops to iterate if squad_num: squad = self.squads[squad_num] else: squad = self.active_squad() for k, char in squad.chars.items(): self.move_char(char, squad_pos[k]) # def _place_minor_random(self): # """Places minor characters randomly if no pos supplied""" # for squad in self.squads: # list_pos = self.board.get_adj_empty_pos(squad.chars['main'].pos) # self.move_char(squad.chars['minor1'], # list_pos.pop(randrange(0, len(list_pos)))) # if squad.chars['minor2']: # self.move_char(squad.chars['minor2'], # list_pos.pop(randrange(0, len(list_pos)))) def initial_placement(self): board = self.board.type for squad in self.squads: pos = squad.chars['main'].init_pos[board] self.move_char(squad.chars['main'], pos) def find_minor_placement(self, squad): return self.board.get_adj_empty_pos(squad.chars['main'].pos) ########################################################################### # Discovery Methods ########################################################################### def get_possible_moves(self, char=None, moves=None): if char is None: char = self.active_char if moves is None: moves = self.dice.num() return self.board.find_moves(char, moves) def get_possible_actions(self): """get dictionary of all available actions""" # No actions available possible_actions = [] # Squad related actions if not self.active_squad().can_act(): return possible_actions if self.active_squad().can_draw: possible_actions.append(Act.draw) if self.active_squad().can_heal_main(): possible_actions.append(Act.heal_main) # todo: don't need this, but might be useful for custom decks # if self.active_squad().can_heal_minor(): # possible_actions.append(Act.heal_minor) # Card related Actions if self.active_squad().has_hand(): # get possible attack targets squad_targets = self.get_squad_targets() for index, card in enumerate(self.active_squad().hand): # attack cards with or without special abilities if card.is_atk(): squad_targets[card.owner]['cards']['attack'] = card # possible_actions.append(index) # special abilities if card.is_special(): squad_targets[card.owner]['cards']['special'] = card return possible_actions # TODO: Clean this up # def get_list_of_char_card_actions(self): # active_chars = self.active_squad().get_active_chars() # ######################### Targeting Methods ############################ def get_squad_targets(self): """ Get dictionary of lists for all possible targets {char_key: char_object}""" active_chars = self.active_squad().get_active_chars() squad_targets = {} for char_key in active_chars: # char = self.active_squad().chars[char_key] squad_targets[char_key]['targets'] = self.get_char_targets( self.active_squad().chars[char_key]) return squad_targets def get_char_targets(self, char): """ Get list of all possible target characters for a single character """ return [target for squad in self.squads if squad.side != char.side for k, target in squad.chars.items() if target.is_alive() and self.board.can_target(char, target)] def get_adj_chars(self, char=None): """return list of adj characters. assumes active char unless set""" if char: origin = char else: origin = self.active_char return [char for squad in self.squads for k, char in squad.chars.items() if char.is_alive() and origin.pos.is_adj(char.pos)] def get_adj_allies_enemies(self, char=None): """return list of adj friendly characters""" allies = [] enemies = [] if char: origin = char else: origin = self.active_char for squad in self.squads: for k, char in squad.chars.items(): if char.is_alive() and origin.pos.is_adj(char.pos): if not origin.is_enemy(char): allies.append(char) else: enemies.append(char) return allies, enemies def get_minor_enemy_chars(self, char=None): enemies = [] if char: active_char = char else: active_char = self.active_char for squad in self.squads: if squad.side != active_char.side: enemies.append(squad.get_minor_chars()) return enemies ########################################################################## # Action Methods ########################################################################## # TODO: Clean this up # def play_card(self): # card = self.active_squad().active_card # if card.self.ack: # def_card = self.target_squad().active_card # # resolve cards # else: # for effects in card.effects: # # play effects # effects['effect_type']() def combat(self): pass ########################################################################### # Card Effects ########################################################################### def damage_adj_chars(self, points, char=None): chars = self.get_adj_chars(char) for char in chars: char.damage(points) def damage_char(self, points=1): """Throw Debris""" self.target_char.damage(points) def deal_cards_to_squads(self, num_cards=4): """ Deals out hand to each squad Hand defaults to initial 4""" for squad in self.squads: squad.draw_card(num_cards) def draw(self, num): """Jedi block, martial defense, serenity, missile launch, taunt, masterful fighting, force strike, deadly aim, bowcaster attack, Latent Force Ability, gain power""" self.active_squad().draw_card(num) def reveal_discard_attack_cards(self, squad_num): """I will not fight you""" self.active_squad().discard_attack_cards() self.squads[squad_num].discard_attack_cards() def reveal_target_hand(self, squad_num): """""" # TODO: FIX THIS return self.squads[squad_num].hand def reveal_target_hand_discard_card(self, squad_num, card_indices): """Insight""" self.reveal_target_hand(squad_num) self.target_discard(squad_num, card_indices) def damage_minor_enemy(self, points, char=None): """Choke""" if char: char.damage(points) else: self.target_char.damage(points) def damage_and_discard_random(self, points, squad_num, num_cards): """Force Lightning""" self.damage_char(points) self.target_discard_random(squad_num, num_cards) def damage_char_and_adj_chars(self, points=1): """Thermal Detonator""" self.target_char.damage(points) self.damage_adj_chars(points, self.target_char) def switch_main_and_minor_pos(self, char): """Royal Command""" self.active_char.switch_pos(char) def heal_main_if_adjacent_alive_or_heal_minor(self, points): # """Luke's in trouble""" pass def heal_more_if_main_alive(self, alive_pts, dead_pts): """Protection""" if self.active_squad().is_main_dead(): self.active_char.heal(dead_pts) else: self.active_char.heal(alive_pts) def damage_legal_targets_shuffle_discard_into_deck(self, points): """Never Tell Me The Odds""" self.damage_legal_targets(points) self.active_squad().shuffle_discard_into_deck() def heal_target_squad_cannot_draw_next_turn(self, points): """Meditation""" self.heal(points) self.squad_cannot_draw_next_turn() def squad_cannot_draw_next_turn(self): pass # def damage_adj_enemies(self, points): # allies, enemies = self.get_adj_allies_enemies(self.active_char) # self._damage_chars(points, enemies) def not_action(self): """Sith speed, super sith speed""" self.active_squad().actions += 1 def lose_action(self, squad_num): """""" self.squads[squad_num] -= 1 def heal(self, points=None): self.active_char().heal(points) def heal_and_move(self, points, moves): """Wookie Healing""" self.heal(points) self.move(moves) def move_and_damage_target_char(self, pos, points): """Its not wise""" self.move_char(self.target_char, pos) self.target_char.damage(points) # def move_and_damage_adj_chars(self, points): # """Flame Thrower""" # # TODO: FIX # chars = self.get_adj_chars(self.active_char) # # for char in chars: # # self.move_character(char) # # char.damage(points) def move_and_draw(self, moves, num_cards): """wisdom, force quickness""" self.move(moves) self.draw(num_cards) def counter(self, points): """Counter attack, blinding surge, force rebound""" self.active_char().damage(points) def move(self, num_moves): """Shot on the run, Heroic Retreat, Jedi Attack, Athletic Surge""" self.board.find_moves(self.active_char, num_moves) def move_squad_draw(self, num_moves, num_cards): """Children of the force""" self.move_squad(num_moves) self.draw(num_cards) def move_no_hand_draw_new_hand(self, num_moves, num_cards): """Calm""" self.move(num_moves) self.no_hand_draw(num_cards) def no_hand_draw(self, num_cards): if not self.active_squad().has_hand(): self.draw(num_cards) def discard_to_draw(self): """precise shot""" self.active_squad().discard_to_draw() def target_dies_draw(self, cards): """kyber dart""" if self.target_char.hp == 0: self.draw(cards) def minor_dead_more_damage(self): """Justice""" if self.active_squad().can_heal_main(): pass def damage_char_squad_loses_action(self, points, action): """wrist cable""" self.target_char.damage(points) # TODO: FIX THIS self.lose_action(action) def damage_squad(self, points): """wrath_vader""" self.target_squad.damage(points) def damage_legal_targets(self, points): """Never tell me the odds, whirlwind""" targets = self.get_char_targets(self.active_char) for target in targets: target.damage(points) def target_discard(self, squad_num, card_indices): """Let Go of your Hatred""" self.squads[squad_num].discard_cards(card_indices=card_indices) def target_discard_random(self, squad_num, num_cards): """Force Drain""" self.squads[squad_num].discard_cards(num_cards=num_cards) def damage_legal_target_discard_random(self, squad_num, num_cards): """Gambler's luck""" self.target_discard_random(squad_num, num_cards) def move_all(self, moves): # force control pass def lift_char(self): # Force Lift pass def drop_char(self): pass def reorder_cards_draw(self, card_indices, num_draw): """Future Foreseen""" self.reorder_cards(card_indices) self.draw(num_draw) def preview_deck(self, depth): self.active_squad().deck_preview(depth) def reorder_cards(self, card_indices): self.active_squad().deck_reorder(card_indices) def kill_or_die(self): """Desperate Shot""" if self.target_char.hp != 0: self.active_char().kill() def hand_size_to_one(self, card_index): """anger""" self.active_squad().hand_size_to_one(card_index) def drain_hp(self, points): # """dark side drain""" pass def hand_size_combat_modifier(self): # """battlemind""" pass def get_card_from_deck(self, card_type): """Wookie instincts""" self.active_squad().get_card_from_deck(card_type) self.active_squad().shuffle() def get_card_from_discard(self, card_type): """jedi mind trick""" self.active_squad().get_card_from_discard(card_type) def squad_discard_hand(self, squad_num): """You Will Die""" self.squads[squad_num].discard_hand() def all_squads_discard_hand(self): for squad in self.squads: squad.discard_hand() def squads_discard_redraw(self, num_cards): """Force Balance""" for squad in self.squads: squad.discard_hand() squad.draw_card(num_cards) def target_squad_reveal_hand(self): # TODO: Not sure on exposure pass def target_squad_discard_special(self): """Your Skills Are Not Complete""" self.target_squad_reveal_hand() pass def teleport(self, pos, char=None): """rocket retreat, assassination""" if char: self.move_char(char, pos) else: self.move_char(self.active_char, pos) def teleport_damage_damage(self, pos, points): """Force Push""" self.teleport(pos, self.target_char) self.target_char.damage(points) def teleport_adj_to_enemy(self): pass def teleport_not_action(self, pos, char=None): """Fire up the jet pack""" self.teleport(pos, char) self.not_action() def teleport_to_minor_damage(self, points): """wrath_anakin""" self.teleport_adj_to_enemy() self.target_char.damage(points) def teleport_to_target_not_action(self): """sudden arrival""" self.teleport_adj_to_enemy() self.not_action() def undefended_attack(self): """all to easy, sniper shot""" self.active_squad() pass