[Question]
  [
Caveman mad. Other caveman take stick but stick was for me. Caveman **fight**!
---
## Description
Caveman need sharp stick to stab other caveman. Other caveman also try to stab with sharp stick. Caveman can sharpen stick, poke with stick, or block poky sticks.
If caveman poke other caveman with sharp stick, other caveman run away and me victory. But if other caveman smartly blocking when me poking, nothing happen except my stick become blunt and me need to sharpen again.
Caveman lazy. Also, caveman dumb. Caveman no know what to do, so caveman need fancy techno computer program to tell caveman what to do.
## Input
Your program's input will be a history of the events that have happened, where `S` stands for sharpen (i.e. the caveman sharpened his stick), `P` stands for poke, and `B` stands for block. The input will be a history of both sides (you and the opponent), so your and the opponent's moves will be separated with a comma (`,`).
Example input:
```
SPB,SBB
```
This means that the player sharpened his/her stick, then poked, then blocked, and the opponent sharpened, then blocked, then blocked again.
You will receive no input on turn 1.
## Output
The output is very similar to the input (because the caveman is not very smart). Your program should output `S` to sharpen, `P` for poke, and `B` for block. Only the first character of output will be taken into account, and any other input will be treated as a `B` (block) command.
* **`S`: sharpen**
When sharpening, the caveman's stick's sharpness goes up by 1 and the stick gets 1 extra poke. Each poke reduces the stick's sharpness by 1, and if the stick's sharpness is 0, it's too dull to poke with. Sharpness starts at 0. If sharpness gets to 5, the stick is a sword! (See below.)
If the opponent pokes while you are sharpening (and they have a sharpness > 0), the opponent wins!
* **`P`: poke**
When poking, the caveman's stick's sharpness goes down by 1 and you poke your opponent! If your opponent is sharpening, you win! If the opponent is poking, your stick hits your opponent's stick and they both get duller (by 1 "sharpness unit"). If the opponent is blocking, nothing happens except that your stick becomes duller.
If you poke when your stick's sharpness is 5 or greater, your stick becomes a sword and you *always* win! (Unless your opponent also has a sword and also chose `P`; in that case, they both become duller, and may revert to sticks if their sharpness falls below 5.)
You cannot poke with a sharpness of 0. If you do, nothing will happen.
* **`B`: block**
When you block, nothing happens when your opponent pokes. If your opponent is not poking, block does nothing.
Blocking does not protect against a sword, even if you also have one!
## Rules and constraints
Additional rules are:
* Your program can read and write files in its *own* folder (no stealing!) if you want to save data, but you can't access anything outside of it (and cavemen don't have internet connection out in the wilderness).
	+ **Important note on files**: If you save files, remember to save them in the directory `players/YourBotsName/somefile.foo`! The current working directory for your program will not be your program's!
* Cavemen are fair: One program can not have code specific for another program, and programs can not help each other. (You may have multiple programs, but they can't interact with each other in any way.)
* The caveman judge is not patient. If the cavemen take more than 100 turns each to decide a winner, the judge gets bored and both cavemen lose.
If your program breaks a rule or doesn't follow the specification, the program is disqualified, removed from `playerlist.txt`, and all duels restart from the beginning. If your program is disqualified, the caveman leader (me!) will comment on your program's post and explain why. If you aren't breaking any rules, your program will be added to the leaderboard. (If your program is not on the leaderboard, there is no explanatory comment on your post, and you posted your program before the "Last updated" time below, tell the caveman leader! Maybe he forgot it.)
In your post, please include:
* A name.
* A shell command to run your program (ex. `java MyBot.java`, `ruby MyBot.rb`, `python3 MyBot.py`, etc.).
	+ Note: input will be appended to this as a command line argument.
	+ The cavemen use Ubuntu 14.04, so make sure your code works (freely) on it.
* A version number, if your code works differently on different versions of your chosen language.
* Your code (obviously).
* How to compile the code, if necessary.
## Controller code / testing, example bot
The caveman leader wrote the control code in C++, and [posted it on a Github repo](https://github.com/KeyboardFire/caveman-duels). You can run and test your program there.
A very, *very* simple program (1 line!) is also [posted in the answers below](https://codegolf.stackexchange.com/a/34969/3808).
## Scoring and leaderboard
Scoring is easy. Whichever caveman wins gets a point. The caveman with the most points after 3 duels against every other caveman becomes the new caveman leader!
```
150     Watson
147     SpeculativeSylwester
146     Gruntt
141     BashMagnon
126     ChargerMan
125     PrisonRules
124     ViceLeader
122     MultiMarkov
122     CaveDoctor
120     RegExMan
120     Hodor
117     FancyTechnoAlgorithm
116     Semipatient
113     Watcher
108     BobCaves
105     MinimaxMan
104     Oracle
102     MaybeMarkov
97      Nash
95      Sicillian
95      Feint
95      Basilisk
94      SharpMan
93      Darwin
91      Nigel
91      JavaMan
88      Entertainer
88      CarefulBot
85      CaveMonkey
84      SSBBP
82      SirPokealot
79      MasterPoker
77      Unpredictable
76      IllogicalCaveman
75      SharpenBlockPoke
75      HuddleWolfWithStick
72      WoodenShield
68      PokeBackBot
68      PatientBlacksmith
66      PatientWolf
58      MonteCarloMan
58      BlindFury
56      BinaryCaveman
55      PokeBot
55      CavekidBlocks
53      Swordmaster
53      Blocker
52      NakedEarlyNerd
52      ModestCaveman
50      LatePokeBot
40      Trickster
39      SwordLover
38      ForeignCaveman
36      Swordsmith *
28      Touche
27      WantASword
27      FoolMeOnce
24      PeriodicalCavemanCicada
11      Aichmophobic
```
*(this leaderboard was auto-magically generated)*
Players marked with a `*` threw some kind of error or exception at some point; these players also have a comment on their posts.
Players who could not be included in the tests for any reason (these players will have a comment on their posts explaining the problem): `Monkey`, `Elephant`, `FacileFibonacci`, `StudiousSylwester`.
Last updated: Aug 3 00:15 (UTC).
  
[Answer]
# Unpredictable Caveman
```
me, he = (ARGV[0] || ' , ').split(',')
@possible_actions = %w[Sharpen Poke Block]
class String
  def sharpness
    @sharpness ||= count('S') - count('P')
  end
  def has_pointy_stick
    (1..4).cover? sharpness
  end
  def has_sword
    sharpness >= 5
  end
  def scary
    sharpness > 0
  end
end
def no action
  @possible_actions.delete(action)
end
def do!
  puts @possible_actions.sample[0]
end
no 'Block' if not he.has_pointy_stick
no 'Poke' if not me.scary
no 'Sharpen' if me.has_sword
no 'Block' if me.has_sword
do!
```
This caveman chooses randomly each round, but I've explained to him very simply that certain actions just don't make sense sometimes. Feel free to copy this code if you want to express different logic.
This is Ruby, save as 'unpredictable.rb' and run with `ruby unpredictable.rb`
[Answer]
# Darwin - C
Who needs strategy, anyway?
Have a group of cavemen go at each other and let natural selection do the rest!
---
We use a very simple model for out caveman's primitive brain: it has no memory and only takes the sharpness of his and his opponent's stick into account.
Those are used as the variables for a binary polynomial of some finite order.
Each action (block, sharpen and poke) has an associated polynomial whose result determines the relative probability of choosing this action.
That's pretty much all there is to it---start with some random coefficients and optimize iteratively.
The bot:
```
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* magic numbers */
#define SWORD_SHARPNESS 5
#define PROGRAM_DIM 4 /* polynomial order + 1 */
#define DEFAULT_FILENAME "players/Darwin/program"
typedef double real;
typedef real program[PROGRAM_DIM][PROGRAM_DIM];
typedef program caveman_brain[3];
typedef char action; /* S, B or P */
/* encodes a pair of actions */
#define ACTION_PAIR(a1, a2) (((int)(a1) << (sizeof(action) * 8)) | (a2))
real eval_program(const program p, double x, double y) {
    real v = 0;
    int i, j;
    for (i = 0; i < PROGRAM_DIM; ++i) {
        real w = 0;
        for (j = 0; j < PROGRAM_DIM; ++j)
            w = x * w + p[i][j];
        v = y * v + w;
    }
    if (v < 0)
        v = 0;
    return v;
}
void read_program(FILE* f, program p) {
    int i, j;
    for (i = 0; i < PROGRAM_DIM; ++i) {
        for (j = 0; j < PROGRAM_DIM; ++j) {
            double v;
            fscanf(f, "%lg", &v);
            p[i][j] = v;
        }
    }
}
int blunt(int* s) {
    int temp = *s;
    if (temp)
        --*s;
    return temp;
}
void sharpen(int* s) { ++*s; }
/* takes two sharpness/action pairs and updates the sharpness accordingly.
 * returns negative value if first caveman wins, positive value if second
 * caveman wins and 0 otherwise. */
int act(int* s1, action a1, int* s2, action a2) {
    switch (ACTION_PAIR(a1, a2)) {
        case ACTION_PAIR('B', 'B'): return 0;
        case ACTION_PAIR('B', 'S'): sharpen(s2); return 0;
        case ACTION_PAIR('B', 'P'): return blunt(s2) >= SWORD_SHARPNESS ? 1 :
                                                                          0;
        case ACTION_PAIR('S', 'B'): sharpen(s1); return 0;
        case ACTION_PAIR('S', 'S'): sharpen(s1); sharpen(s2); return 0;
        case ACTION_PAIR('S', 'P'): sharpen(s1); return *s2 > 0 ? 1 : 0;
        case ACTION_PAIR('P', 'B'): return blunt(s1) >= SWORD_SHARPNESS ? -1 :
                                                                          0;
        case ACTION_PAIR('P', 'S'): sharpen(s2); return *s1 > 0 ? -1 : 0;
        case ACTION_PAIR('P', 'P'): {
            int t1 = blunt(s1), t2 = blunt(s2);
            if (t1 >= SWORD_SHARPNESS && t2 < SWORD_SHARPNESS)
                return -1;
            else if (t2 >= SWORD_SHARPNESS && t1 < SWORD_SHARPNESS)
                return 1;
            else
                return 0;
        }
    }
}
/* processes a pair of strings of actions */
int str_act(int* s1, const char* a1, int* s2, const char* a2) {
    for (; *a1 && *a2; ++a1, ++a2) {
        int winner = act(s1, *a1, s2, *a2);
        if (winner)
            return winner;
    }
    return 0;
}
double frandom() { return (double)rand() / RAND_MAX; }
/* chooses an action based on self and opponent's sharpness */
action choose_action(const caveman_brain b, int s1, int s2) {
    double v[3];
    double sum = 0;
    double r;
    int i;
    for (i = 0; i < 3; ++i) {
        v[i] = eval_program(b[i], s1, s2);
        sum += v[i];
    }
    r = frandom() * sum;
    if (r <= v[0])
        return 'B';
    else if (r <= v[0] + v[1])
        return 'S';
    else
        return 'P';
}
/* portable tick-count for random seed */
#ifdef _WIN32
#include <Windows.h>
unsigned int tick_count() { return GetTickCount(); }
#else
#include <sys/time.h>
unsigned int tick_count() {
    struct timeval t;
    gettimeofday(&t, NULL);
    return 1000 * t.tv_sec + t.tv_usec / 1000;
}
#endif
int main(int argc, const char* argv[]) {
    const char* filename = DEFAULT_FILENAME;
    const char *a1, *a2;
    FILE* f;
    caveman_brain b;
    int s1 = 0, s2 = 0;
    int i;
    srand(tick_count()); rand();
    a1 = argc > 1 ? argv[1] : "";
    if (*a1) {
        a2 = strchr(a1, ',');
        if (a2 == NULL) {
            printf("invalid input!\n");
            return 1;
        }
        ++a2;
    } else
        a2 = a1;
    if (argc > 2)
        filename = argv[2];
    f = fopen(filename, "r");
    if (f == NULL) {
        printf("failed to open `%s'\n", filename);
        return 1;
    }
    for (i = 0; i < 3; ++i)
        read_program(f, b[i]);
    fclose(f);
    str_act(&s1, a1, &s2, a2);
    printf("%c\n", choose_action(b, s1, s2));
    return 0;
}
```
Compile with: `gcc darwin.c -odarwin -w -O3`.
Run with: `./darwin <history>`.
The bot reads the coefficients from a file named `program` in the `players/Darwin` directory (a different file can be specified as a second command-line argument).
This program seems to do well:
```
0.286736 0.381578 -0.128122 1.33933 
0.723126 0.380574 1.21659 -0.9734 
0.924371 0.998632 -0.0951554 0.744323 
-0.113888 -0.321772 -0.260496 -0.136341 
0.280292 -0.699782 -0.246245 1.27435 
-1.24563 -0.959822 -0.745656 0.0347998 
-0.917928 -0.384105 0.319008 -0.70434 
0.484375 0.802138 0.0967234 0.638466 
0.406679 0.597322 1.39409 0.902353 
-0.735946 0.742589 0.955567 0.643268 
-0.503946 0.446167 1.002 0.328205 
0.26037 0.113346 0.0517265 -0.223298 
```
Save as `players/Darwin/program`.
Following is a program that generates `program` files that can be used by the bot (doesn't have to be compiled if you use the `program` file above):
```
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* magic numbers */
#define SWORD_SHARPNESS 5
#define MAX_TURN_COUNT 100
#define PROGRAM_DIM 4 /* polynomial order + 1 */
#define CAVEMAN_COUNT 500
#define GENERATION_COUNT 12
#define DUEL_COUNT 8
#define ERROR_BACKOFF 0.5
#define DEFAULT_FILENAME "players/Darwin/program"
typedef double real;
typedef real program[PROGRAM_DIM][PROGRAM_DIM];
typedef program caveman_brain[3];
typedef char action; /* S, B or P */
/* encodes a pair of actions */
#define ACTION_PAIR(a1, a2) (((int)(a1) << (sizeof(action) * 8)) | (a2))
real eval_program(const program p, double x, double y) {
    real v = 0;
    int i, j;
    for (i = 0; i < PROGRAM_DIM; ++i) {
        real w = 0;
        for (j = 0; j < PROGRAM_DIM; ++j)
            w = x * w + p[i][j];
        v = y * v + w;
    }
    if (v < 0)
        v = 0;
    return v;
}
void write_program(FILE* f, const program p) {
    int i, j;
    for (i = 0; i < PROGRAM_DIM; ++i) {
        for (j = 0; j < PROGRAM_DIM; ++j)
            fprintf(f, "%g ", p[i][j]);
        fprintf(f, "\n");
    }
    fprintf(f, "\n");
}
int blunt(int* s) {
    int temp = *s;
    if (temp)
        --*s;
    return temp;
}
void sharpen(int* s) { ++*s; }
/* takes two sharpness/action pairs and updates the sharpness accordingly.
 * returns negative value if first caveman wins, positive value if second
 * caveman wins and 0 otherwise. */
int act(int* s1, action a1, int* s2, action a2) {
    switch (ACTION_PAIR(a1, a2)) {
        case ACTION_PAIR('B', 'B'): return 0;
        case ACTION_PAIR('B', 'S'): sharpen(s2); return 0;
        case ACTION_PAIR('B', 'P'): return blunt(s2) >= SWORD_SHARPNESS ? 1 :
                                                                          0;
        case ACTION_PAIR('S', 'B'): sharpen(s1); return 0;
        case ACTION_PAIR('S', 'S'): sharpen(s1); sharpen(s2); return 0;
        case ACTION_PAIR('S', 'P'): sharpen(s1); return *s2 > 0 ? 1 : 0;
        case ACTION_PAIR('P', 'B'): return blunt(s1) >= SWORD_SHARPNESS ? -1 :
                                                                          0;
        case ACTION_PAIR('P', 'S'): sharpen(s2); return *s1 > 0 ? -1 : 0;
        case ACTION_PAIR('P', 'P'): {
            int t1 = blunt(s1), t2 = blunt(s2);
            if (t1 >= SWORD_SHARPNESS && t2 < SWORD_SHARPNESS)
                return -1;
            else if (t2 >= SWORD_SHARPNESS && t1 < SWORD_SHARPNESS)
                return 1;
            else
                return 0;
        }
    }
}
/* processes a pair of strings of actions */
int str_act(int* s1, const char* a1, int* s2, const char* a2) {
    for (; *a1 && *a2; ++a1, ++a2) {
        int winner = act(s1, *a1, s2, *a2);
        if (winner)
            return winner;
    }
    return 0;
}
double frandom() { return (double)rand() / RAND_MAX; }
double firandom() { return 2.0 * rand() / RAND_MAX - 1.0; }
/* chooses an action based on self and opponent's sharpness */
action choose_action(const caveman_brain b, int s1, int s2) {
    double v[3];
    double sum = 0;
    double r;
    int i;
    for (i = 0; i < 3; ++i) {
        v[i] = eval_program(b[i], s1, s2);
        sum += v[i];
    }
    r = frandom() * sum;
    if (r <= v[0])
        return 'B';
    else if (r <= v[0] + v[1])
        return 'S';
    else
        return 'P';
}
typedef struct {
    caveman_brain brain;
    int sharpness;
    int score;
} caveman;
void init_caveman(caveman* c, const caveman* m, double e) {
    int p, i, j;
    c->score = 0;
    for (p = 0; p < 3; ++p) {
        for (i = 0; i < PROGRAM_DIM; ++i) {
            for (j = 0; j < PROGRAM_DIM; ++j) {
                c->brain[p][i][j] = m->brain[p][i][j] + firandom() * e;
            }
        }
    }
}
int duel(caveman* c1, caveman* c2) {
    int winner;
    int turn;
    c1->sharpness = c2->sharpness = 0;
    for (turn = 0; turn < MAX_TURN_COUNT; ++turn) {
        winner = act(&c1->sharpness,
                     choose_action(c1->brain, c1->sharpness, c2->sharpness),
                     &c2->sharpness,
                     choose_action(c2->brain, c2->sharpness, c1->sharpness));
        if (winner)
            break;
    }
    if (winner < 0)
        ++c1->score;
    else if (winner > 0)
        ++c2->score;
    return winner;
}
/* portable tick-count for random seed */
#ifdef _WIN32
#include <Windows.h>
unsigned int tick_count() { return GetTickCount(); }
#else
#include <sys/time.h>
unsigned int tick_count() {
    struct timeval t;
    gettimeofday(&t, NULL);
    return 1000 * t.tv_sec + t.tv_usec / 1000;
}
#endif
int main(int argc, const char* argv[]) {
    const char* filename = DEFAULT_FILENAME;
    FILE* f;
    caveman* cavemen;
    caveman winner;
    int gen;
    double err = 1.0;
    int i;
    srand(tick_count()); rand();
    memset(&winner, 0, sizeof(caveman));
    if ((cavemen = (caveman*)malloc(sizeof(caveman) * CAVEMAN_COUNT)) == NULL) {
        printf("not enough memory!\n");
        return 1;
    }
    for (gen = 0; gen < GENERATION_COUNT; ++gen) {
        int i, j, k;
        const caveman* leader;
        printf("[Gen. %d / %d] ", gen + 1, GENERATION_COUNT);
        fflush(stdout);
        for (i = 0; i < CAVEMAN_COUNT; ++i)
            init_caveman(&cavemen[i], &winner, err);
        for (i = 0; i < CAVEMAN_COUNT; ++i) {
            for (j = i + 1; j < CAVEMAN_COUNT; ++j) {
                for (k = 0; k < DUEL_COUNT; ++k)
                    duel(&cavemen[i], &cavemen[j]);
            }
        }
        leader = cavemen;
        for (i = 1; i < CAVEMAN_COUNT; ++i) {
            if (cavemen[i].score > leader->score)
                leader = &cavemen[i];
        }
        printf("Caveman #%d wins with %d victories in %d duels\n",
               leader - cavemen + 1,
               leader->score, (CAVEMAN_COUNT - 1) * DUEL_COUNT);
        memcpy(&winner, leader, sizeof(caveman));
        err *= ERROR_BACKOFF;
    }
    free(cavemen);
    if (argc > 1)
        filename = argv[1];
    printf("Dumping brain to `%s'\n", filename);
    f = fopen(filename, "w");
    if (f == NULL) {
        printf("failed to open `%s'\n", filename);
        return 1;
    }
    for (i = 0; i < 3; ++i)
        write_program(f, winner.brain[i]);
    fclose(f);
    return 0;
}
```
Compile with: `gcc genprog.c -ogenprog -w -O3`.
Run with: `./genprog [output-filename]`.
---
# Watson
What's the DNA of a winning caveman?
Perhaps this fella has the answer:
```
# That's the actual logic. Initialization goes below.
def run():
    if his_sharpness[-10] - turn / 15 + 1 + turn % 3 - his_sharpness[-6] < 0:
        act(B=0, S=0, P=100) # 7.21% chance
    elif his_sharpness[-6] + 1 - his_sharpness[-2] < 0:
        act(B=0, S=0, P=100) # 4.15% chance
    elif his_history[-3] - my_history[-1] <= 0 and my_sharpness[-1] - turn / 10 <= 0:
        act(B=0, S=100, P=0) # 11.34% chance
    elif his_sharpness[-1] == 0:
        act(B=0, S=100, P=0) # 27.84% chance
    else:
        act(B=100, S=0, P=0) # 49.46% chance
# Boring stuff go here...
import sys, random
# Actions
block, sharpen, poke, idle = range(4)
# Converts textual history to internal format
def convert_history(textual_history):
    return ["BSP".index(action) for action in textual_history]
# Calculates sharpness after performing an action sequence
def calculate_sharpness(history):
    return history.count(sharpen) - history.count(poke)
# Returns a list containing the sharpness at the end of each turn
def sharpness_history(history):
    return [calculate_sharpness(history[:i + 1]) for i in range(len(history))]
# Acts based on the probability distribution (B%, S%, P%)
def act(B, S, P):
    r = random.random() * 100
    print "BSP"[(r >= B) + (r >= B + S)]
# Setup data
textual_history = sys.argv[1] if len(sys.argv) > 1 else ","
my_history, his_history = (convert_history(h) for h in textual_history.split(','))
my_sharpness, his_sharpness = (sharpness_history(h) for h in (my_history, his_history))
turn = len(my_history)
my_history, his_history = ([idle] * 16 + h for h in (my_history, his_history))
my_sharpness, his_sharpness = ([0] * 16 + s for s in (my_sharpness, his_sharpness))
# Make a move
run()
```
Run with: `python Watson.py`
Watson is the product of a genetic algorithm.
Unlike Darwin, the genetic datum this time is an actual program, written in a tiny domain-specific language (here translated to Python).
---
# Simple Sequence Beats Big Players
This little fella does surprisingly (or, maybe, not so surprisingly) well, especially against the leaders:
```
import sys
print "Simple Sequence Beats Big Players".split(' ')[
    len(sys.argv[1]) / 2 % 5 if len(sys.argv) > 1 else 0
]
```
Run with: `python SSBBP.py`
[Answer]
# Cave Doctor - Lua
"Me lose to new foreigners, knocked them out to study them"
When you've seen as many patients as the cave doctor, you begin to truly understand the cave man psyche (or so I hope). Cave doctor's game is pure strategy, he waits for pokes which he blocks in an attempt to disarm his opponent, but he won't let that opponent get close to making a sword. He tries to predict when it's safe to sharpen so he doesn't loose the upper hand.
```
caveman={havePointyStick=function (t)     
   local pointy=0   
   for i in t.stick:gmatch("[SP]") do
    if i=="S" then 
      pointy=pointy+1
    elseif pointy>0 then
      pointy=pointy-1
    end   
   end 
 t.sharp=pointy>0
 t.lastmove=t.stick:sub(t.stick:len())
 return pointy 
 end,
    Stupid=function (stick)--I put way to much effort in this...
      o = {} 
      setmetatable(o, caveman)
      o.smartness=0
      o.stick=stick
      caveman.__index = caveman
      return o
    end,
     Smart= function (stick)
      o ={} 
      setmetatable(o, caveman)
      o.smartness=100
      o.stick=stick
      caveman.__index = caveman
      return o
    end
       }
    if arg[1]==nil then  
       print("S")
    else   
      split=arg[1]:find(",")  
      me=caveman.Smart(arg[1]:sub(0,split-1)) 
      he=caveman.Stupid(arg[1]:sub(split+1)) 
      mesharp=me:havePointyStick()  
      hesharp=he:havePointyStick()
      if not he.sharp and mesharp<5 then print("S")--Go for the sword  
      elseif mesharp>4 or me.stick:len()>93 then
         if (mesharp>0) then print("P")--We're losing/about to win or time's running out
         else print("S")--uh-oh
         end
      else 
         u,g,h=he.stick:match("(B+)S+(B+)S+(B+)$")
         g,u,h=he.stick:match("(P+)S+(P+)S+(P+)$")
         if u~=nil and u==g and g==h then 
            if not me.sharp then print("S")
            else print("P")
            end
         elseif me.stick:match("SBSB$")~=nil then print("B")
         elseif he.stick:len()>7 and he.stick:match("P")==nil and me.lastmove~="S" then print("S")
         else
         b,u,h=he.stick:match("(B*)(S+)(B*)$")
         if u~=nil then
             if (h:len()>3 and me.lastmove=="B") or (b:len()>h:len() and b:len()>0 and h:len()>0) then print("S")
             else print("B")
             end
          else print("B")
          end   
      end   
   end 
end
```
Run with: `lua CaveDoctor.lua`
[Answer]
# ForeignCaveman
ForeignCaveman has no idea what you just said. He just... does stuff.
`javac ForeignCaveman.java` then `java ForeignCaveman`
```
public class ForeignCaveman {
    public static void main(String[] args) {
        int m = (int) (Math.random()*3);
        switch(m) {
            case 0: System.out.println('B'); 
                    break;
            case 1: System.out.println('P'); 
                    break;
            case 2: System.out.println('S'); 
                    break;
        }
   }
}
```
[Answer]
# Vice-Leader
[Doorknob♦](https://codegolf.stackexchange.com/users/3808/doorknob) is leader. Me want be leader! Follow super intelligent program to become leader!
Compile: `javac ViceLeader.java` Run: `java ViceLeader`.
```
public class ViceLeader {
    public static void main(String[] args) {
        if (args.length == 0 || !args[0].contains(",")) {
            System.out.print("S");
            return;
        }
        String[] history = args[0].split(",");
        int mySharpness = getSharpness(history[0]);
        int enemySharpness = getSharpness(history[1]);
        // enough sharpness to strike until end of game
        if (100 - history[0].length() <= mySharpness) {
            System.out.print("P");
            return;
        }
        // sharpen while secure
        if (enemySharpness == 0) {
            System.out.print("S");
            return;
        }
        // enemy blocks the whole time and I didn't use this tactic on last turn
        if (isBlocker(history[1]) && history[0].charAt(history[0].length() - 1) != 'S') {
            System.out.print("S");
            return;
        }
        // TAKE HIM OUT!
        if (enemySharpness == 4 || mySharpness >= 5) {            
            System.out.print("P");
            return;
        }
        // enemy sharpens the whole time => sharpen to strike on next turn
        if (isSharpener(history[1])) {
            System.out.print("S");
            return;
        }
        System.out.print("B");
    }
    private static int getSharpness(String history) {
        int sharpness = 0;
        for (char move : history.toCharArray()) {
            if (move == 'S') {
                sharpness++;
            } else if ((move == 'P' && sharpness > 0) || move == '^') {
                sharpness--;
            }
        }
        return sharpness;
    }
    private static boolean isBlocker(String history) {
        if (history.length() < 3) {
            return false;
        }
        for (int i = history.length() - 1; i > history.length() - 3; i--) {
            if (history.charAt(i) != 'B') {
                return false;
            }
        }
        return true;
    }
    private static boolean isSharpener(String history) {
        if (history.length() < 3) {
            return false;
        }
        for (int i = history.length() - 1; i > history.length() - 3; i--) {
            if (history.charAt(i) != 'S') {
                return false;
            }
        }
        return true;
    }
}
```
[Answer]
# Maybe Markov 2.1
I think it uses Markov Chains to predict what the other caveman will do, but I only looked briefly at the wikipedia page about Markov Chains and decided it had too much text.
It tries to stay alive for 30 rounds and then builds up a table with current-next state changes, and reacts to what is thinks the other caveman will do.
The code contains a lot of unnecessary statements, but it performs pretty well.
## EDIT
Detected a flaw in logic. Now it actually does something when it has a sword.
`$ python3 players/MaybeMarkov/MaybeMarkov.py`
```
import sys, itertools
from operator import itemgetter
from collections import defaultdict
SHARPEN, POKE, BLOCK, HALP = 'SPB?'
all_actions = SHARPEN, POKE, BLOCK
always = 1
def do(action):
    print(action)
    exit(0)
if len(sys.argv) < 2:
    do(SHARPEN)
class status:
    def __init__(self, actions):
        self.step = len(actions)
        self.last = actions[-1]
        self.sh = self.sharpness = actions.count(SHARPEN) - actions.count(POKE)
        self.dull = self.sharpness <= 0
        self.has_sword = self.sharpness >= 5
        self.actions = actions
        self.ratio = {act:actions.count(act)/self.step for act in all_actions}
        self.can_do = set(all_actions)
        if self.dull:
            self.can_do.remove(POKE)
    def can(self, action):
        return action in self.can_do
me, he = map(status, sys.argv[-1].split(','))
turns = me.step
if he.has_sword:
    if me.can(POKE)                :do(POKE)
    if always                      :do(SHARPEN)
if me.has_sword:
    if he.last != POKE and me.last == BLOCK :do(POKE)
    if he.can(POKE)                :do(BLOCK)
    if always                      :do(POKE)
if not he.can(POKE)                :do(SHARPEN)
if turns <= 4                      :do(BLOCK)
if turns < 30:
    if he.ratio[SHARPEN] == 1:
        if me.can(POKE)            :do(POKE)
        if always                  :do(SHARPEN)
    if always                      :do(BLOCK)
if turns > 97:
    do(POKE)
def react_on(action):
    do({
        HALP    : BLOCK,
        SHARPEN : POKE,
        POKE    : BLOCK,
        BLOCK   : SHARPEN
    }[action])
states = tuple(itertools.product(all_actions, all_actions))
change = defaultdict(lambda:defaultdict(lambda:0))
count  = defaultdict(lambda:0)
for i in range(1, turns):
    prev = me.actions[i-1], he.actions[i-1]
    now  = me.actions[i]  , he.actions[i]
    change[prev][now] += 1
    count[prev] += 1
current = change[me.last, he.last]
prediction = HALP
if len(current) is 0:
    do(BLOCK)
if len(current) is 1:
    if tuple(current.values())[0] > turns / 7:
        prediction = tuple(current.keys())[0][1]
counts = itemgetter(1)
if len(current) > 1:
    key1, value1 = max(current.items(), key=counts)
    current[key1] *= 0.9
    key2, value2 = max(current.items(), key=counts)
    if key1 == key2:
        prediction = key1[1]
react_on(prediction)
```
[Answer]
# FancyTechnoAlgorithm
A fancy techno algorithm for the fancy techno computer program.
Caveman keep lose battle. Caveman angry. So caveman go to computer school learn make algorithm.
```
import random, sys  # Need import some advanced techno code
if __name__ == '__main__':  # If fancy techno computer program is main
    try:  # Me try use fancy techno algorithm!
        me, he     = sys.argv[1].split(",")
        mePointy   = me.count("S") - me.count("P")
        hePointy   = he.count("S") - he.count("P")
        meCanPoke  = mePointy > 0
        heCanPoke  = hePointy > 0
        meHasSword = mePointy >= 5
        heHasSword = hePointy >= 5
        meScary    = meCanPoke + meHasSword 
        heScary    = heCanPoke + heHasSword
        # Me donno fancy coding math algoritm.
        # Math confuse. Me code work, me happy.
        if he[-6:] == "SB"*3:
            print "SP"[meCanPoke]
        elif (len(he) > 30 and he[-3:].count("B") > 2) or \
             (hePointy > 2 and he.count("SSBB") > 0 and he.count("BBS") > 0):
            if meHasSword:
                print "P"
            else:
                print "SB"[me[-1] == "S"]
        elif hePointy > 3 and he.count("BBS") > 2:
            print "SP"[me[-1] == "S"]
        else:
            print random.choice(\
                [["S", "SP", "P" ],\
                 ["B", "B" , "P" ],\
                 ["S", "P" , "P" ]][heScary][meScary])
    except:  # Fancy techno algorithm Failed... Me just sharpen.
        print "S"
```
Python 2 program. To run: `python fancytechnoalgorithm.py`
[Answer]
**PeriodicalCicadaCaveman**
This rather smart cave man has studied a certain [Bug](http://en.wikipedia.org/wiki/Periodical_cicadas) and realized no one can adjust their life style to take advantage of the prime number Cicada. 
It hides / blocks for most of it's life, but occasionally pokes. Sure it's vulnerable to Swords, and spends a whole cycle with an unsharpened stick, but sharpening your stick when it's totally blunt? That's exactly what the others expect from it... not this Cicada
to compile: **mcs program.cs** to run **mono program.exe**
```
public class PeriodicalCicadaCaveman
{
  const int Periodic = 13; //Could be 17
  public static void Main(string[] args)
  {
    if (args.Length == 0) 
    {
          System.Console.WriteLine("S");
          return;
    }
    var arg1 = args[0];
    if(arg1.Length == 0) 
    {
        //Always start with a sharp stick
        System.Console.WriteLine("S");
        return;
    }
    var myHistory = arg1.Split(',')[0];
    var theirHistory = arg1.Split(',')[1];
    int sharpness = 0;
    int timeElapsed =  myHistory.Length;
    for(int i = 0; i < timeElapsed; i++)
    {
        if(myHistory[i] == 'S')  
        {
            sharpness++;
        }
        if(myHistory[i] == 'P')
        {
            sharpness--;
        }
    }
    if((myHistory.Length % 13) == 0 
            || timeElapsed > 90 // Running out of time! To hell with the routine
        )
    {
        //The Secada strikes!
        if(sharpness > 1)
        {
            System.Console.WriteLine("P");
            return;
        }
        else
        {
            System.Console.WriteLine("S"); 
            return;
        }
    }
    System.Console.WriteLine("B"); 
  }
}
```
Edit: Changed the sharpness-- code... if I poke either I win or my stick gets duller
Edit2: Added in Bobs suggestion
Edit: Changed to only poke when at sharpness 2, if the stick is ever at zero the other guy might make a sword.
[Answer]
## The Watcher
He watches his opponent's movements, always letting them show their hand before he strikes. He is particularly prepared for those who neglect to work toward a sword.
```
import sys, random
if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""
def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret
def weighted_random(dict):
    i = random.randrange(sum(dict.values()))
    for k, v in dict.items():
        i -= v
        if i < 0:
            return k
def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif sharpness_other == 0:
        return 'S'  #Guaranteed safe
    elif sharpness_other == 1:
        #If the opponent isn't interested in a sword, time is on our side
        block_count = len(history_self) - len(history_self.rstrip('B'))
        if block_count > 3 and random.randrange(block_count) > 3:
            return 'S'
        else:
            return 'B'
    elif sharpness_other >= 5:
        return 'S'
    else:
        #Search for a weakness
        for i in range(10, 2, -1):
            if history_other[-i:] == history_other[-i*2:-i]:
                predicted_action = history_other[-i]
                if predicted_action == 'S':
                    if sharpness_self > 0:
                        return 'P'
                    else:
                        return 'S'
                elif predicted_action == 'B':
                    return 'S'
                elif predicted_action == 'P':
                    return 'B'
        #Presumably the opponent is random - respond with some educated randomness
        if sharpness_self == 0:
            return random.choice(['S','S','B'])
        return weighted_random({
            'S': sharpness_self,
            'B': 1,
            'P': sharpness_other,
        })
if __name__ == "__main__":
    print(action(history_self, history_other))
```
Filename: `watcher.py`
To run: `python watcher.py`
## Basilisk
Seeks to destroy those who look at him too closely. Consistently beats the Watcher, but will probably fare worse overall.
```
import sys, random
if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""
def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret
def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif len(history_self) < 13:
        return 'SBBSBPSBBSBPP'[len(history_self)]
    elif 5 + 5 * sharpness_self < random.randrange(len(history_self)):
        return 'S'
    elif sharpness_other == 0:
        if sharpness_self == 0 or random.randrange(sharpness_self) == 0:
            return 'S'
        else:
            return 'P'
    elif sharpness_other == sharpness_self:
        return 'P'
    else:
        return 'B'
if __name__ == "__main__":
    print(action(history_self, history_other))
```
Filename: `basilisk.py`
To run: `python basilisk.py`
## Nash
Seeks to make his opponent's choices irrelevant, by choosing each move with a probability that accounts for its risks and rewards
```
import sys, random
if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""
movemap = [ [(1.000000,0.000000),(0.473863,0.526137),(0.394636,0.605364),(0.490512,0.509488),(1.000000,0.000000)],
        [(0.695328,0.000000,0.304672),(0.275953,0.582347,0.141700),(0.192635,0.700391,0.106974),(0.196343,0.689662,0.113995),(0.289968,0.544619,0.165413)],
        [(0.570635,0.000000,0.429365),(0.236734,0.570126,0.193139),(0.167197,0.687133,0.145670),(0.173139,0.667169,0.159693),(0.264911,0.475316,0.259773)],
        [(0.490512,0.000000,0.509488),(0.196309,0.578888,0.224803),(0.135744,0.692358,0.171898),(0.140638,0.663397,0.195965),(0.220709,0.426989,0.352302)],
        [(1.000000,0.000000,0.000000),(0.147944,0.636760,0.215296),(0.089478,0.737358,0.173165),(0.087259,0.704604,0.208137),(0.128691,0.435655,0.435655)]  ]
def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret
def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif sharpness_other >= 5:
        return 'S'
    moves = movemap[sharpness_self][sharpness_other]
    v = random.random()
    if v < moves[0]:
        return 'S'
    elif v < moves[0] + moves[1]:
        return 'B'
    else:
        return 'P'
if __name__ == "__main__":
    print(action(history_self, history_other))
```
This isn't quite the Nash equilibrium (my strategy generator has some instability), but it's close.
For curiosity's sake, here are the estimates of how likely this bot is to win in each game state:
```
map = [ [0.50000000,0.26337111,0.15970733,0.08144046,0.00000000,0.00000000],
        [0.73662889,0.50000000,0.37879183,0.28035985,0.16622410,0.00000000],
        [0.84029267,0.62120817,0.50000000,0.39441630,0.26038353,0.00000000],
        [0.91855954,0.71964015,0.60558370,0.50000000,0.35246401,0.00000000],
        [1.00000000,0.83377590,0.73961647,0.64753599,0.50000000,0.00000000],
        [1.00000000,1.00000000,1.00000000,1.00000000,1.00000000,0.50000000] ]
```
Filename: `nash.py`
To run: `python nash.py`
## Feint
Opens with a quick attack, to test his opponent's defenses.
```
import sys, random
if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""
def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret
def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    sharpness_other = sharpness(history_other)
    if sharpness_self >= 5:
        return 'P'
    elif len(history_self) < 2:
        return 'SP'[len(history_self)]
    elif history_other[1] == 'P':
        # Fierce fight
        if sharpness_self == 0:
            return 'S'
        elif history_self[-(1 + history_self.count('P'))] == 'S':
            return 'P'
        else:
            return 'B'
    else:
        # Smart guy
        if sharpness_other == 1:
            return 'B'
        elif history_self[-1] != 'S' or history_self[-4:] == 'BSBS':
            return 'S'
        elif history_other.count('S') > history_other.count('B'):
            return 'P'
        else:
            return 'B'
if __name__ == "__main__":
    print(action(history_self, history_other))
```
Filename: `feint.py`
To run: `python feint.py`
## LatePokeBot
PokeBot's little brother. Never shows weakness, but tries to fight like his big brother.
```
import sys, random
if len(sys.argv) > 1:
    history_self, history_other = sys.argv[1].split(',')
else:
    history_self = history_other = ""
def sharpness(history):
    ret = 0
    for action in history:
        if action == 'S':
            ret += 1
        elif action == 'P' and ret > 0:
            ret -= 1
    return ret
def action(history_self, history_other):
    sharpness_self = sharpness(history_self)
    return 'SSP'[sharpness_self]
if __name__ == "__main__":
    print(action(history_self, history_other))
```
Filename: `latepokebot.py`
To run: `python latepokebot.py`
[Answer]
# PokeBot
Written in Ruby.
```
puts((ARGV.shift || "P,").match(/(.),/)[1] == "P" ? "S" : "P")
```
Run with `ruby pokebot.rb`.
This bot isn't very smart; it does about what the average caveman would do on his own anyway.
[Answer]
# PatientWolf v2.0
Sharpens if dull, pokes if enemy will have a sword next turn or if enemy is dull, blocks otherwise.
```
my ($me,$him) = split(/,/,$ARGV[0]);
if(!defined $me) {
    print "S";
    exit;
}
my $mysharpness =()= ($me =~ /S/g);
$mysharpness -= ($me =~ /P/g);
my $opponentsharpness =()= ($him =~ /S/g);
$opponentsharpness -= ($him =~ /P/g);
if($mysharpness == 0) {
    print "S";
} elsif($opponentsharpness <= 0 || $opponentsharpness == 4) {
    print "P";
} else {
    print "B";
}
```
Run with
```
perl patientwolf.pl
```
EDIT: thanks to @sylwester for pointing out a bug
[Answer]
# **Binary Caveman**
*Sharpen, Stab, Repeat*
Based on the idea that blocking is for sissies, this caveman alternates between the two remaining options.
```
public class BinaryCaveman { 
    public static void main(String[] args) {
        int timelapse = 0;
        if(args.length>0)
        {
            timelapse = ((args[0].length() - 1) / 2);
        }
        switch(timelapse % 2) 
        {
            case 0: System.out.println('S'); 
                    break;
            case 1: System.out.println('P'); 
                    break;
        }
    }
}
```
Compile with `javac BinaryCaveman.java`
Run with `java BinaryCaveman`
**EDIT:** Adventures in String Arrays..... args.length() throws an error. args.length always returns 1. args[0].length() returns the lengths of the first string in the array.
**EDIT 2:** Updated thanks to help from Doorknob, Brilliand, and Sylwester. Thanks guys.
[Answer]
# CavekidBlocks
A crying and frightened cave kid may look like an easy prey. Don't let his pretty face fool you 'cause he knows how to block.
```
import sys, math, random
def count(a):
    s = 0
    for i in range(len(a)):
        if a[i] == 'P': s-=1
        elif a[i] == 'S': s+=1
        if s < 0: s = 0
    return s
kid = []
scary_adult = []
what2do = 'Sharpen the Stick! Why not? Adult may be doing the same. DONT trust adults!'
if len(sys.argv) > 1:
    kid, scary_adult = sys.argv[1].split(",")
    kid_stick_sharpness = count( kid )
    scary_adult_stick_sharpness = count( scary_adult )
    if (scary_adult_stick_sharpness >= 2):
        what2do = "Block! Block! Block! Adult's stick looks scary sharp."
    elif (kid_stick_sharpness > 0):
        what2do = 'Point your Stick to the adult. It may scary him.'
    else:
        what2do = 'Sharpen the Stick!'
    # Roll d20 for a courage check.
    dice = random.randint(1,20)
    if (dice > 15): what2do = 'Poke the adult! Critical Hit!'
    elif (dice <= 5): what2do = 'Block! Block! Block!'
print(what2do[0])
```
Run with `python3 cavekidblocks.py`
# ChargerMan
This caveman is very conservative. Will try to charge his weapon and only attacks when needed.
```
import sys, math, random
def countSharpness(a):
    s = 0
    for i in range(len(a)):
        if a[i] == 'P': s-=1
        elif a[i] == 'S': s+=1
        if s < 0: s = 0
    return s
def getHistory():
    me = ""
    him = ""
    if len(sys.argv) > 1:
        me, him = sys.argv[1].split(",")
    return me,him
if __name__ == '__main__':
    me, him = getHistory()
    me_s = countSharpness(me)
    him_s = countSharpness(him)
    answer = 'B'
    # First Case
    if (len(me) == 0):
        answer = 'S'
    # I have a sword
    elif (me_s == 5):
        answer = 'P'
    # Cant let he gets a sword
    elif (him_s == 4):
        answer = 'P'
    # His sword is dull
    elif (him_s == 0):
        # He may try to sharp
        # Cant attack? Sharp my stick
        if (me_s == 0): answer = 'S'
        else:
            if (random.randint(0,33) != 0): answer = 'S'
            else: answer = 'P'
    elif (len(him) % 5 == 0):
        # Decide what to do based on the
        # opponent last 3 movements.
        hist = him[-3:]
        # Does he like to block?
        if (hist.count('B') >= 2): answer = 'S'
    print(answer)
```
Run with `python3 chargerman.py`
# Trickster
Trickster doesn't know how to fight, so he tries to confuses other caveman.
```
import sys, math
a = "PPS"
i = 0
if (len(sys.argv) > 1): i = math.floor(((len(sys.argv[1])-1)/2) % 3)
print(a[i])
```
Run with `python3 trickster.py`
Unfortunately, after the commit [acc74](https://github.com/KeyboardFire/caveman-duels/commit/acc7413b3df37dfabdea61d82ef8d78ada139290), Trickster doesnt work as planned anymore.
[Answer]
# Hodor
Hodor is not very aggressive. He likes to stay in his shield unless there's a good opportunity to strike. 
compile with: `javac Hodor.java` and run with: `java Hodor`
code:
```
public class Hodor {
    public static void main(String[] args){
        String previousMoves = null;
        //account for no input
        if(args.length == 0){
            System.out.print('S');
            System.exit(0);
        }else{
            previousMoves = args[0];
        }
        //declare variables
        char action = 'S';
        int enemySharpens = 0, enemyPokes = 0, myPokes = 0, mySharpens = 0;
        String[] movesArray = previousMoves.split(",");
        char[] enemyMoves = movesArray[1].toCharArray(), myMoves = movesArray[0].toCharArray();
        //determine enemy sharpness
        for(int i=0; i<enemyMoves.length; i++){
            if(enemyMoves[i] == 'S'){
                enemySharpens++;
            }else if(enemyMoves[i] == 'P'){
                enemyPokes++;
            }
        }
        //block if opponent can poke, else sharpen
        if(enemySharpens - enemyPokes > 0){
            action = 'B';
        }else{
            action = 'S';
        }
        //determine my sharpness
        for(int i=0; i<movesArray[0].length(); i++){
            if(myMoves[i] == 'P'){
                myPokes++;
            }else if(myMoves[i] == 'S'){
                mySharpens++;
            }
        }
        //poke as much as possible if the game is about to end
        if((mySharpens-myPokes) > (100-enemyMoves.length)){
            action = 'P';
        }
        try{
            //sharpen if opponent blocks 2 times in a row and I didn't just sharpen
            if((enemyMoves[enemyMoves.length-1] == 'B') && (enemyMoves[enemyMoves.length-2] == 'B') && (myMoves[myMoves.length-1] != 'S')){
                action = 'S';
            }
            //poke if opponent sharpens twice in a row
            if((enemyMoves[enemyMoves.length-1] == 'S') && (enemyMoves[enemyMoves.length-2] == 'S')){
                action = 'P';
            }
            //poke if the opponent just sharpened/blocked then poked, has a blunt stick, and my stick isn't blunt
            if((enemyMoves[enemyMoves.length-2] != 'P') && (enemyMoves[enemyMoves.length-1] == 'P') && (enemySharpens-enemyPokes == 0) && (mySharpens - myPokes > 0)){
                action = 'P';
            }
        }catch (ArrayIndexOutOfBoundsException e){
            //not enough info
        }
        //poke if we have a sword
        if(mySharpens-myPokes > 4){
            action = 'P';
        }
        System.out.print(action);
    }
}
```
Edit: minor code update
[Answer]
# Speculative Sylwester - Perl5
Speculative Sylwester wants to take out sword seekers by looking at the patterns and poke when there is a chance opponent will sharpen and sharpen when opponent is most likely to block. However, he will not do that if there is a chance that he would have guessed that himself will sharpen in the next move and we are even more cautious when we decide to sharpen.
As for when opponent is blunt he tries to be aggressive but will eventually start to save for a sword when that seems fruitless.
```
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
## Valid operations
my $SHARPEN = "S";
my $POKE    = "P";
my $BLOCK   = "B";
## It will also print resolution to stderr
my $VERBOSE = 0;
my $first_move = not @ARGV;
my ($me, $you) = split(',', $ARGV[0]) unless( $first_move );
## What do I do?
me_do($SHARPEN, "beginning") if $first_move;
me_do($POKE, "end is near") if  almost_over() || sword($me);
me_do($SHARPEN, "you sword") if !sword($me) && sword($you);
me_do($POKE, "you repeat") if consecutive_sharpens($you) && sharp($me);
me_do(blunt_move(), "you blunt stick") if not sharp($you); 
me_do(aggressive_move(), "me think you sharpen") if sharpen_next($you) && !sharpen_next($me);
me_do($SHARPEN, "me think you block") if you_block_next() && very_little_chance_me_sharpen_next();
me_do($BLOCK, "me have no idea you do");
sub almost_over {
  sharp($me) >= (100 - length($you));
}
sub sharp {
  my $history = shift;
  my $sharp = 0;
  foreach my $s ( split('',$history) ) {
    $sharp++ if( $s eq "S");
    $sharp-- if( $s eq "P" && $sharp > 0);
  }
  return $sharp;
}
sub sword {
  my $me = shift;
  sharp($me) >= 5;
}
sub num_pokes {
  my $me = shift;
  $me =~ s/[^P]//g; #/ SO highlight bug?
  length($me);
}
sub consecutive_sharpens {
  my $you = shift;
  $you =~ m/SS+$/
}
sub sharpen_next {
  my $you = shift;
  $you =~ /([^S]+)S\1S\1$/;
}
sub you_block_next {
  $you =~ /([^B]+B*)B\1B\1$/ || $you =~ /B{4}$/;
}
sub very_little_chance_me_sharpen_next {
  $me !~ /S$/ && ( $me !~ /([^S]+)S\1$/ || $me =~ /^SB+SB+$/ ); 
}
sub blunt_move {
  my $sword_move = sword($me) ? $POKE : $SHARPEN;
  ( $me =~ m/(?:PS){5,}/ || sharp($me)*7 < num_pokes($me) ? $sword_move : aggressive_move() );
}
sub aggressive_move {
  sharp($me)? $POKE : $SHARPEN;
}
sub me_do {
  my ($stick_operation, $reason) = @_;
  my $arg = ( $first_move ? "" : "$me,$you" );
  my $resolution = "$stick_operation me do because $reason ($arg)";
  print "$resolution\n";
  err($resolution);
  exit;
}
sub err {
  my($str) = @_;
  print STDERR "SpeculativeSylwester:$str\n" if $VERBOSE;
}
```
To run on linux just add this in playerlist.txt:
```
perl players/SpeculativeSylwester/SpeculativeSylwester.pl
```
# Facile Fibonacci - R6RS Scheme
Besides the first move Facile Fibonacci blocks when the turn is a [Fibonacci number](http://en.wikipedia.org/wiki/Fibonacci_number) (starting from 0) and fills the rest with `PPSS..` and changes when passes 8 to an endless sequence of `PSS` to win with a sword.
```
#!r6rs
(import (rnrs base)
        (only (rnrs) fold-left display command-line))
(define %SHARPEN "S")
(define %POKE    "P")
(define %BLOCK   "B")
(define (fibonacci? n)
  (let loop ((a 1) (b 1))
    (cond ((> a n) #f)
          ((= a n) #t)
          (else (loop b (+ a b))))))
(define (poke? num-sp)
  (if (< num-sp 8)
      (even? (div num-sp 2))
      (= 2 (mod num-sp 3))))
(define (split-string x)
  (let ((len (div (string-length x) 2)))
    (substring x 0 len)))
(define (num-sp x)
  (fold-left (lambda (a x)
               (if (eqv? x #\B) a (+ a 1)))
               0
               (string->list x)))
(define (advanced-strategy me)
  (cond ((fibonacci? (string-length me)) %BLOCK)
        ((poke? (num-sp me)) %POKE)
        (else %SHARPEN)))
(define (decide args)
  (if (= (length args) 1)
      %SHARPEN
      (advanced-strategy (split-string (cadr args)))))
;; The dirty imperative code:
(display (decide (command-line)))
```
To run just install ikarus with `apt-get install ikarus` and add this in playerlist.txt:
```
ikarus --r6rs-script players/FacileFibonacci/FacileFibonacci.scm
```
# Studious Sylwester - Perl5
Studious Sylwester uses the same tactic as Speculative Sylwester, but he also looks at previous games to determine where he might have taken a wrong choice.
```
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
## Valid operations
my $SHARPEN = "S";
my $POKE    = "P";
my $BLOCK   = "B";
## It will also print resolution to stderr
my $VERBOSE = 0;
my $path = $0; # "players/StudiousSylwester/StudiousSylwester.pl";
my $first_move = not @ARGV;
my ($me, $you) = split(',', $ARGV[0]) unless( $first_move );
## What do I do?
me_do($SHARPEN, "beginning") if $first_move;
me_do(consult_history($POKE, "end is near")) if  almost_over() || sword($me);
me_do(consult_history($SHARPEN, "you sword")) if sword($you);
me_do(consult_history($POKE, "you repeat")) if consecutive_sharpens($you) && sharp($me);
me_do(consult_history(blunt_move(), "you blunt stick")) if not sharp($you);
me_do(consult_history(aggressive_move(), "me think you sharpen")) if sharpen_next($you) && !sharpen_next($me);
me_do(consult_history($SHARPEN, "me think you block")) if you_block_next() && very_little_chance_me_sharpen_next();
me_do(consult_history($BLOCK, "me have no idea you do"));
sub almost_over {
  sharp($me) >= (100 - length($you));
}
sub sharp {
  my $history = shift;
  my $sharp = 0;
  foreach my $s ( split('', $history) ) {
    $sharp++ if( $s eq "S");
    $sharp-- if( $s eq "P" && $sharp > 0);
  }
  return $sharp;
}
sub sword {
  my $me = shift;
  sharp($me) >= 5;
}
sub num_pokes {
  my $me = shift;
  $me =~ s/[^P]//g; #/ SO highlight bug?
  length($me);
}
sub consecutive_sharpens {
  my $you = shift;
  $you =~ m/SS+$/
}
sub sharpen_next {
  my $you = shift;
  $you =~ /([^S]+)S\1S\1$/;
}
sub you_block_next {
  $you =~ /([^B]+B*)B\1B\1$/ || $you =~ /B{4}$/;
}
sub very_little_chance_me_sharpen_next {
  $me !~ /S$/ && ( $me !~ /([^S]+)S\1$/ || $me =~ /^SB+SB+$/ );
}
sub blunt_move {
  my $sword_move = sword($me) ? $POKE : $SHARPEN;
  ( $me =~ m/(?:PS){5,}/ || sharp($me)*7 < num_pokes($me) ? $sword_move : aggressive_move() );
}
sub aggressive_move {
  sharp($me)? $POKE : $SHARPEN;
}
sub consult_history {
  my ($suggested_move, $why) = @_;
  my $mylen = length($me);
  # By demanding 5 or more there are 81 (- illegals)
  # different possibilities. Below that and
  # we are shooting in the dark.
  return @_ if( $mylen <= 4 );
  my $override = $suggested_move;
  my @lines = ();
  my %matches      = (P => 0, B=> 0, S=> 0);
  my %match_prefix = (P => 0, B=> 0, S=> 0);
  my $file = "$path.prefix";
  my $sem = "$path.sem";
  my $found_session = 0;
  # Since Judge is running multiple instances at the same time we flock
  open(LOCK, "> $sem") || die ("$path error while open $sem: $!");
  flock(LOCK, 2);
  if( -e $file ) {
    open(FH, $file) || die("$path: error while open $file: $!");
    my $prevyou = substr($you,0,-1);
    while(my $ln = <FH>){
      if ( $ln =~ m/^$me(.).*,$you(.?).*$/ ) {
         # Match that ends here is either a win or a loss depending on my choice
     my $key = ($2 eq "" ? ( $1 eq $POKE ? $SHARPEN : $POKE ) : $2);
     $matches{$key}++;
     $match_prefix{$1}++;
      }
      if( $ln =~ m/^$me,$prevyou$/ ) {
        $found_session++;
    next;
      }
      $found_session++ if( $ln =~ m/^$me.*,$prevyou.*$/ );
      push @lines,$ln;
    }
  }
  my $num_matches = (grep { $matches{$_} != 0 } keys %matches);
  unless( $num_matches || $found_session || $mylen == 5 ) {
    err("WARNING: You have not started this game from the beginning. This will not be a valid outcome! ($me,$you)");
  }
  if( $num_matches == 1 ) {
    my $match_val = (grep { $matches{$_} != 0 } keys %matches)[0];
    if( $match_val eq $BLOCK && !sharp($me)) {
      $override = $SHARPEN;
      $why = "me know u block";
    } elsif ( $match_val eq $SHARPEN ) {
      $override =  aggressive_move();
      $why = "me know u sharpen";
    } elsif ( $match_val eq $POKE && !sword($me) ) { 
      $override = $BLOCK;
      $why = "me know u poke";
    }
  } elsif($num_matches > 1 && $mylen > 6 ) {
    # if the chances are overwelming we are not poked we might as well sharpen
    # if we are wrong here we loose
    if( $matches{$POKE} * 4 < ($matches{$BLOCK}+$matches{$SHARPEN}) && !sword($me)){
      $override = $SHARPEN;
      $why = "me think u block/sharpen";
    }
    # if chances for sharpening is higher than poke/block we go for it with any stick
    if( $matches{$SHARPEN} > 2*($matches{$BLOCK}+$matches{$POKE}) && sharp($me) ) {
      $override = $POKE;
      $why = "me think u sharpen";
    }
    # if the chances for poke is overwelming, we might consider blocking
    if( $matches{$POKE} > 2*($matches{$BLOCK}+$matches{$SHARPEN}) && !sword($me)){
      $override = $BLOCK;
      $why = "me think u poke";
    }
  }
  unless ( $match_prefix{$override} ) {
    open( FH, "> $file") ||     die("$path: error while open $file: $!");
    push @lines, "$me$override,$you\n";
    foreach my $line ( sort @lines ) {
      print FH $line;
    }
  }
  my $stats = join("",map {"$_=>$matches{$_} "} keys %matches);
  if( $override ne $suggested_move ) {
     $why .= ". stats: $stats, original choice: $suggested_move";
  }
  close FH;
  close LOCK;
  return ( $override, $why );
}
sub me_do {
  my ($stick_operation, $reason) = @_;
  my $arg = ( $first_move ? "" : "$me,$you" );
  my $resolution = "$stick_operation me do because $reason ($arg)";
  print "$resolution\n";
  err($resolution);
  exit;
}
sub err {
  my($str) = @_;
  print STDERR "StudiousSylwester:$str\n" if $VERBOSE;
}
```
To run on linux just add this to playerlist.txt
```
perl players/StudiousSylwester/StudiousSylwester.pl
```
**Studious edit**
I can't reproduce the problems you had with `$0` not being the full path to the perl script when it's run with perl. I have also pulled your changes and I see no changes in the CavemanDuels src and It's the same I've been running 20+ times without the problem you are reporting. I'm starting to fear you might have sourced the script as a bash script instead of running it while executable or as an argument to perl. I need more info to actually know for sure. As a test I did this and you can do the same to see if you get the same result:
```
echo '#!/usr/bin/perl
print "$0\n\n";' > testcmd.pl;
perl ./testcmd.pl;           # outputs ./testcmd.pl
bash -c "perl ./testcmd.pl"; # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs an error since it's not executable
chmod 755 ./testcmd.pl;
./testcmd.pl;                # outputs ./testcmd.pl
bash -c ./testcmd.pl;        # outputs ./testcmd.pl since it's executable
```
[Answer]
# Swordsmith
Need sharp stick. If have sharp stick, poke. Me no feel pain.
```
program Swordsmith
   implicit none
   integer :: mySharp,ierr,arg_count
   logical :: lExist
   character(38) :: filename = "players/Swordsmith/SwordsmithSharp.txt"
   
! check argument counts for initialization of storage file
   arg_count = command_argument_count()
   if(arg_count == 0) then
      inquire(file=filename,exist=lExist)
      mySharp = 0
      if(lExist) then
         open(unit=10,file=filename,status='replace')
      else
         open(unit=10,file=filename,status='new')
      endif
      write(10,*) mySharp
      close(10)
   endif
   
! open, read, & close the file for mySharp
   open(unit=10,file=filename,status='old')
   read(10,*) mySharp
   close(10)
! make decision
   if(mySharp < 5) then
      print '(a1)',"S"
      open(unit=10,file=filename,status='replace')
      mySharp = mySharp + 1
      write(10,*) mySharp
      stop
   endif
   print '(a1)',"P"
end program Swordsmith
```
Save as `swordsmith.f90` and compile with `gfortran -o swordsmith swordsmith.f90`, execute as you would any normal executable: `./swordsmith`.
[Answer]
## PatientBlacksmith
This bot is written in R, use `Rscript PatientBlacksmith.R` to trigger it .
```
args <- commandArgs(TRUE)
if(length(args)){
    input <- strsplit(strsplit(args,split=",")[[1]],"")
    me <- input[[1]]
    opponent <- input[[2]]
    sharpness <- 0
    for(i in seq_along(opponent)){
        if(opponent[i]=="S") sharpness <- sharpness + 1
        if(opponent[i]=="P") sharpness <- sharpness - 1
        }
    out <- ifelse(sharpness>0,"B","S")
    bfree <- me[me!="B"]
    r <- rle(bfree) #run length encoding
    S_sequence <- r$length[r$value=="S"]
    P_sequence <- r$length[r$value=="P"]
    if(!length(P_sequence)) P_sequence <- 0
    if(tail(S_sequence,1)==5 & tail(P_sequence,1)!=5) out <- "P"
}else{out <- "S"}
cat(out)
```
Measures the opponent stick sharpness: blocks when sharp, take time to sharpen otherwise. When own sharpness reaches 5, poke until sharpness is gone.
[Answer]
# Prison Rules, Haskell
Cavewoman think caveman and other caveman should talk, share stick. But, hey ho, if must fight, fight prison rules. Find boss and attack.
ViceLeader Alpha Caveman now; that who caveman must fight. Other cavemen fight later. If my caveman lose, no worry; he too hairy anyway.
```
import System.Environment
-- Tell caveman next move
next move
    | end with sharp stick  = poke with (what have)
    | they no poky          = sharpen stick
    | me have sword         = poke with sword
    | soon them have sword  = try poke or sharpen
    | soon have own sword   = fear pokes
    | think them want sword = sharpen stick
    | getting bored now     = sharpen stick
    | otherwise             = block poky stick
-- How fancy techno computer program know?
    where
        end with sharp stick = pokiness my stick >= moves before fight boring
        they no poky  = pokiness their stick == 0
        me have sword = pokiness my stick >= 5
        soon "them" have sword = pokiness their stick == 4
        soon have "own" sword  = pokiness my stick == 4
        try poke or sharpen = if pokiness my stick > 0
                              then poke with stick
                              else sharpen stick
        fear pokes = count 2 (block poky stick) and (sharpen stick)
        think them want sword = pokiness their stick == 3
        getting bored now = those last 2 mine same
        what have
            | me have sword = sword
            | otherwise     = stick
-- Rest not for caveman - only techno computer
        moves before time up = time - (length . fst $ move)
        and   = my
        mine  = my
        my    = fst move
        their = snd move
        before = "before"
        bored  = "bored"
        boring = "boring"
        have   = "have"
        no     = "no"
        now    = "now"
        own    = "own"
        pokes  = "pokes"
        same   = "same"
        sharp  = "sharp"
        them   = "them"
        want   = "want"
fight = 100
main = do
    movesHistoryEtc <- getArgs
    putStrLn . next . basedOn $ movesHistoryEtc
basedOn = movesOfEachCaveman . history
history []    = ""
history (h:_) = h
movesOfEachCaveman "" = ("", "")
movesOfEachCaveman h  = (\(a, b) -> (a, tail b)) . span (/= ',') $ h
sharpened = 'S'
poked     = 'P'
blocked   = 'B'
times m = length . filter (== m)
with  = "WITH"
poky  = "POKY"
sword = "SWORD"
stick = "STICK"
sharpen stick    = "SHARPEN " ++ stick
block poky stick = "BLOCK " ++ poky ++ " " ++ stick
poke with stick  = "POKE " ++ with ++ " " ++ stick
pokiness stick is = foldl countPokiness 0 stick
countPokiness pokyPoints 'P'
    | pokyPoints > 0         = pokyPoints - 1
    | otherwise              = 0
countPokiness pokyPoints 'S' = pokyPoints + 1
countPokiness pokyPoints  _  = pokyPoints
allLast n x xs = all (== x) $ take n . reverse $ xs
those previous n moves same = ((length moves) >= n)
                           && (allLast n (last moves) moves)
count n firstMoves moveHistory lastMove = if allLast n fm moveHistory
                                          then lastMove
                                          else firstMoves
    where fm = head firstMoves
```
Written in Haskell (go functional programming!), so save as *prisonrules.hs*, then compile with:
```
ghc prisonrules.hs
```
And run as:
```
prisonrules [history]
```
[Answer]
# Deep Thoughts, C
Caveman code. Caveman think. Caveman do.
```
// DeepThoughts.c
#include <stdio.h>  // Me need for plan
#include <string.h> // Me need for memory
// Me count sharps. If me still here, pokes no work
int is_pointy(char *past){
    int pointy = 0;     // Stick dull
    while(*past){
        switch(*past ++){
            case 'S': pointy ++; break;
            case 'P': if(pointy > 0) pointy --;
        }
    }
    return pointy;
}
// Me brain
int main(int argc, char *argv[]){
    int me_pointy = 0;  // Is 0, stick dull. Is 5, has sword
    int you_pointy = 0; // Same to you
    int me_last;        // Me last plan
    int you_last;       // Same to you
    char *you;          // You past
    int when;           // Time
    int me_plan;        // Me deep thought
    // Me remember
    if(argc > 1){
        you = strchr(argv[1], ',');     // Me find you past in me arg
        *you ++ = 0;
        when = strlen(argv[1]);         // Time is passing
        me_pointy = is_pointy(argv[1]); // Me look at me past
        you_pointy = is_pointy(you);    // Same to you
        me_last = argv[1][when - 1];    // Why me do that?
        you_last = you[when - 1];       // Same to you
    }
    // Me has deep thoughts. Me make plan
    if(me_pointy >= 5) me_plan = 'P';       // Me has sword
    else if(you_pointy == 0) me_plan = 'S'; // Me safe. You stick dull
    else if(when == 1) me_plan = 'P';       // Me shoot first (more thought)
    else if(me_pointy == 1 && when < 42) me_plan = 'B';  // Me try for sharper (deeper thought)
    else if(me_pointy > 0) me_plan = 'P';   // Me stick not dull
    else if(me_last == 'P') me_plan = 'B';  // Me in trouble
    else me_plan = 'S';                     // Me cross toes
    // Me do plan
    putchar(me_plan);
    return 0;
}
```
Me do testing. More thoughts better.
[Answer]
I call him JavaMan
```
compile: javac JavaMan.java
run: java JavaMan SPB,SBB
```
note: I don't intend to play code golf.. but if you are a golfer and the spaces / extra lines make your eyes bleed.. feel free to change it
```
public class JavaMan
{
    public static void main(String[] args)
    {
        // input: SPB,SBB
        // me, enemy
        // S: sharpen, P: poke, B: block
        if (args.length == 0)
        {
            System.out.println("S");
        }
        else
        {
            String[] states = args[0].split(",");
            Player me = new Player(states[0].toCharArray());
            Player enemy = new Player(states[1].toCharArray());  //fixed thanks to Roy van Rijn
            if (me.hasSword())
            {
                System.out.println("P");
            }
            else if (!enemy.canPoke())
            {
                if (me.canPoke() && (Math.random() * 95) < states[0].length())
                {
                    System.out.println("P");
                }
                else
                {
                    System.out.println("S");
                }
            }
            else if (enemy.hasSword())
            {
                if (me.canPoke())
                {
                    System.out.println("P");
                }
                else
                {
                    System.out.println("S");
                }
            }
            else if (enemy.canPoke())
            {
                if (me.canPoke())
                {
                    if ((Math.random() * 95) < states[0].length())
                    {
                        System.out.println("P");
                    }
                    else
                    {
                        System.out.println("B");
                    }
                }
                else
                {
                    if ((Math.random() * 95) < states[0].length())
                    {
                        System.out.println("S");
                    }
                    else
                    {
                        System.out.println("B");
                    }
                }
            }
            else
            {
                System.out.println("S");
            }
        }
    }
}
class Player
{
    int sharpLevel;
    public Player(char[] state)
    {
        sharpLevel = 0;
        for (char c : state)
        {
            switch (c)
            {
            case 'S':
                sharpLevel++;
                break;
            case 'P':
                sharpLevel--;
                break;
            case 'B':
                break;
            default:
                System.out.println(c);
            }
        }
    }
    public boolean hasSword()
    {
        return sharpLevel > 4;
    }
    public boolean canPoke()
    {
        return sharpLevel > 0;
    }
}
```
[Answer]
# Nigel
Nigel is a patient, defensive old caveman who would rather be tactical than go all out on the attack.
It's a PHP script, call with `php nigel.php`
```
<?php
// Seed the random number generator
srand(time());
// Simple function output chosen move
function move($m)
{
    echo $m;
    echo "\n";
    exit;
}
// Make stick sharp if first move
if (sizeof($argv) == 1)
    move("S");
// Grab the list of moves
$moves = explode(",", $argv[1]);    
$mySharpness = 0;
$opSharpness = 0;
// Loop through all previous moves and calculate sharpness
for ($i=0; $i<strlen($moves[0]); $i++)
{
    $myMove = substr ($moves[0], $i, 1);
    $opMove = substr ($moves[1], $i, 1);
    if ($myMove == "S")     $mySharpness++;
    if ($opMove == "S")     $opSharpness++; 
    if ($myMove == "P" && $mySharpness > 0)     $mySharpness--;
    if ($opMove == "P" && $opSharpness > 0)     $opSharpness--;     
}
// We somehow have a sword.. ATTACK!
if ($mySharpness > 4)
    move("P");
    
// Opponent is blunt, guarenteed upgrade!
if ($opSharpness < 1)
    move("S");          
// If we're sharp, either block or poke, unless OP is near a sword
if ($mySharpness > 0)
{
    // Oppenent is halfway to a sword.. ATTACK!
    if ($opSharpness > 2)
        move("P");  
        
    if (rand(0,1) == 0)     move("P");
    else                    move("B");
}
// If we're blunt, either sharpen or block
else
{
    if (rand(0,1) == 0)     move("S");
    else                    move("B");  
}
?>
```
[Answer]
## Aichmophobic - Lua
He'll occasionally poke you, but only until the some stick gets too sharp. When this happens, he'll panic and curl into fetal position.
```
if arg[1] == nil then
  response = "S"
elseif not arg[1]:match('SSSSS') == nil then
  --PANIC
  response = "B"
else  
  --Minds his own business and goes where he pleases
  math.randomseed(os.time())
  local rand = math.random();
  response = rand > 0.6 and "P" or "S"
end
print(response)
```
Run it with:
`lua aichmophobic.lua`
[Answer]
## Bob Caves
Bob Caves is one of the most clever guys in his cave. He has learned to count with one hand (the other is occupied in holding his stick). He has known of this Stone Age Olympics and wanted to participate.
His main strategy is block and sharpen his stick until he has a nice sharpy stick or the other caveman has a sharpy one too. In this case Bob Caves tries to poke him!
```
import java.util.Random;
public class BobCaves {
    public static void main(String[] args) {
        int mySharpness = 0;
    int otherSharpness = 0;
    //Boc counts
    if (args.length > 0) {
        String[] ss = args[0].split(",");
        mySharpness = howSpiky(ss[0]);
        otherSharpness = howSpiky(ss[1]);
    }
    // Bob thinks!
    Random rn = new Random();
    if (mySharpness == 0 && otherSharpness == 0){
        System.out.println( "S");
    }
    if (otherSharpness == 0 && mySharpness < 5 && mySharpness > 0){
        if (rn.nextBoolean()){
            System.out.println("P");
        } else {
            System.out.println("S");
        }
    } 
    if (mySharpness >= 5 || (otherSharpness >= 2 && mySharpness > 0)) {
        System.out.println("P");
    }
    if (rn.nextInt(5) > 3) {
        System.out.println("S");
    } 
    System.out.println("B");
    }
    private static int howSpiky(String s1) {
        int count = 0;
        char[] c1 = s1.toCharArray();
        for (int i = 0; i < c1.length; i++) {
        if (c1[i] == 'S') {
                count++;
            } else if (c1[i] == 'P'){
                count --;
            }
        }
        return count;
    }
}
```
Compile with `javac BobCaves.java` and run with `java BobCaves`
Edit: Bob now counts when there is any block! (thanks to [Mikey Mouse](https://codegolf.stackexchange.com/users/23447/mikey-mouse)). Also he will sharp his stick when the other caveman stick is blunt.
Edit 2: Improved count method (thanks again to Mikey).
Edit 3: Making Bob slightly more aggressive.
[Answer]
## Gruntt
Gruntt is defensive. Gruntt analyzes other cavemen moves to know how to poke them. Then he pokes them right in the eye. Gruntt is not a nice caveman.
```
public class Gruntt {
public static void main(String[] args) {
    System.out.println(whatToDo(args));
}
private static String whatToDo(String[] args){
    int mySharpness = 0;
    int otherSharpness = 0;
    if (args.length > 0) {
        String[] ss = args[0].split(",");
        mySharpness = howSpiky(ss[0]);
        otherSharpness = howSpiky(ss[1]);
    } else {
        return "S";
    }
    if (mySharpness >= 5){
        return "P";
    }
    String res = wowoo(args[0].split(",")[1]);
    if ("P".equals(res) && mySharpness > 0) {
        return "P";
    } else if ("P".equals(res) && mySharpness == 0) {
        return "S";
    } else if ("S".equals(res) && !args[0].split(",")[0].endsWith("S")) {
        return "S";
    }
    if (otherSharpness == 4 && !args[0].split(",")[0].endsWith("P")){
        return "P";
    }
    if (otherSharpness == 0){
        return "S";
    }
    return "B";
}
private static int howSpiky(String s1) {
    int count = 0;
    char[] c1 = s1.toCharArray();
    for (int i = 0; i < c1.length; i++) {
    if (c1[i] == 'S') {
            count++;
        } else if (c1[i] == 'P'){
            count --;
        }
    }
    return count;
}
private static String wowoo(String s){
    String s1 = "";
    String s2 = "";
    if (s.length() >= 4){
        s1 = s.substring(s.length() - 4);
    }
    if (s.length() >= 3){
        s2 = s.substring(s.length() - 3);
    }
    if ("SPSP".equals(s1)){
        return "P";
    } else if ("SSS".equals(s2)){
        return "P";
    } else if ("BBBB".equals(s1)){
        return "S";
    } else if ("SBSB".equals(s1)){
        return "P";
    }
    return null;
}
}
```
Compile with `javac Gruntt.java` and run with `java Gruntt`
[Answer]
## Is it a bird? Is it a plane? It's RegExMan!
He tries to analyze your super-boring sequences with his special primeval RegEx-power!
```
#!/usr/bin/env python
import sys, re
def whatAmIDoing(opnHist, meSharp, opnSharp) :
    match = re.search(r"([PSB]{3,})\1$", opnHist)    ### Super RegEx ftw!
    if meSharp >= 5 :
        return "P"
    if opnSharp == 4 and meSharp > 0 :
        return "P"
    if match :
        opnStrat = match.group()
        if opnStrat[0] == "S" :
            if meSharp > 0 :
                return "P"
            else :
                return "S"
        elif opnStrat[0] == "B" :
            return "S"
    if opnSharp <= 0 :
        return "S"
    return "B"
try :
    hist = sys.argv[1].split(",")
    sharp = map(lambda h : h.count("S") - h.count("P"), hist)
    answer = whatAmIDoing(hist[1], *sharp)
except Exception :
    answer = "S"
finally :
    print(answer)
```
---
Written in Python 2.7, run with `python RegExMan.py [history]`
[Answer]
# Sicillian
But it's so simple! All I have to do is divine from what I know of other caveman: is he the sort of caveman who would block, sharpen, or poke? Now, a clever caveman would poke or block, because he would know that only a great fool would sharpen and expose himself to attack. I am not a great fool, so I can clearly not sharpen. But other caveman must know I am not a great fool, and would have counted on it, so I can clearly not poke or block!
Run with:
```
javac Sicillian.java
java Sicillian
```
Code:
```
public class Sicillian {
    public static void main(String[] args) {
        if (args.length == 0) System.out.println("S");
        else {
            //get and analyze history
            String[] history = args[0].split(",");
            Caveman vizzini = new Caveman(history[0].toCharArray());
            Caveman fool = new Caveman(history[1].toCharArray());
            Think divine = new Think(history[0].toCharArray(),history[1].toCharArray());
            //The Sicillian always thinks and makes a logical decision before acting...
            char onlyAFool = divine.clearly(vizzini.getSharpness(),fool.getSharpness());
            //Never go in against a Sicillian when death is on the line!
            if(onlyAFool == 'S') {
                if(!vizzini.weaponless()) poke();
                else sharpen();
            }
            else if(onlyAFool == 'P') {
                if(vizzini.hasSword()) poke();
                else block();
            }
            else if(onlyAFool == 'B') sharpen();
            else {          // Inconceivable!
                //if he's a sharpener, poke him where it hurts!
                if(fool.isSharpener()) {
                    if(vizzini.getSharpness() >= 2) poke();  //don't ever go weaponless, else you give him the advantage
                    else sharpen();
                }               
                //if he's a blocker, get sword and break through his defense
                else if(fool.isDefensive()) {
                    if(vizzini.hasSword()) poke();
                    else sharpen();
                }
                // fool doesn't have a disposition to do anything in particular
                else {
                    //he could be sharpening and blocking to get a sword in which case his sharpness will be higher
                    //or a random, which will average a lower sharpness
                    if (fool.getSharpness() <= 2) { //assume random
                        if(vizzini.hasSword()) poke();
                        else if(fool.weaponless()) sharpen();
                        else block();
                    }
                    else {
                        if(vizzini.hasSword()) poke();
                        else if(vizzini.getSharpness() > fool.getSharpness()) sharpen();    //we can win race to sword
                        else if(vizzini.getSharpness() >= 2 || (!vizzini.weaponless() && fool.onEdge())) poke();
                        else sharpen();
                    }
                }
            }           
        }
    }   //end of main
    private static void poke() {
        System.out.println("P");
    }
    private static void block() {
        System.out.println("B");
    }
    private static void sharpen() {
        System.out.println("S");
    }
}
class Think {
    private char[][] cleverman = new char[6][6];    //tracks what the enemy does in a particular situation 
    private int mySharpness;
    private int enemySharpness;
    public Think(char[] myAction, char[] enemyAction) {
        //init variables
        mySharpness = 0;
        enemySharpness = 0;
        for(int i = 0; i < myAction.length; i++) {
            //remember what enemy did last time
            cleverman[mySharpness][enemySharpness] = enemyAction[i];
            //System.out.println("When I was at ("+mySharpness+") and he was at ("+enemySharpness+") he did ("+enemyAction[i]+")");
            //calculate my sharpness
            if(myAction[i] == 'S') mySharpness++;
            else if(myAction[i] == 'P') mySharpness--;
            if(mySharpness < 0) mySharpness = 0; //ensure multiple pokes don't create a negative sharpness
            //calculate my enemy's sharpness
            if(enemyAction[i] == 'S') enemySharpness++;
            else if(enemyAction[i] == 'P') enemySharpness--;
            if(enemySharpness < 0) enemySharpness = 0; //ensure multiple pokes don't create a negative sharpness
        }   
    }
    public char clearly(int myAction, int enemyAction) {
        if(myAction > 5) myAction = 5;
        if(enemyAction > 5) enemyAction = 5;
        return cleverman[myAction][enemyAction];
    }
}
class Caveman {
    private int sharpness;
    private int disposition;    //Finite State Machine: how inclined the caveman is toward blocking (0) or sharpening (4)
    public Caveman(char[] action) {
        sharpness = 0;
        disposition = 1;        //assume a slightly defensive disposition
        for (int i = 0; i < action.length; i++) {
            if(action[i] == 'S') {
                sharpness++;
                disposition++;
            }
            else if(action[i] == 'P') sharpness--;
            else disposition--;                     //blocking
            if(sharpness < 0) sharpness = 0; //ensure multiple pokes don't create a negative sharpness
            if(disposition > 4) disposition = 4;
            else if(disposition < 0) disposition = 0;
        }
    }
    public int getSharpness() {
        return sharpness;
    }
    public boolean weaponless() {
        return sharpness == 0;
    }
    public boolean hasSword() {
        return sharpness >= 5;
    }
    public boolean onEdge() {
        return sharpness == 4;
    }
    public boolean isDefensive() {
        return disposition == 0;
    }
    public boolean isSharpener() {
        return disposition == 4;
    }
    public int getDisposition() {
        return disposition;
    }
}
```
[Answer]
# bash-magnon
Bash-magnons were robustly built and powerful. The body was generally heavy and solid with a strong musculature. The forehead was fairly straight rather than sloping like in Neanderthals, and with only slight browridges. The face was short and wide. The chin was prominent. The brain capacity was about 1,600 cubic centimetres (98 cu in), larger than the average for modern humans. However, recent research suggests that the physical dimensions of so-called "Bash-Magnon" are not sufficiently different from modern humans to warrant a separate designation.
*Me have a brain, me remember.* 
This is a self executable `./bash-magnon.sh` 
```
#!/bin/bash
function min () {
 [[ $1 -gt $2 ]] && echo $2 || echo $1
}
function max () {
[[ ${1%% *} -gt ${2%% *} ]] && echo $1 || echo $2
}
declare -A brain
declare -i C S P B me he
he=0
me=0
C=0
S=0; B=0; P=0
left=${1%%,*}
right=${1##*,}
while  : 
do
    [[ "${right:$C:1}" ]] && brain[$he$me]=${right:$C:1}
    case "${left:$C:1}${right:$C:1}" in
    BB) true;;
    BP) ((he--));;
    BS) ((he++));;
    PP) ((he--)); ((me--));;
    PB) ((me--));;
    PS|SP) exit;;
    SB) ((me++));;
    SS) ((me++)); ((he++));;
    "") break;;
    esac
    me=$(max 0 $me)
    me=$(min 9 $me)
    he=$(max 0 $he)
    he=$(min 9 $he)
    ((C++))
done
[[ $me$he =  *[5-9] ]] && ((P+=2))
[[ $me$he =  [5-9]* ]] && ((P+=2))
[[ $me$he =  [1-9]0 ]] && ((P+=2))
[[ $me$he =  00 ]] && ((S+=2))
[[ $me$he =  [1-4]4 ]] && ((P+=2))
[[ $me$he =  0[1-4] ]] && ((S+=1))
[[ $me$he =  0* ]] && ((B+=1))
case "${brain["$he$me"]}" in 
S) ((P+=2));;
B) ((S+=2));;
P) ((B+=2));;
*) ((B++));;
esac
set $(max "$B B" "$(max "$P P" "$S S")" )
echo $2
```
[Answer]
# PokeBackBot
Simply adapted from PokeBot:
```
puts 'SBPB'[(ARGV.shift || ',').split(',', 2)[0].length % 4]
```
Run with `ruby pokebackbot.rb`.
This uses the next simplest strategy, and blocks "patiently" for one round before attacking.
[Answer]
**Swordmaster**
Written in Python 3.4 (works with Python 3.x)
Tries to get a sword as fast as possible but attacks if it has a chance to hit him (sharpness > 0) and enemy could hurt it too (enemy sharpness > 0).  
Blocks only if has no sharpness and enemy could attack.
Start with:  
```
python3 swordmaster.py MOVES
```
(assumed you save it as `swordmaster.py`)
Quick and ugly code:
```
import sys, random
dg = False
if len(sys.argv) > 1:
    ow,ot = sys.argv[1].split(',')
else:
    ow = ot = ""
def gs(m):
    ow = 0
    ot = 0
    i = 0
    ms = m[0]
    mo = m[1]
    for _ in mo:
        if ms[i] == 'S':
            ow += 1
        elif ms[i] == 'P' and mo[i] in ['P','B']:
            ow -= 1
        if mo[i] == 'S':
            ot += 1
        elif mo[i] == 'P' and ms[i] in ['P','B']:
            ot -= 1
        if dg:
            print("Own: {}, Other: {}".format(ow,ot))
        i += 1
    return [ow, ot]
def sm(sh):
    if (type(sh) != list) and dg:
        raise ValueError('Invalid sh type.')
    ow, ot = sh
    if ow >= 5:
        ret = 'P'
    elif ow >= 0 and ot == 0:
        ret = 'S'
    elif ow > 0 and ot > 0:
        ret = 'P'
    elif ow == 0 and ot > 0:
        ret = 'B'
    else:
        ret = random.choice(['S','B','P']) #Should not happen
    return ret
if __name__ == "__main__":
    print(sm(gs([ow,ot])))
```
(Set `dg` to `True` to enable debug messages)
[Answer]
# FoolMeOnce.py
Save each player's moves for the first duel, then replay with the exact same moves. If the enemy's algorithm is nonrandom, we can predict the same outcome and strike only when we know we'll win.
```
import os
import sys
import random
def getLastMove(player, turn):
    path = 'players/FoolMeOnce/'+player+str(turn)+'.txt'
    if os.path.isfile(path):
        with open(path, 'r') as f:
            return f.read()
    else:
        return 'nofile'
def sharpness(history):
    sharpness = 0
    for c in history:
        if c is 'S':
            sharpness+=1
        elif c is 'P' and sharpness > 0:
            sharpness-=1
    return sharpness
def takeTurn(choice, history, turn):
    print(choice)
    with open('players/FoolMeOnce/me'+str(turn)+'.txt', 'w') as f:
        f.write(choice)
    #also record their last choice
    choice = history[-1]
    with open('players/FoolMeOnce/them'+str(turn)+'.txt', 'w') as f:
        f.write(choice)
#if its the first turn, always sharpen
if(len(sys.argv) == 1):
    print('S')
else:
    history = sys.argv[1].split(',')
    meSharp = sharpness(history[0])
    themSharp = sharpness(history[1])
    turn = len(history[0])
    #read opponents move and our move for this turn from last duel
    them = getLastMove('them', turn);
    me = getLastMove('me', turn);
    #if this is first duel, fool me once
    if(them is 'nofile' or me is 'nofile'):
        if themSharp is 0 and meSharp >0:
            takeTurn(random.SystemRandom().choice('PS'), history, turn)
        else:
            takeTurn('B', history, turn)
    #if we could have played a winning move, do it. otherwise do what we did last time
    elif(them is 'S' and meSharp > 0):
        takeTurn('P', history, turn)
    else:
        takeTurn(me, history, turn)
```
Written in python 3, so most likely you'll have to use **python3 FoolMeOnce.py**
On the first round, I'm not sure if we get an empty string or just a comma, so there may be some tweaks needed.
]