game development

SimCity, but with Permits: Building a Political City Simulation

SimCity, but with Permits: Building a Political City Simulation

SimCity, but with permits

A classic city builder gives you a clean map and a powerful cursor. Drag a road, paint a residential zone, wait a few seconds, and a block of apartments appears. The pleasure comes from watching an idea become a skyline.

Permit Pending starts from the opposite direction. It is a browser-based city simulation where a mayor proposes apartment buildings, bus lanes, and factories, then waits for hearings, objections, appeals, and elections. The game offers scenarios ranging from a 200-resident hamlet to a 300,000-resident metropolis. That scale is useful, but the more interesting design choice is the delay: every decision has time to collide with money, neighbors, and the next vote.

How do you build a game in which the most important action may be waiting? You model the city as a chain of causes rather than a pile of buildings.

Start with a clock

A simulation is a model that advances rules over time. For a permit-driven city, monthly turns are a natural unit. A hearing can happen in month seven, construction can finish months later, and an election can arrive before the crane does.

This is called a discrete-time simulation: the world updates in steps rather than continuously. The update loop might look like this:

for (const month of months) {
 resolveScheduledEvents(month);
 updateResidents(month);
 updateBusinesses(month);
 updateLandValues(month);
 publishNews(month);
 checkElection(month);
}

The order matters. If new jobs arrive before rents are recalculated, the city feels different than it would if housing prices updated first. A player may not see the loop, but they feel its consequences when a technology boom raises demand before their apartment proposal reaches a hearing.

Turn every project into a state machine

A permit should not be a boolean called approved. It is a process with legal and political stages. A state machine is a set of named states with rules for which transitions are allowed.

const nextStages = {
 draft: ['filed'],
 filed: ['hearing', 'withdrawn'],
 hearing: ['approved', 'modified', 'appealed', 'denied'],
 modified: ['hearing', 'withdrawn'],
 appealed: ['approved', 'denied'],
 approved: ['building'],
 building: ['complete'],
 complete: [],
 denied: [],
 withdrawn: []
};

This structure does more than make the interface look realistic. It prevents impossible outcomes. A withdrawn project cannot leap straight to completion, and an appeal can add months without requiring a special-case rule for every building type.

The state also gives the game a story surface. A six-story compromise is not the same object as a twelve-story proposal. It may produce fewer homes, earn less tax revenue, and disappoint a different group of voters. One transition changes several systems at once.

Give residents competing reasons

A single happiness bar cannot explain a zoning fight. An agent is a simulated actor with its own attributes and decisions. In a city game, an agent might be a household, a business, a neighborhood association, or a council member.

Each actor can evaluate the same project differently:

const influence = population * turnout * organization;
const support = benefits - perceivedCosts + trust;
const voteWeight = influence * support;

A renter may see an apartment building as relief from rising housing costs. A homeowner nearby may see traffic and a threat to property value. A business may welcome customers but fear construction delays. None of these reactions needs to be irrational, and none needs to be perfectly consistent.

The useful trick is to separate support from influence. A group can strongly oppose a project but rarely vote, while a smaller group can show up at every hearing. Permit Pending’s seven-seat council and four-year election cycle turn that distinction into a strategic problem: public opinion matters, but organized opinion gets a chair at the table.

Let the economy push back

The city’s economy should not be a decorative dashboard. It should create pressure that the player can trace.

A first housing model can be small:

const pressure = householdsSeekingHomes / Math.max(availableHomes, 1);
const rentChange = 0.02 * (pressure - 1) * averageRent;
averageRent += rentChange;

When demand exceeds available homes, rent rises. If a project is delayed, that shortage lasts longer. When the building finally opens, the pressure eases—but new jobs, transit access, or population growth may create another shortage somewhere else.

This is a feedback loop: an outcome becomes a new input. More transit can make a district attractive, which raises land values, which makes development profitable, which brings opposition, which slows development. The loop does not need a complicated economic forecast to feel convincing. It needs consequences that arrive late enough to surprise you and clearly enough to learn from.

Make delay a mechanic, not a loading screen

A hearing should not be a random pause. It should create decisions.

The game can place future events on an event queue, a list of actions sorted by the month when they occur:

events.push({ month: 7, type: 'hearing', caseId: 42 });
events.push({ month: 11, type: 'appeal', caseId: 42 });

Between those dates, the mayor has time to change parking rules, offer a concession, build a bus route, or spend political capital elsewhere. The proposed tower is no longer a button with a progress bar. It is a moving target inside a city that keeps changing.

That is why a small compromise can have a large cost. Reducing height may calm one neighborhood, but it can also make the project financially weak. A tax break may rescue it, but now the budget has less money for transit. The delay exposes dependencies that a faster city builder would hide.

Explain why the player lost

Complex simulations need observability, a way to inspect what the system is doing and why. Without it, a failed election feels like the game cheated.

A useful explanation might read:

Rents rose 14% because 1,200 households competed for 300 open homes.
The apartment case lost support after parking was reduced.
Homeowner turnout was high; renter turnout was low.

Heatmaps, graphs, a local newspaper, and case histories all serve the same purpose: they turn invisible calculations into evidence. The player can disagree with the simulation, but they should be able to reconstruct its logic.

This is also good engineering. The same tools that help a player understand a rent spike help a developer find a bug in the housing model. A game that explains itself is easier to balance because every surprising result leaves a trail.

The city is the unfinished argument

Permit Pending works as a city builder because it changes what progress means. A tower is not proof that the player made the correct choice; it is evidence that a coalition survived long enough to build one.

That makes the sandbox feel less like a machine waiting for instructions and more like a living argument. The map changes, residents react, businesses move, and the calendar keeps advancing while a permit sits in committee. The hard part is not placing the next building. It is preserving the chain of consequences from a good idea to a politically survivable one.

ahsan

ahsan

Hello! I am Mr Ahsan, the writer of the Website. I am from Netherland. I like to write about technology and the news around it.

Comments (0)

No comments yet. Be the first to respond!

Leave a Comment

Your comment will be visible after review.