gpgoap

Category: c library
Tags: C library

General Purpose GOAP

History

Unkown, used in game development.

FAQ

What is it?

Http request parser

How cool is it?

Rather.

Competitors?

cppgoap, probaly more

When to use it?

When have a limited (64) set of actions and transitions and don't want to program a full AI.

Is it dead?

Nope.

Where is it?

https://github.com/stolk/GPGOAP

How to use it

The documentation in the README.md is extremly good.

Download

file: 1_download.sh

#!/bin/bash

mkdir tmp
cd ./tmp
wget -q https://github.com/stolk/GPGOAP/archive/master.zip -O GPGOAP.zip
unzip -q GPGOAP.zip
cd GPGOAP-master
gcc -std=c99 -c goap.c
gcc -std=c99 -c astar.c
ar -cru libgpgoap.a goap.o astar.o
ranlib libgpgoap.a

Init

file: main.c

#include <stdio.h>
#include <string.h>

#include <goap.h>
#include <astar.h>

#define PLANS 16
int main(int argc, char** argv) {
    static actionplanner_t ap;
    worldstate_t from, goal;

    const char* plan[PLANS];
    int plansz = PLANS;
    int plancost;
    size_t i;
    char desc[ 4096 ];

    goap_actionplanner_clear(&ap);

    goap_set_pre(&ap, "scout", "armedwithgun", true);
    goap_set_pst(&ap, "scout", "enemyvisible", true);

    goap_set_pre(&ap, "approach", "enemyvisible", true);
    goap_set_pst(&ap, "approach", "nearenemy", true);

    goap_set_pre(&ap, "aim", "enemyvisible", true);
    goap_set_pre(&ap, "aim", "weaponloaded", true);
    goap_set_pst(&ap, "aim", "enemylinedup", true);

    goap_set_pre(&ap, "shoot", "enemylinedup", true);
    goap_set_pst(&ap, "shoot", "enemyalive", false);

    goap_set_pre(&ap, "load", "armedwithgun", true);
    goap_set_pst(&ap, "load", "weaponloaded", true);

    goap_set_pre(&ap, "detonatebomb", "armedwithbomb", true);
    goap_set_pre(&ap, "detonatebomb", "nearenemy", true);
    goap_set_pst(&ap, "detonatebomb", "alive", false);
    goap_set_pst(&ap, "detonatebomb", "enemyalive", false);

    goap_set_pre(&ap, "flee", "enemyvisible", true);
    goap_set_pst(&ap, "flee", "nearenemy", false);


    goap_description(&ap, desc, sizeof(desc));
    LOGI("%s", desc);

    goap_worldstate_clear(&from);
    goap_worldstate_set(&ap, &from, "enemyvisible", false);
    goap_worldstate_set(&ap, &from, "armedwithgun", true);
    goap_worldstate_set(&ap, &from, "weaponloaded", false);
    goap_worldstate_set(&ap, &from, "enemylinedup", false);
    goap_worldstate_set(&ap, &from, "enemyalive", true);
    goap_worldstate_set(&ap, &from, "armedwithbomb", true);
    goap_worldstate_set(&ap, &from, "nearenemy", false);
    goap_worldstate_set(&ap, &from, "alive", true);

    goap_set_cost(&ap, "detonatebomb", 5);	// make suicide more expensive than shooting.

    goap_worldstate_clear(&goal);
    goap_worldstate_set(&ap, &goal, "enemyalive", false);
    goap_worldstate_set(&ap, &goal, "alive", true); // add this to avoid suicide actions in plan.

    worldstate_t states[PLANS];
    plancost = astar_plan(&ap, from, goal, plan, states, &plansz);

    LOGI("plancost = %d", plancost);
    goap_worldstate_description(&ap, &from, desc, sizeof(desc));
    LOGI("%-23s%s", "", desc);

    for (i = 0; i < plansz && i < PLANS; ++i) {
        goap_worldstate_description(&ap, states+i, desc, sizeof(desc));
        LOGI("%d: %-20s%s", i, plan[i], desc);
    }

    printf("cost: %\n", plancost);

    return 0;
}

file: 2_compile_and_run.sh

#!/bin/bash

gcc -o ./tmp/main main.c -I./tmp/GPGOAP-master/ -L./tmp/GPGOAP-master -lgpgoap
./tmp/main

Output

scout:
  armedwithgun==1
  enemyvisible:=1
approach:
  enemyvisible==1
  nearenemy:=1
aim:
  enemyvisible==1
  weaponloaded==1
  enemylinedup:=1
shoot:
  enemylinedup==1
  enemyalive:=0
load:
  armedwithgun==1
  weaponloaded:=1
detonatebomb:
  nearenemy==1
  armedwithbomb==1
  enemyalive:=0
  alive:=0
flee:
  enemyvisible==1
  nearenemy:=0

plancost = 4
                       ARMEDWITHGUN,enemyvisible,nearenemy,weaponloaded,enemylinedup,ENEMYALIVE,ARMEDWITHBOMB,ALIVE,
0: scout               ARMEDWITHGUN,ENEMYVISIBLE,nearenemy,weaponloaded,enemylinedup,ENEMYALIVE,ARMEDWITHBOMB,ALIVE,
1: load                ARMEDWITHGUN,ENEMYVISIBLE,nearenemy,WEAPONLOADED,enemylinedup,ENEMYALIVE,ARMEDWITHBOMB,ALIVE,
2: aim                 ARMEDWITHGUN,ENEMYVISIBLE,nearenemy,WEAPONLOADED,ENEMYLINEDUP,ENEMYALIVE,ARMEDWITHBOMB,ALIVE,
3: shoot               ARMEDWITHGUN,ENEMYVISIBLE,nearenemy,WEAPONLOADED,ENEMYLINEDUP,enemyalive,ARMEDWITHBOMB,ALIVE,

Note:

The output is here in text; IRL you'd probably walk the structs directly.

The input is also as text which is error prone, Youd better use some defines/enums.

64 states/actions might seem a bit less, but with this amount of memory usage you could have many-many variants.

Further reading:

We only tipped the top of the iceberg here. There is much more:

http://alumni.media.mit.edu/~jorkin/goap.html