To solve Nolan's optimization problem, we first need to define the variables and constraints based on the given conditions. Let's denote:

- \(x\) as the number of multiple choice questions answered,
- \(y\) as the number of short answer questions answered.

The objective is to maximize the total score, which can be calculated as \(2x + 5y\), since each multiple choice question is worth 2 points and each short answer question is worth 5 points.

The constraints are:
1. Nolan can answer at most 30 questions in total: \(x + y \leq 30\).
2. He must answer at least 15 multiple choice questions: \(x \geq 15\).
3. He must answer at least 10 short answer questions: \(y \geq 10\).
4. Nolan can answer at most 20 multiple choice questions: \(x \leq 20\).
5. He can answer at most 20 short answer questions: \(y \leq 20\).

All variables are non-negative since the number of questions cannot be negative.

Now, let's translate these conditions into Gurobi code in Python:

```python
from gurobipy import *

# Create a new model
m = Model("Nolan_Contest")

# Define the variables
x = m.addVar(lb=15, ub=20, vtype=GRB.INTEGER, name="multiple_choice")
y = m.addVar(lb=10, ub=20, vtype=GRB.INTEGER, name="short_answer")

# Set the objective function
m.setObjective(2*x + 5*y, GRB.MAXIMIZE)

# Add constraints
m.addConstr(x + y <= 30, "total_questions")

# Optimize model
m.optimize()

# Print solution
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Multiple Choice Questions: {x.x}")
    print(f"Short Answer Questions: {y.x}")
    print(f"Total Score: {2*x.x + 5*y.x}")
else:
    print("No optimal solution found")
```