PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates object-oriented design, stateful simulation, and event-logging competency for modeling turn-based combat mechanics, including active-entity selection, damage resolution, death and replacement, and simultaneous-death draw conditions.

  • medium
  • OpenAI
  • Coding & Algorithms
  • Software Engineer

Simulate turn-based monster team battle

Company: OpenAI

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

Design an object-oriented model and implement the core battle logic for a turn-based fight between two teams of monsters. The system should simulate the battle and produce a detailed, chronological battle log, as well as the final result. --- ## Game Setup There are two teams: **Team A** and **Team B**. Each team has an **ordered list of monsters**. Each **Monster** has the following attributes: - `name`: string - `health`: positive integer (HP) - `attack`: positive integer (attack power) The battle continues until at least one team has no living monsters. --- ## Active Monster Rules For each team, the **active monster** is defined as: - The first monster in that team's list whose `health > 0`. - If a team has no monsters with `health > 0`, that team immediately loses (unless this happens to both teams in the same round, see draw rule below). --- ## Round and Attack Rules The battle proceeds in **rounds**. Each round follows this exact sequence: 1. Determine the active monster for Team A and Team B as described above. 2. **Team A's active monster attacks Team B's active monster.** - Damage calculation: `defender.health -= attacker.attack`. - If the defender's health becomes `<= 0`, that monster dies. 3. **If Team B's active monster is still alive after step 2**, it immediately counterattacks: - Team B's active monster attacks Team A's active monster using the same damage rule: `defender.health -= attacker.attack`. - If the defender's health becomes `<= 0`, that monster dies. 4. The round ends, and the next round begins with newly determined active monsters based on the updated health values. **Death and replacement:** - When a monster's `health <= 0`, it is considered dead and removed from battle. - On the **next round**, the next monster in that team's list with `health > 0` becomes the new active monster (if any). --- ## Win / Draw Conditions - **Win:** - If, after processing the attacks in a round, one team has **no living monsters** and the other team still has at least one living monster, the surviving team wins. - **Draw:** - If the last remaining monsters of both teams die **in the same round** (for example, Team A's monster kills Team B's monster, but Team B's monster's counterattack in the same round kills Team A's monster as well), the result is a draw. --- ## Logging Requirements You must generate a **battle log** in strict chronological order. The log should include at least: 1. **Each attack event**, with: - Attacker name and team. - Defender name and team. - Damage dealt (equal to attacker's `attack`). - Defender HP change: `HP_before -> HP_after`. 2. **Each death event**, including: - Which monster died (name, team). - If a new monster becomes active for that team in the **next round**, log which monster is coming in as the replacement. 3. **Final result**, as one of the strings: - `"Team A wins"` - `"Team B wins"` - `"Draw"` You may choose the exact log format (e.g., a list of strings or structured records), but it must be sufficient to reconstruct the full sequence of events. --- ## Implementation / OOD Requirements Use good object-oriented design. Do **not** put all logic into a single class or function. At minimum, design the following classes (you may add more helper classes if needed): - `Monster` - Holds `name`, `health`, `attack` and exposes any behavior needed (e.g., takeDamage, isAlive). - `Team` - Holds an ordered collection of `Monster` instances. - Provides methods to get the current active monster and to determine if the team is defeated. - `BattleEngine` - Orchestrates the battle rounds between two `Team` instances. - Runs the main battle loop according to the rules above. - Generates the chronological battle log. - Determines the final result. - `BattleResult` - Contains at least: - `winner`: one of `"Team A"`, `"Team B"`, or `"Draw"`. - `log`: the ordered battle log. **Task:** Design and implement these classes and the core battle logic so that, given two teams of monsters as input, you can run the battle with `BattleEngine` and obtain a `BattleResult` containing the winner and the full battle log.

Quick Answer: This question evaluates object-oriented design, stateful simulation, and event-logging competency for modeling turn-based combat mechanics, including active-entity selection, damage resolution, death and replacement, and simultaneous-death draw conditions.

Implement the core battle engine for a **turn-based monster team fight** between **Team A** and **Team B**, and produce a detailed, time-ordered battle log. ## Function ```python def solution(team_a, team_b): ... ``` - `team_a` and `team_b` are **ordered lists of monsters**. Each monster is a tuple `(name, hp, atk)`: - `name` — non-empty string - `hp` — integer health - `atk` — integer attack power - Return a **dict** of the form `{'winner': <result string>, 'log': [<line>, ...]}`, where `'log'` is the list of battle-log lines in the exact order they occur, and `'winner'` is the result string (see **Result** below). ## Active monster - A team's **Active Monster** is the **first monster in its list with HP > 0**. Monsters are used strictly in list order; once a monster dies it is never revisited. - A team with no living monster has no Active Monster. ## Round flow (fixed order) The battle proceeds in numbered rounds starting at **Round 1**. In each round, using each team's Active Monster: 1. **Team A's Active Monster attacks Team B's Active Monster.** 2. **Team B's Active Monster counterattacks Team A's Active Monster.** 3. Deaths and replacements are resolved, then the next round begins. **Damage:** when X attacks Y, `Y.hp -= X.atk`. ## Dying strike (important) - The **counterattack always happens** if Team B's monster was alive at the start of the round — **even if Team A's attack already reduced it to HP ≤ 0**. This is a **dying strike**. - Resolution of deaths is deferred: a monster whose HP drops to **≤ 0** during the round is only **removed after both the attack and the counterattack have been logged**. ## Replacement When the Active Monster of a team dies, it is removed and the **next living monster (if any)** in that team's list becomes Active for the following round. ## Logging (exact text and order) Use these exact line formats. `before`/`after` are the defender's HP immediately before and after the hit (`after` may be ≤ 0): - **Attack:** `Round {n}: {attacker} (Team A) attacks {defender} (Team B) for {atk} damage ({before}->{after})` - **Counterattack:** `Round {n}: {attacker} (Team B) counterattacks {defender} (Team A) for {atk} damage ({before}->{after})` Append ` [dying strike]` to this line when Team A's attack this round already brought Team B's defender to HP ≤ 0. - **Death:** `{name} (Team X) dies` - **Replacement:** `Team X sends out {name}` — logged only when a next living monster exists. - **Result (always the last line):** `Result: Team A wins` / `Result: Team B wins` / `Result: Draw`. **Within a round, resolve and log Team B's death/replacement first, then Team A's** (matching the A-attacks-then-B-counterattacks order). ## Empty teams at the start Before Round 1, if a team has no living monster, log it and end immediately: - Both teams empty → log `Team A has no alive monsters.`, then `Team B has no alive monsters.`, then `Result: Draw`. - Only Team A empty → log `Team A has no alive monsters.`, then `Result: Team B wins`. - Only Team B empty → log `Team B has no alive monsters.`, then `Result: Team A wins`. (These `... has no alive monsters.` lines are only emitted for an already-empty team at the start of the battle, not for teams that are wiped out mid-battle.) ## Result After each round's deaths are resolved, check end conditions: - **Team A wins** if Team B has no living monster left. - **Team B wins** if Team A has no living monster left. - **Draw** if **both** teams have no living monster after the same round. The `'winner'` value in the returned dict is the result phrase: `"Team A wins"`, `"Team B wins"`, or `"Draw"`. ## Design requirement Keep the engine reasonably object-oriented: define **Monster**, **Team**, and **BattleEngine** (they may be nested inside `solution`). Return the result as a dict containing the winner and the full log. ## Constraints - `0 <= len(team_a), len(team_b) <= 50` - Monster `name` is a non-empty string. - `1 <= hp <= 10^4` - `1 <= atk <= 10^4` - The total number of rounds (and thus the log) is small enough to materialize in memory for the given tests.

Constraints

  • 0 <= len(team_a), len(team_b) <= 50
  • Monster name is non-empty string
  • 1 <= health <= 10^4
  • 1 <= attack <= 10^4
  • Total number of rounds (and thus log size) will be small enough to fit in memory for the given tests (this problem requires generating the full log).

Examples

Input: ([('A1', 10, 4)], [('B1', 9, 3)])

Expected Output: {'winner': 'Team A wins', 'log': ['Round 1: A1 (Team A) attacks B1 (Team B) for 4 damage (9->5)', 'Round 1: B1 (Team B) counterattacks A1 (Team A) for 3 damage (10->7)', 'Round 2: A1 (Team A) attacks B1 (Team B) for 4 damage (5->1)', 'Round 2: B1 (Team B) counterattacks A1 (Team A) for 3 damage (7->4)', 'Round 3: A1 (Team A) attacks B1 (Team B) for 4 damage (1->-3)', 'Round 3: B1 (Team B) counterattacks A1 (Team A) for 3 damage (4->1) [dying strike]', 'B1 (Team B) dies', 'Result: Team A wins']}

Explanation: B1 can still counterattack as a dying strike in round 3, but then dies. Team B has no monsters left, so Team A wins.

Input: ([('A', 5, 5)], [('B', 5, 5)])

Expected Output: {'winner': 'Draw', 'log': ['Round 1: A (Team A) attacks B (Team B) for 5 damage (5->0)', 'Round 1: B (Team B) counterattacks A (Team A) for 5 damage (5->0) [dying strike]', 'B (Team B) dies', 'A (Team A) dies', 'Result: Draw']}

Explanation: Both last monsters reach HP <= 0 within the same round (B’s counterattack is a dying strike), so the result is Draw.

Input: ([('A1', 6, 4), ('A2', 8, 2)], [('B1', 5, 3), ('B2', 7, 5)])

Expected Output: {'winner': 'Team B wins', 'log': ['Round 1: A1 (Team A) attacks B1 (Team B) for 4 damage (5->1)', 'Round 1: B1 (Team B) counterattacks A1 (Team A) for 3 damage (6->3)', 'Round 2: A1 (Team A) attacks B1 (Team B) for 4 damage (1->-3)', 'Round 2: B1 (Team B) counterattacks A1 (Team A) for 3 damage (3->0) [dying strike]', 'B1 (Team B) dies', 'Team B sends out B2', 'A1 (Team A) dies', 'Team A sends out A2', 'Round 3: A2 (Team A) attacks B2 (Team B) for 2 damage (7->5)', 'Round 3: B2 (Team B) counterattacks A2 (Team A) for 5 damage (8->3)', 'Round 4: A2 (Team A) attacks B2 (Team B) for 2 damage (5->3)', 'Round 4: B2 (Team B) counterattacks A2 (Team A) for 5 damage (3->-2)', 'A2 (Team A) dies', 'Result: Team B wins']}

Explanation: After round 2 both first monsters die and are replaced. B2 then defeats A2 in round 4, leaving Team A with no living monsters.

Input: ([], [('B', 1, 1)])

Expected Output: {'winner': 'Team B wins', 'log': ['Team A has no alive monsters.', 'Result: Team B wins']}

Explanation: Team A starts with no monsters, so it loses immediately.

Hints

  1. Keep a pointer (index) to each team’s current active monster and only move it forward when a monster dies to avoid rescanning from the beginning every round.
  2. To handle draws correctly, decide precisely when a monster is considered dead versus when it can still perform its counterattack ("dying strike").
Last updated: Mar 29, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Infection Spread Simulation with Death Threshold - OpenAI (medium)
  • Spreading Contagion on a Grid - OpenAI (medium)
  • Streaming Entropy with Numerical Stability - OpenAI (hard)
  • Implement a Distributed Rate Limiter - OpenAI (medium)
  • Compute Plant Infection Time - OpenAI (medium)