Thursday, 24 July 2014

Custom AIs and whatnot: Parsnip Theory Alpha 11 released!

I've done another update to Parsnip Theory, which you can get... at, well, the link in this sentence.

Aside from the change in the table graphics so you don't accidentally mistake them for vents (yeah, they don't sit well with me, perhaps I could do some palette changes), I've given the AI system an overhaul.

By that I mean I've made it possible to write your own AIs in Lua.

Currently there's a crouching-aware version of the AI that's been there since I put AI in.

If you'd rather revert back to the old AI, just make the Lua side throw an error and it will jump back to that. Be very aware of this when writing your own AIs, because it can catch you out.

There are two functions that are added:
  • game.astar_layer(layer_index, x1, y1, x2, y2) - returns a list of directions (order is: 0=south, 1=east, 2=north, 3=west) to get from point 1 to point 2, or nil if you can't get there. WARNING: While point 1 can contain a player, point 2 cannot! So you'll want to find a neighbouring cell for point 2.
  • game.line_layer(layer_index, x1, y1, x2, y2) - returns a tuple (success, xt, yt) where (xt, yt) is where something thrown would actually land, and success is a boolean indicating if you actually managed to hit point 2.
The AI is called from time to time via a function called hook_tick. It takes one argument, conventionally "gstate". This is a table containing:
  • tid: The ID number of your team, useful for identifying who in the object table is actually in your team.
  • ocount: Number of objects in the object table.
  • layers: A table containing tables of the form:
    • x, y: Top-left corner of the layer. Do not assume this is 0, 0.
    • w, h: Width and height of the layer. Do not assume this is 40 x 40.
    • data: A 2D table in order [y][x] (not relative to x,y, so [0][3] really does mean (3, 0) in space!) containing cell data of the form:
      • ctyp: Type of cell. This is a string. Valid types are: "oob", "floor", "solid", "backwall", "table", and "layer" (which is unused and intended for transitions between layers.
      • tset, tidx: Tileset and tile index respectively - what the tile actually looks like.
      • p1: A parameter for specific kinds of tiles. Currently unused.
      • has_ob: A boolean indicating if there is an object on that tile or not.
  • objects: A table containing tables of the form:
    • otyp: What type of object this is. Valid types are: "player", "food_tomato". Note, you will probably never see food_tomato as while that object exists, the AI tends to not be called. Still, don't assume everything is a player.
    • layer: Which layer this object belongs to.
    • cx, cy: Which cell this object belongs to on its respective layer.
    • ox, oy: The pixel offset of this object. Note, this probably shouldn't be here, so don't rely on it, and expect me to remove it.
    • steps_left: How many steps this object can take - undefined for things that aren't players, but it's there.
    • health: How much health this thing has - once again, undefined for nonplayers.
    • flags: A table of certain things:
      • flags.crouch: True if this object is crouching.
    • fd: A table containing things specific to a given object. The stuff this contains for a player is:
      • team: Which team this player belongs to.
      • face: Which direction this object is facing (0=south, 1=east, 2=north, 3=west). Mostly irrelevant in terms of strategy.
gstate is generated every single time the function is called, and it's a copy of the current state. Modifying it will not allow you to cheat, as it won't affect the actual state of the game.

hook_tick must return one of these things:
  • "idle": Do nothing.
  • "newturn": Move onto the next player. You may need to return this several times, due to the turn change delay (which is there to prevent desyncs)
  • "move", x1, y1, x2, y2: Moves player at point 1 to point 2. You MUST ensure that the player at point 1 belongs to you, and it's YOUR responsibility to ensure there is a valid path. Use game.astar_layer to get the exact path.
  • "attack", x1, y1, x2, y2: Uses player at point 1 to attack point 2. You MUST ensure that the player at point 1 belongs to you, and it's YOUR responsibility to ensure there is a valid line of sight. Use game.line_layer to check this.
  • "crouch", x1, y1: Crouches player at point 1. You MUST ensure that the player at point 1 belongs to you and it isn't already crouched.
  • "stand", x1, y1: Stands player at point 1. You MUST ensure that the player at point 1 belongs to you and it is currently crouched.
That's the API, anyway.

So whether or not you read or understood any of that, go ahead and give Parsnip Theory a whirl today!
http://fanzyflani.itch.io/parsnip-theory

If you have any issues, there's always the comment section and my twitter @fanzyflani, and there's also a Facebook page for Parsnip Theory.

Have fun!

No comments:

Post a Comment