Inces awnser is spot on, these are just some tips to go along.
First of all, if you need to hold more info per tile (for example, has zombie and is water) consider having other dictionaries (like a json) or arrays as values like so:
var grid : Dictionary = {
Vector(0,0) : {
object : zombie,
terrain : forest,
has_trap : true,
walkable: false
}
Vector(1,0) : {
object : wall,
terrain : grass,
has_trap : false,
walkable : false
}
...
}
One advtange of doing this, is that when you later start to code all the logic, for example, if you can walk in the tile or not, you dont have to check if it has a bear, a shark, a castle, etc.. you just check for example, if grid[Vector(x,y)].walkable
.
Aside from that, how to to do the checks, and how to change info is 100% dependant on your game, and up to you. For example if a "fight" has to happen always that 2 units end up one next to the other, I would do this:
first, I would put in the object key, an actuall class or node that represents the entity. The important thing is to be able to check if the object is of type say "unit". You also could have a setter function in the grid var, in order to trigger checks when the grid is changed (you could also do the checks based on player input for example). Then i would do this:
func get_neighbors(tile_pos) -> Array:
# this returns an array holding the 4 neighbors of the given tile
func has_unit(tile_pos) -> bool:
# returns true if the object value is of type unit
func should_battle(tile_pos) -> bool:
for tile in get_neighbors(tile_pos):
if has_unit(tile):
# trigger the fight
In this example you would check for should_battle()
after a unit moves, using of course the position the unit moved to.
Last advice, making this types of games involves a lot of logic, so they could be quite daunting. I have great love for them though, so if you too, power on!