King’s Conflict is a cross-genre turn-based strategy game which offers a genuinely novel mix of cards, conquest, strategy, tactics, and above all fun. Available for PC and Android, it's now in Open Beta - and is 100% free!

Post feature Report RSS Map Design and the AI in King's Conflict

King's Conflict - a unique and free community-driven card/strategy hybrid game - is in late alpha but fully playable. The game is based around maps - it doesn't yet have a map-designer, but this article explains how maps are put together, to enable the community to design and submit then, and also gives some insights into the AI.

Posted by on

King's Conflict is a unique, free and (above all) fun card/strategy game hybrid, currently available for Windows only during testing. Download, create an account, and play!

Maps are at the heart of KC, and the KC team want to encourage the community to design them. This article should give anyone who wants to enough info to send in any maps they'd like to see in the game. At the moment the game doesn't have a map editor as such, but it's fairly easy to design maps as code.

We'll look at how the familiar ‘The Crossing' map (used for the tutorial) is defined.

The Terrain Map
First and most important is the map terrain data. When playing the game it looks like this:


But in the map design code it's represented as an 11x11 block of characters, like this:

MMHHHPPPPPP

MMMHPPPFFFF

MPFFPPFFFDF

PPPMP6ddd4P

PPMMPDPPPPP

-----B-----

PPPPPDPMMPP

P6ddd4PMPPP

FDFFFPPFFPM

FFFFPPPHMMM

PPPPPPHHHMM

Each character of course represents a different tile type. Mostly they are logical, though I ran out of sensible ones for all the various bends of rivers and roads. The full allowable set is:

P: Plains

M: Mountains

H: Hills

F: Forest

S: Sea

-: River (horizontal)

|: River (vertical)

0: River (bending from top to left)

1: River (bending from top to right)

2: River (bending from bottom to right)

3: River (bending from bottom to left)

B: Bridge (road vertical, river horizontal)

b: Bridge (river horizontal, road vertical)

D: Road (vertical)

d: Road (horizontal)

4: Road corner (from top to left)

5: Road corner (from top to right)

6: Road corner (from bottom to right)

7: Road corner (from bottom to left)

The following three terrain type have been newly added (since first post of this feature):

E: Desert

V: Volcano

L: Lava

Basic map design is pretty easy then, but there are a few things to bear in mind.

Get the bends right

There is nothing to stop you creating a map with impossible bends that don't join up. The game doesn't check this - it's up to you to design something that looks OK. Make sure you use the right bend/corner codes - the table below should help!


Symmetry

When you play, you always start in the bottom left corner. When you are playing online your opponent also thinks they are starting in the bottom left corner. This works, of course, because the game mirrors things quietly in the background, and you never really notice it - you see your friend in the top right corner in red, and he or she sees you in the top right corner in red. To achieve this, all maps absolutely HAVE to be completely symmetrical - mirrored about a line from top left to bottom right (the red line below). If they aren't, this trick doesn't work - and symmetry also keeps the game fair, as both sides have the same access to equal-sized regions.


It's up to the map designer to get this mirroring right - the game doesn't check, it assumes you know what you are doing! It's not quite as simple as just mirroring the codes either, as the road/river bends will all be reversed.

Terrain types

All maps need to have a good variety of terrain types, so that people don't find themselves with cards in their hand that they can't use at all. All maps need to have at least some forest, water (rivers, seas or both), mountains and plains. Hills are less vital, as there are no cards that absolutely require them. All current maps do have them though.

Design to counter cheesy tactics

The main things to be aware of here are top-decked mercenaries and jujus. Mercenaries can be placed anywhere in a controlled region - make sure it's not possible for someone to kill an enemy king by placing a mercenary on the first turn, before they get a chance to do anything. Also consider the small juju - could a player trap the opposing king before it can move? This would be a guaranteed and skill-less win, as the trapped player couldn't place units. It would also be boring and no fun to play against - best to avoid it in map design. There are a few other subtleties too. Remember for instance that mountains can be used to spawn dragons and mountain giants which can swat a king in a single stroke - so be careful putting mountains right next to the King's start point. Also be careful about blocking off one side of the map from the other. It's OK to block with forests (which only block one or two units), but having a map where you can't reach the opponent without crossing mountains or water is likely to annoy people, as it forces them to put certain cards in their deck to be able to play on your map.

Map data for the computer player

There is another side to map design - as well as laying out the terrain, we need to give the computer player (the A.I.) some hints as to how to play it. These are only relevant to the computer player - to play online against another human all the game needs is the terrain map described above - but all maps have A.I. hint data as well to make sure they are playable against a computer opponent.

Currently there are three sets of data for each map - again these are 11x11 grids of codes, each corresponding to a single terrain tile. The codes are numbers 0 to 9, and are used to help the A.I. score all possible moves and choose the best one.

First, we have the ‘strategic points' data. For the crossing, this looks like:

00100001210

00111232220

00112423320

00123444310

00136764400

00024942000

00227772200

00288882200

04788888210

08998811000

00987650000

The computer takes these into account when placing and moving combat-capable servants, and when placing combat-capable structures. A high number makes the tile more attractive to the computer, and a low number makes it less so. The positions are not mirrored - they are as you see the map, so you are bottom left and the computer is top right. Notice that these are set up so that the computer wants to position units around the bridge (which is strategically important), and down towards the bottom left (where your king is likely to be). They increase gradually for the most part towards these areas, so that there is a gradient - the computer doesn't look more than one move ahead, so to keep moving in the right direction there needs to be a strategic gain for each individual move. You might think that having a ‘9' for the bridge itself would mean that units get this far and no further (all moves from there are to a lower number, so less favoured), but as only one unit can occupy each tile this isn't a problem - the computer would tend to leave one unit guarding the bridge and then move others on, which is probably what you would want it to do.

These aren't the only thing the AI takes into account when moving. It also weighs up how well things are going, favouring moves away from its king and towards your king if it thinks it's ahead, and vice versa if it thinks it's behind. There are a few other rules as well, including preferring moves that help with region control, or would give a favourable combat outcome. Despite all this the strategic points remain important - giving sensible values for them can help the computer to play well.

Next is the ‘safe points' data. For The Crossing...

86554113467

85443331221

74333221110

64210000000

10000000000

00000000000

00000000000

00000000022

00000000333

00000000022

00000000004

This is similar to the strategic points, except that it applies to support units rather than combat units - things like farms, mines, peasants, smiths etc, that aren't going to be used for combat but instead need to be kept out of the way. Here the high values are towards the computers side of the map (and in the bottom right to a lesser extent).

Finally there is one other dataset, which at the moment is only used by stonemasons whose job is to head for the mountains and start generating walls. This is the ‘mountain_pref' data - for The Crossing it looks like:

98554433221

88855443311

85544332211

22284432110

00152110000

00000000000

00000112210

00000112110

00000000003

00000000222

00000000022

The high values here are in the mountains, for obvious reasons, but there is a gradient leading up to them to encourage the stonemasons to move in the right direction until they get there. So a stonemason starting near the top right in a ‘1' or ‘2' tile will tend to move left to a ‘3' or ‘4' tile first move, then left again to a ‘4' or ‘5' tile, etc, before eventually arriving in the nice safe ‘9' tile in the top left corner (or one of the ‘8''s round it if the ‘9' tile is occupied).

And that's it! Armed with all the above, anyone can create a KC map - if you do so and want it to be considered for general use, just create the four data grids and post them on the forums. Actually, even better would be to convert them into the form I need to put them into the program, which is as follows (this second example is the ‘Mountain Passes' map).

Have fun map making!


Sample code for "Mountain Passes"

GlobalVariables.stringmap=new Array(); //terrain map

GlobalVariables.stringmap.push("PPFFPPPPPPP");

GlobalVariables.stringmap.push("PFFFFPPPPHH");

GlobalVariables.stringmap.push("FFPPPPPD2--");

GlobalVariables.stringmap.push("HHHDHHHD|HH");

GlobalVariables.stringmap.push("HMMDMMHD|MM");

GlobalVariables.stringmap.push("MMMDMMMDMMM");

GlobalVariables.stringmap.push("MM|DHMMDMMH");

GlobalVariables.stringmap.push("HH|DHHHDHHH");

GlobalVariables.stringmap.push("--0DPPPPPFF");

GlobalVariables.stringmap.push("HHPPPPFFFFP");

GlobalVariables.stringmap.push("PPPPPPPFFPP");

GlobalVariables.strategicpoints=new Array(); //strategic points

GlobalVariables.strategicpoints.push("00000111100");

GlobalVariables.strategicpoints.push("00011111110");

GlobalVariables.strategicpoints.push("00022223222");

GlobalVariables.strategicpoints.push("00032223200");

GlobalVariables.strategicpoints.push("00143334200");

GlobalVariables.strategicpoints.push("00143334200");

GlobalVariables.strategicpoints.push("00254445310");

GlobalVariables.strategicpoints.push("00365555310");

GlobalVariables.strategicpoints.push("55476666200");

GlobalVariables.strategicpoints.push("99888775200");

GlobalVariables.strategicpoints.push("99987752100");

GlobalVariables.strategicpoints_safe=new Array(); //safe tiles

GlobalVariables.strategicpoints_safe.push("99887766555");

GlobalVariables.strategicpoints_safe.push("65322233366");

GlobalVariables.strategicpoints_safe.push("74322110000");

GlobalVariables.strategicpoints_safe.push("83211100055");

GlobalVariables.strategicpoints_safe.push("92014000000");

GlobalVariables.strategicpoints_safe.push("00000000000");

GlobalVariables.strategicpoints_safe.push("00000000006");

GlobalVariables.strategicpoints_safe.push("00000000005");

GlobalVariables.strategicpoints_safe.push("00001112224");

GlobalVariables.strategicpoints_safe.push("00011122233");

GlobalVariables.strategicpoints_safe.push("00001111222");

GlobalVariables.strategicpoints_mountain_pref =new Array(); //stonemason prefs

GlobalVariables.strategicpoints_mountain_pref.push("00001011000");

GlobalVariables.strategicpoints_mountain_pref.push("00011111100");

GlobalVariables.strategicpoints_mountain_pref.push("01111222200");

GlobalVariables.strategicpoints_mountain_pref.push("00333303000");

GlobalVariables.strategicpoints_mountain_pref.push("05400003099");

GlobalVariables.strategicpoints_mountain_pref.push("04100004560");

GlobalVariables.strategicpoints_mountain_pref.push("00000000000");

GlobalVariables.strategicpoints_mountain_pref.push("00000000000");

GlobalVariables.strategicpoints_mountain_pref.push("00000000000");

GlobalVariables.strategicpoints_mountain_pref.push("00000000000");

GlobalVariables.strategicpoints_mountain_pref.push("00000000000");

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: