R/PDstrategies.R

Defines functions strat1 strat3 strat2 strat4 getrich meineStrat2 phases stratego Alphabet3 squishy.the.octopus nashtag1 pudb.strat2 nottitfortat prof.strat schachmatt_tournament phases Globaler.Tit.4.Tat viva.PD.Strategy into.spaaaace screams.in.space nice.tit.for.tat tft.forgive.fast.2 counter.nice.tit.for.tat a.ntft.1 mean.tit.for.tat tft.forgive.slow counter.tft.forgive.slow forgive.slower tft.forgive.slow.killer Rainbow.Unicorns.one eat.mindfreaks.2 regenbogen Rainbow.Unicorns.one.killer seda.strat2 destab.strat2.0 counter.strat2 strat2.killer antistrat2 answer.strat3 ta.daaa destab.ta.daaa counter.ta.daaa tatada a.tadaaa.1 TikTak1 eat.unicorns.65 TokTok a.TikTak1 Antitiktak1 Antitiktak1.simplified Antitiktak1.improved the.undertaker.1 counter.the.undertaker.1 overtaker answer.strat2 probably.nice.Base probably.not.that.nice eat.unicorns.50 dont.mind answer.strat1 net.nice0 net.nice1 net.nice.minus1 net.nice.start1 a.net.nice0 antiprof2 ron TikTak2 a.tiktak.2 strat.fot.tik.tak Antitiktak2 probably.nice.High.err probably.not.so.nice the.undertaker.2 counter.the.undertaker.2 answer.to.undertaker.2 overtaker.High.err eat.unicorns.48 dont.mind.High.err Rainbow.Unicorns.two counter.rainbow.unicorns.two Rainbow.Unicorns.two.killer tft.forgive.fast harry counter.tft.forgive.fast dont.forgive tft.forgive.fast.killer da.taaa counter.da.taaa a.td.2 da.taaa.counter nice.tit.for.tat.High.err counter.nice.tit.for.tat.2 antistrat2.High.err el.majestro.incredibile bot.GraDOS_Ghost.2017 bot.Legend.2017 bot.Amateur.2017 bot.Semi_Pro.2017 bot.Beginner.2017 bot.Expert.2017 moneymaker.2017 waning.generosity.2017 slowpoke categorizer.2017 scorer.2017 three.of.five.2017 talion.2017 tft.2forgive tft.2forgive.counter compare.exploration grim.trigger counter.grim.trigger generous.tit.for.tat contrite.tit.for.tat.Axelrod contrite.tit.for.tat counter.contrite.tit.for.tat pavlov

Documented in Alphabet3 a.net.nice0 answer.strat1 answer.strat2 answer.strat3 answer.to.undertaker.2 a.ntft.1 antiprof2 antistrat2 antistrat2.High.err Antitiktak1 Antitiktak1.improved Antitiktak1.simplified Antitiktak2 a.tadaaa.1 a.td.2 a.TikTak1 a.tiktak.2 compare.exploration counter.da.taaa counter.nice.tit.for.tat counter.nice.tit.for.tat.2 counter.rainbow.unicorns.two counter.strat2 counter.ta.daaa counter.tft.forgive.fast counter.tft.forgive.slow counter.the.undertaker.1 counter.the.undertaker.2 da.taaa da.taaa.counter destab.strat2.0 destab.ta.daaa dont.forgive dont.mind dont.mind.High.err eat.mindfreaks.2 eat.unicorns.48 eat.unicorns.50 eat.unicorns.65 el.majestro.incredibile forgive.slower getrich Globaler.Tit.4.Tat harry into.spaaaace mean.tit.for.tat meineStrat2 nashtag1 net.nice0 net.nice1 net.nice.minus1 net.nice.start1 nice.tit.for.tat nice.tit.for.tat.High.err nottitfortat overtaker overtaker.High.err phases probably.nice.Base probably.nice.High.err probably.not.so.nice probably.not.that.nice prof.strat pudb.strat2 Rainbow.Unicorns.one Rainbow.Unicorns.one.killer Rainbow.Unicorns.two Rainbow.Unicorns.two.killer regenbogen ron schachmatt_tournament screams.in.space seda.strat2 squishy.the.octopus strat1 strat2 strat2.killer strat3 strat4 stratego strat.fot.tik.tak ta.daaa tatada tft.forgive.fast tft.forgive.fast.2 tft.forgive.fast.killer tft.forgive.slow tft.forgive.slow.killer the.undertaker.1 the.undertaker.2 TikTak1 TikTak2 TokTok viva.PD.Strategy

#' A student strategy
#'
#' @export
strat1 = function(obs,i,t,otherC,mylastobserved,...) {

  # Cooperate in the first period
  if (t==1){
    # we set otherC to 1, meaning we give our opponent initial credit
    return(list(a="C",otherC=1,mylastobserved="A"))
  }

  j=3-i

  # Cooperate in the second period
  if (t==2){
    # we remember whether Villain played C and count it
    if(obs$a[[j]]=="C"){
      mylastobserved=obs$a[[i]]
      return(nlist(a="C",otherC=otherC+1,mylastobserved))
    }
    # we remember our last observed action
    mylastobserved=obs$a[[i]]
    return(nlist(a="C",otherC,mylastobserved))
  }


  # in the next eight rounds, do what Villain did the most.
  if(t>2 && t<11){
    # we remember Villains last action
    if(obs$a[[j]]=="C"){
      otherC= otherC + 1
    }
    # we remember our last action
    mylastobserved=obs$a[[i]]
    # if we mostly observed "D", we play "D".
    if(otherC<0.5*t){
      return(nlist(a="D",otherC,mylastobserved))
    }
    # else we play "C"
    return(nlist(a="C",otherC,mylastobserved))
  }

  # after ten rounds, we make a case-by-case-analysis
  if(t>=11){
    # we remember Villains last action
    if(obs$a[[j]]=="C"){
      otherC= otherC + 1
    }
    # we remember our last action
    mylastobserved=obs$a[[i]]
    # if less than half of our observations are "C", we play "D"
    if(otherC<0.5*t){
      return(nlist(a="D",otherC,mylastobserved))
    }
    # if Villain was nice, we play "C" in most cases but try to to play "D" some of the time too
    if(otherC>=0.5*t && otherC<=0.75*t){
      # if my last observed action was "D", we cooperate
      if(mylastobserved=="D"){
        return(nlist(a="C",otherC,mylastobserved))
      }
      # else we cooperate with 85% probability
      if(mylastobserved=="C"){
        do.cooperate=(runif(1)<0.85)
        if(do.cooperate){
          return(nlist(a="C",otherC,mylastobserved))
        }
        else{
          return(nlist(a="D",otherC,mylastobserved))
        }
      }
    }
    # If Villain is too nice, we try to exploit him by deflecting with a high probability
    if(otherC>0.75*t){
      # if my last observed action was "D", we cooperate
      if(mylastobserved=="D"){
        return(nlist(a="C",otherC,mylastobserved))
      }
      # else we cooperate with 67% probability
      if(mylastobserved=="C"){
        do.cooperate=(runif(1)<0.67)
        if(do.cooperate){
          return(nlist(a="C",otherC,mylastobserved))
        }
        else{
          return(nlist(a="D",otherC,mylastobserved))
        }
      }
    }
  }

}

#' A student strategy
#'
#' @export
strat3 = function(obs,i,t,counter=0,standi="G",obsl=c("Start"),obslown=c("Start"),ansl=c("Start"),...) {

  # Set parameters
  er=0.25;
  a=1;
  # other player
  j = 3-i

  # Cooperate in the first period, then decide among the answers what strategy to play  for the next 5 rounds  (depending on the expectet length and observation error of the game)

  # Save observations of every round
  if (t>=1){
    obsl[t]=obs$a[j];
    obslown[t]=obs$a[i];
  }
  # Opening strategy
  if (t==1){
    ansl[t+1]="C";
    return(list(a="C",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))
  }

  if (t>=2){

    if (counter>=2){
      counter=counter-1;
    }
    if (counter==1){
      counter=counter-1;
      ansl[t+1]="D";
      return(list(a="D",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))
    }
    if (standi=="S"){
      a=sum(ifelse(obsl=="D",1,0))/(length(obsl)-1);
      if (a<=0.4*(1+(2/t))){
        standi="G1"
      }else{
        standi="S";
      }
    }
    if (standi=="G1"){
      if(a<=0.4*(1+(2/t))){
        standi ="G1";
      }else{
        if(obsl[t]=="D"){
          standi="S";
        }else{
          standi="G"
        }
      }
    }
    if (standi=="G"){
      if(obsl[t]=="C"|| (obsl[t]=="D" & obslown[t-1]=="D") || (obsl[t]=="D" & obslown[t]=="D") ){
        standi="G";
      }else{
        standi="G1";
      }
    }

  }

  # The returns for the different states
  if (standi=="G"){
    ansl[t+1]="C";
    return(list(a="C",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))
  }
  if (standi=="G1"){

    r=runif(1)
    if(r<(1-(er/2))){
      ansl[t+1]="C";
      return(list(a="C",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))
    }
    ansl[t+1]="D";
    return(list(a="D",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))
  }
  if (standi=="S"){
    if (counter==0){
      counter=8;
    }
    ansl[t+1]="D";
    return(list(a="D",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))
  }



  # never return nothing (to prevent failure)
  ansl[t]="C";
  return(list(a="C",counter=counter,standi=standi,obsl=obsl,obslown=obslown,ansl=ansl))

}

#' A student strategy
#'
#' @export
strat2 = function(obs,i,t,nr.df=0,last.his=NULL,count=0,...){

  j = 3-i

  # Cooperate in the first period
  if (t==1){
    return(list(a="C", nr.df=nr.df,last.his=last.his,count=count))
  }

  last.his[1]=last.his[2] # store the previous last action from other player in last.his[1]
  last.his[2]=obs$a[j] # store the last action from other player in last.his[2]

  # reset the counter and defect number from other player
  if(count==0){
    nr.df<-0
  }

  # rise the counter of receiving "defect"
  if(obs$a[j]=="D")
    nr.df=nr.df +1

  count=count+1

  # reset the counter every 6 steps
  if(count>=7){
    count<-0
  }

  # because of noise we try to be nice
  if(nr.df<=1){ # 0,1
    return(list(a="C",nr.df=nr.df, last.his=last.his,count=count))
  }

  # play the last move from other player
  if (nr.df==2) # 2
    return(list(a=obs$a[j],nr.df=nr.df,last.his=last.his,count=count))

  # predicting "always.defect" type from other player, so we defect
  if (nr.df==6){ # 6
    return(list(a="D",nr.df=nr.df,last.his=last.his,count=count))
  }

  # only defect if we receive 2 times in a row defect, otherwise cooperate
  if (nr.df>=3){ #  3,4,5
    if(last.his[1]=="D" && obs$a[j]=="D"){
      return(list(a="D",nr.df=nr.df, last.his=last.his,count=count))
    }
    else return(list(a="C",nr.df=nr.df, last.his=last.his,count=count))
  }
}

#' A student strategy
#'
#' @export
strat4 = function(obs,i,t,itsyou=0,still.defect=3,still.cooperate=3,haveto.cooperate=0,haveto.defect=3,endto.cooperate=3,knowwho=0,...){
  debug.store("strat4",i,t)       # Store each call for each player
  debug.restore("strat4",i=1,t=7) # Restore call for player i in period t

  j = 3-i
  b = obs$a[j]

  if(t==1){
    return(list(a="C",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
  }

  if(itsyou==1){
    if(b=="D"){
      still.defect=still.defect-1
      if(b=="C"){
        still.defect=still.defect+1
        if(still.defect==4){
          still.defect=still.defect-1
        }
      }

      if(still.defect==0){
        itsyou=0
        return(list(a="D",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
      }
    }
    return(list(a="C",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
  }
  if(knowwho==3){
    itsyou=1
    return(list(a="C",itsyou=itsyou,still.defect=3,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
  }

  if(b=="C"){
    knowwho=knowwho+1
  }

  if(b=="D"){
    knowwho=0
  }


  if(endto.cooperate==0){
    return(list(a="D",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=0,knowwho=knowwho))
  }
  if(still.defect==0){
    if(haveto.defect==0){
      endto.cooperate=endto.cooperate-1

      return(list(a="C",itsyou=itsyou,still.defect=3,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
    }
    if(b=="C"){
      haveto.cooperate=haveto.cooperate+1
    }
    if(haveto.cooperate==2){
      do.cooperate=(runif(1)<0.85)
      if(do.cooperate){
        endto.cooperate=endto.cooperate-1
        return(list(a="C",itsyou=itsyou,still.defect=3,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
      } else {
        return(list(a="D",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
      }
    }
    haveto.defect=haveto.defect-1
    return(list(a="D",itsyou=itsyou,still.defect=0,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
  }

  if(still.cooperate==0){
    if(still.defect<2){
      still.defect=still.defect+1
    }
    return(list(a="C",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
  }

  if(b=="C"){
    still.cooperate=still.cooperate-1
    if(still.defect<2){
      still.defect=still.defect+1
    }
    return(list(a="C",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
  }

  if(b=="D"){
    still.defect=still.defect-1
    if(still.cooperate<2){
      still.cooperate=still.cooperate+1
    }
    do.defect=(runif(1)<0.85)
    if(do.defect){
      return(list(a="D",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
    } else{
      return(list(a="C",itsyou=itsyou,still.defect=still.defect,still.cooperate=still.cooperate,haveto.cooperate=haveto.cooperate,haveto.defect=haveto.defect,endto.cooperate=endto.cooperate,knowwho=knowwho))
    }
  }
}

#' A student strategy
#'
#' @export
getrich = function(obs,i,t,trueself=c(), obsself=c(),DforC=0,...) {



  #ERSTE RUNDE
  if (t==1){
    trueself[t]=1
    return(list(a="C",trueself=trueself,obsself=obsself,DforC=DforC))
  }

  j= 3-i


  #Beobachtung des anderen merken
  if(obs$a[i]=="C"){
    obsself[t-1]=1
  }
  else
    obsself[t-1]=0



  #Der andere hat KOOPERIERT, wir kooperieren grunds?tzlich auch
  if (obs$a[j]=="C") {
    trueself[t]=1
    DforC=0
    return(list(a="C",trueself=trueself,obsself=obsself,DforC=DforC))
  }

  #DforC zu hoch
  if (DforC>3){
    trueself[t]=0
    return(list(a="D",trueself=trueself,obsself=obsself,DforC=DforC))
  }


  #Der andere hat DEFLEKTIERT

  #Beobachtung: Wir hatten zuvor kooperiert
  if (t==2){
    trueself[t]=0
    return (list(a="D",trueself=trueself,obsself=obsself,DforC=DforC))
  }
  if (obsself[t-2]==1){ #Weniger Vertrauen in Mitspieler, deflektieren
    DforC=DforC+1
    trueself[t]=0
    return(list(a="D", trueself=trueself,obsself=obsself,DforC=DforC))
  }
  #Beobachtung:Wir hatten zuvor deflektiert

  if(trueself[t-2]==0){  #Tats?chlich deflektiert, Gegener auch deflektiert
    x=runif(1)


    if (x<0.9-DforC*0.2){ #Je nach Kooperationsstatus des Gegners ?fter wieder kooperieren
      trueself[t]=1
      return(list(a="C", trueself=trueself,obsself=obsself,DforC=DforC))
    }
    else{
      trueself[t]=0
      return(list(a="D", trueself=trueself,obsself=obsself,DforC=DforC))
    }
  }

  if (trueself[t-2]==1){  #Wir hatten eigentlich kooperiert, wurde aber falsch wahrgenommen: kooperieren
    trueself[t]=1
    return(list(a="C",trueself=trueself,obsself=obsself,DforC=DforC))
  }

  #SICHERHEITSOPTION
  trueself[t]= 1
  return(list(a="C",trueself=trueself,obsself=obsself,DforC=DforC))

}

#' A student strategy
#'
#' @export
meineStrat2 = function(obs,i,t, BeoGegner = 0, BeoSelbst = 0, HandlSelbst = 0 , FehlBeo = FALSE, ... ){

  # wie viele Runden sind wir "gutm?tig"?
  gutm = 8

  # j ist Spielerindex des Gegners
  j = 3-i

  #### in Runde 1 kooperieren wir immer
  if (t==1){
    HandlSelbst[t] = "C"
    FehlBeo[t] = FALSE
    return(list(a="C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo =FehlBeo))
  }

  ### Beginne ab Runde 2 die Beobachtungen zu dokumentieren und einige Variablen zu berechnen

  # BeoGegner ist die beobachtete Handlung aus Runde t-1 des Gegners
  # BeoSelbst ist die Beobachtung (des Gegners) der eigenen Handlung
  BeoGegner[t-1] = obs$a[j]
  BeoSelbst[t-1]=obs$a[i]

  # wie oft konnte ich eine Kooperation des Gegners beobachten?
  KoopBeo = length(BeoGegner[BeoGegner =="C"])

  # versuche die tats?chliche Anzahl der Kooperationen zu berechnen, indem die error.prob herausgerechnet wird
  # KoopTat soll die tats?chliche Zahl der Kooperationen des Gegners sein (Approximation, ist bei kleiner Rundenzahl mit Fehler behaftet)
  KoopTat = min((t-1), KoopBeo/0.75)

  # wir befinden uns in Runde [t], nimmt der Gegner in dieser Runde meine Kooperation aus der Vorrunde,
  # also aus [t-1] falsch wahr? T = ja, F = nein
  FehlBeo[t] = (BeoSelbst[t-1] != HandlSelbst[t-1])

  # in wie viel Prozent der Runden habe ich eine Defektion beobachtet?
  AntDefekBeo = (length(BeoGegner[BeoGegner=="D"])/ (t-1))

  # in wie viel Prozent der Runden hat Gegner tats?chlich defektiert? (Versuche  Beobachtungsfehler herauszurechnen)
  AntDefekTats = max(0, (AntDefekBeo - (KoopTat*0.25/(t-1))))

  # wie oft wurde von mir eine Defektion (durch den Gegner) beobachtet?
  DefSelbst = length(BeoSelbst[BeoSelbst=="D"])

  # in wie viel Prozent der Runden wurde von mir eine Defektion beobachtet?
  AntDefSelbst = DefSelbst/(t-1)

  # denken wir, dass der Gegner uns NICHT ausnutzt?
  # ja, wenn wir selbst ?fter defektieren als er, ja = TRUE
  GegnerNett = (AntDefSelbst*1.25 >= AntDefekTats)

  # in Runde 2- gutm
  if (t <= gutm){

    # wenn Gegner Fehlbeobachtung hatte und deswegen defektiert, kooperiere trotzdem
    if (FehlBeo[t-1] & BeoGegner[t-1]== "D"){
      HandlSelbst[t] = "C"
      return(list(a="C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo ))
    }

    # in diesen F?llen, hatten wir wahrscheinlich eine Fehlbeobachtungen und kooperieren deswegen
    else if ( t>2){
      if(BeoGegner[t-1] == "D" & BeoGegner[t-2] != "D"){
        HandlSelbst[t] = "C"
        return(list(a="C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo ))
      }
    }

    # sonst: handle wie Gegner in Runde zuvor
    else{
      HandlSelbst[t] = BeoGegner[t-1]
      return(list(a= BeoGegner[t-1], BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))
    }
  }

  ### ab jetzt (t > gutm) verwenden wir die erhobenen Daten und die berechneten Variablen um Gegner einzusch?tzen

  # in dieser Runde wollen wir Gegner "ausnutzten"
  else if(BeoSelbst[t-1] == "C" & BeoSelbst[t-2]== "C"  & BeoGegner[t-1]== "D" ){
    HandlSelbst[t] = "D"
    return(list(a=  "D", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))
  }

  else{
    # wenn Gegner kooperiert, kooperiere
    if(BeoGegner[t-1] == "C"){
      HandlSelbst[t] = "C"
      return(list(a="C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo= FehlBeo))
    }

    # Gegner hatte Fehlbeobachtung, kooperiere trotz seiner Defektion, wenn er nett ist
    else if(FehlBeo[t-1] & GegnerNett) {
      HandlSelbst[t] = "C"
      return(list(a="C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo= FehlBeo))
    }

    # wenn Gegner keine Fehlbeobachtung hatte (und trotzdem defektiert hat)
    else{

      # wenn wir Gegner als nett einsch?tzen und er in Runde [t-2] kooperiert hat, dann kooperiere
      # wir haben seine Defektion wahrscheinlich als falsch wahgenommen
      if( GegnerNett & BeoGegner[t-2] != "D"){
        HandlSelbst[t] = "C"
        return(list(a= "C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))
      }

      # wenn wir Gegner als NICHT nett einsch?tzen, nehmen wir seine Defektion wahrscheinlich nicht falsch wahr
      # handle wie er in der Vorrunde
      else if(!GegnerNett){

        # Ausnahme: wenn Gegnger in vorherigen beiden Runden kooperiert hat
        if(BeoGegner[t-2] == "C"& BeoGegner[t-3] == "C"){
          HandlSelbst[t] = "C"
          return(list(a="C", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))
        }
        else{
          HandlSelbst[t] = "D"
          return(list(a="D", BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))
        }
      }

      # sonst: handle wie Gegner in Vorrunde
      else{
        HandlSelbst[t] = BeoGegner[t-1]
        return(list(a= BeoGegner[t-1], BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))
      }
    }
  }
  # zur Sicherheit
  HandlSelbst[t] = BeoGegner[t-1]
  return(list(a= BeoGegner[t-1], BeoGegner = BeoGegner, BeoSelbst = BeoSelbst, HandlSelbst = HandlSelbst, FehlBeo = FehlBeo))

}

#' A student strategy
#'
#' @export
phases = function(obs,i,t,equal=TRUE,offender=FALSE,victim=FALSE,...){


  #j beschreibt Index des Gegners
  j=3-i


  # Kooperiere in der ersten Runde
  if(t==1)
    return(list(a="C",offender=offender,equal=equal,victim=victim))

  # Phase equal:
  if(equal){

    #Wir kooperieren wenn unsere beobachteten Handlungen ?bereinstimmen und bleiben in Phase equal.
    if(obs$a[[j]]==obs$a[[i]]){
      return(list(a="C",offender=offender,equal=equal,victim=victim))
    }

    #Spielt der Gegner eine einseitige Defektion, antworten wir mit einer Defektion und wechseln in Phase victim.
    else if(obs$a[[j]]=="D"){
      return(list(a="D",offender=FALSE,equal=FALSE,victim=TRUE))
    }

    #Spielen wir die einseitige Defektion, antworten wir mit einer Kooperation und welchseln in den Status offender.
    else if (obs$a[[i]]=="D"){
      return(list(a="C",victim=FALSE,equal=FALSE,offender=TRUE))
    }
  }

  #Phase victim: Wir defektieren solange bis unser Gegner Koopertiert.
  if(victim){

    # Defektiert der Gegner, defektieren wir zur?ck und bleiben in Phase Victim
    if(obs$a[[j]]=="D"){
      return(list(a="D",offender=offender,equal=equal,victim=victim))
    }

    # Koopertiert der Gegner, kooperieren wir zur?ck und wechseln in Phase equal.
    else{
      return(list(a="C",offender=FALSE,victim=FALSE,equal=TRUE))
    }
  }

  #Phase offender: Wir bleiben solange in dieser Phase und kooperieren, bis eine erfolgreiche Kooperation entsteht.
  if(offender){

    # ?nderung der Phase bei einvernehmlicher Kooperation, wechsel in Phase equal
    if(obs$a[[j]]=="C" && obs$a[[i]]=="C"){
      return(list(a="C",victim=FALSE,offender=FALSE,equal=TRUE))
    }
    # Kooperieren und in Phase bleiben
    else{
      return(list(a="C",offender=offender,equal=equal,victim=victim))
    }
  }

  #nicht notwendig
  else{
    return(list(a="C",offender=offender,equal=equal,victim=victim))
  }
}

#' A student strategy
#'
#' @export
stratego = function(obs,i,t,memoryI=0,memoryJ=0,...) {

  # j beschreibt Index des Gegners
  j=3-i

  # ab Runde 2 wird ein Ged?chtnis gebildet, wobei:
  # memoryI=Ged?chtnis mit meinen Spielz?gen
  # memoryJ=Ged?chtnis mit den Spielz?gen des Gegners
  if (t>1)
    memoryI[t-1]=obs$a[i]
  memoryJ[t-1]=obs$a[j]

  # Kooperiere in den ersten f?nf Runden
  if (t<=5) {
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
  }

  # W?hle in den Runden 6 bis 8 jeweils einen zuf?lligen Spielzug
  if (t>5 && t<=8) {
    a=sample(c("C","D"),1)
    return(list(a=a,memoryI=memoryI,memoryJ=memoryJ))
  }

  # Erzeuge zwei Kurzzeitged?chtnisse der letzten 4 bzw. 8 Runden
  shortmemory=memoryJ[(length(memoryJ)-3):length(memoryJ)]
  longmemory=memoryJ[(length(memoryJ)-7):length(memoryJ)]

  # Defektiere, wenn der Gegner in den letzten 8 Runden ebenfalls nur defektiert hat
  if(length(which(longmemory=="D"))==8) {
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ))
  }

  # Spiele abh?ngig vom Gegnerverhalten in den letzten 8 Runden
  if(length(which(longmemory=="C"))==4 && length(which(shortmemory=="C"))==2) {
    a=sample(c("C","D"),1)
    return(list(a=a,memoryI=memoryI,memoryJ=memoryJ)) # W?hle einen zuf?lligen Spielzug,
    # wenn er sowohl in den letzten 8 als auch in den letzten 4 Runden jeweils gleich oft kooperiert und defektiert hat
  }
  else if(length(which(longmemory=="C"))>=6 && length(which(shortmemory=="C"))==4) {
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ)) # Defektiere, wenn er in den letzten 4 Runden nur kooperiert hat
    # und gleichzeitig in den letzten 8 Runden mindestens 6 mal ebenfalls kooperiert hat
  }
  else {
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ)) # Kooperiere in allen anderen F?llen
  }
}

#' A student strategy
#'
#' @export
Alphabet3 = function(obs,i,t,memoryI=0, memoryJ=0,...) {

  library(StratTourn)

  #Der Gegner bekommt den Index j.
  j = 3-i

  # Ab Runde 2 wird das Ged?chtnis gebildet. In memoryI werden die eigenen Handlungen der vorherigen Runde gespeichert. In memoryJ die Handlungen der vorherigen Runde des Gegners.

  if (t>1){
    memoryI[t-1]=obs$a[i]
    memoryJ[t-1]=obs$a[j]
  }

  # Kooperiere in den ersten f?nf Runden.
  if (t<=5){
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))

  }

  # Erzeuge ein Kurzzeitged?chtnis der letzten 5 Runden, in welchem gespeichert      wird, was der Gegner von einem selber beobachtet.
  shortmemoryI=memoryI[(length(memoryI)-4):length(memoryI)]

  if (t==6){
    # Spiele abh?ngig von der Wahrnehmung des Gegners in den letzten f?nf Runden.       Falls der Gegner mehr als eine Defektion beobachtet hat
    # kooperiere, sonst defektiere.
    if(length(which(shortmemoryI=="C"))>=4){
      return(list(a="D",memoryI=memoryI,memoryJ=memoryJ))
    }
    else{
      return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
    }
  }
  # Erzeuge ein Kurzzeitged?chtnis der letzten sechs Runden f?r die Z?ge des         Gegners.
  shortmemoryJ=memoryJ[(length(memoryJ)-5):length(memoryJ)]

  if (t>=7){
    if (t%%6>0){
      # In den folgenden 5 Runden spiele jeweils abh?ngig von der Handlung des           Gegners in den letzten sechs Runden.
      # Falls er mehr als f?nf mal defektiert hat, defektiere ebenfalls. Sonst           kooperiere.
      if(length(which(shortmemoryJ=="D"))>=5){
        return(list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
      else{
        return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
      }
    }
    # Defektiere in jeder 6.Runde, au?er der Gegner nimmt jemanden zu aggressiv        wahr oder der Gegner ist zu aggressiv.
    else {
      if(length(which(shortmemoryJ=="D"))>=5){
        return(list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
      else if (length(which(shortmemoryI=="C"))>=4){
        return(list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
      else{
        return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
      }

    }

  }




}

#' A student strategy
#'
#' @export
squishy.the.octopus = function(obs,i,t,preObs=c("C","C"),ans="C",preAns="C",defectTotal=0,defectConsecutive=0,stopLoss=FALSE,...) {

  # Variable Definitions
  answer="C"
  j = 3-i

  # Constants that control the stopLoss system
  consecutiveStopLossBarrier=3
  if(t>10){
    consecutiveStopLossBarrier=4
  }
  relativeStopLossBarrier=0.25+0.05+max(0,(18-t)*0.02)

  # debug.store("tit.for.tat",i,t) # Store each call for each player
  # debug.restore("tit.for.tat",i=1,t=2) # Restore call for player i in period t

  # Find out if other player punished me because of an observation error
  obserr=FALSE;
  if(preObs[1]=="D" & obs$a[j]=="D" & preAns=="C"){
    obserr=TRUE;
  }

  # Update extra variables
  preObs=c(obs$a[i],obs$a[j])
  preAns=ans

  # Cooperate in the first period
  if (t==1)answer="C"

  # Alway cooperate in the early game
  if(! stopLoss){

    # Register defections that are NOT caused by observation error
    if(obs$a[j]=="D" & (!obserr)){
      defectTotal=defectTotal+1
      defectConsecutive=defectConsecutive+1
    }
    else{
      defectConsecutive=0
    }

    # Activate the StopLoss after x unprovoked defections in a row
    if(defectConsecutive>consecutiveStopLossBarrier){
      stopLoss=TRUE
    }

    # Activate the stop loss if the unprovoked defection quota exceeds the error probability significantly
    if(t>=5 & ((defectTotal/t)>relativeStopLossBarrier)){
      stopLoss=TRUE
    }

    # Play always cooperate until the game ends or the stop loss is triggered
    if(! stopLoss){
      return(list(a="C",preObs=preObs,preAns=preAns,ans="C",defectTotal=defectTotal,defectConsecutive=defectConsecutive,
                  stopLoss=stopLoss))
    }
  }

  # Play noise-safe tit-for-tat after the stop loss barrier was triggered:
  # Be forgiving if a previous defection was caused by an observation error.
  # Otherwise play tit-for-tat
  if (obs$a[j]=="C" | obserr){
    answer="C"
  }
  else{
    answer="D"
  }


  return(list(a=answer,preObs=preObs,preAns=preAns,ans=answer,defectTotal=defectTotal,defectConsecutive=defectConsecutive,
              stopLoss=stopLoss))
}

#' A student strategy
#'
#' @export
nashtag1 = function(obs,i,t,state=1,z=0,cop=4,wdh=0,memoryJ=0,...){
  j = 3-i

  #memory aufbauen ab 2. Runde
  if(t>1){memoryJ[t-1]=obs$a[j]}

  # Erzeuge ein Kurzzeitgedächtnis der letzten 30 Runden (ab Runde 30)
  if(t>=30){shortmem=memoryJ[(length(memoryJ)-29):length(memoryJ)]}

  #########################################
  ##State=1: Kooperiere bis Gegener in letzten 30 Fällen 13 mal defektiert hat (Bedingung 1) oder 3 mal in Folge
  # defektiert hat (Bedingung 2). Falls eine Wechselbedingung erfüllt, dann in State 2 wechseln.
  if (state==1){

    #Zähler z für aufeinander folgende Defektierungen des Gegeners
    if(obs$a[j]=="D"){z=z+1} #bei Defektion +1
    else{z=0}                #sonst 0 setzen

    #Bedingungen zum Wechseln in State 2 prüfen
    if (z==3){ #Bedingung 2 prüfen
      state=2
      z=0
    }
    if(t>=30){ #ab Runde 30
      if(length(which(shortmem=="D"))>12){ #Bedingung 1 prüfen
        state=2
        z=0
      }
    }

    #falls State immer noch =1 (keine State-Wechselbedingung erfüllt wurde) => Kooperiere
    if(state==1){
      return(list(a="C",state=state,z=z,cop=cop,wdh=wdh,memoryJ=memoryJ))
    }
  }
  ###################################################################################################################
  ##State=2: "Tit for Tat". Bis Gegner 5 mal in Folge Defektiert hat (Bedingung), dann in State 3 wechseln.
  #########################
  if(state==2){

    #Zähler für aufeinanderfolgende Defektierungen des Gegeners
    if(obs$a[j]=="D"){z=z+1}
    else{z=0}

    #Bedingung zum Wechseln in State 3 prüfen
    if(z==5){
      state=3
      z=0
    }
    #Falls keine Wechselbedingung erfüllt, Tit for Tat Spielen
    else{return(list(a=obs$a[j],state=state,z=z,cop=cop,wdh=wdh,memoryJ=memoryJ))}
  }

  ##################################################################################################################
  ##State=3: "Kooperation": 5 Runden. 3 mal Kooperieren. 1 mal Defektieren. Dannach testen, ob Geg. in den letzten
  ######################### 3 Rd. min. 1 mal kooperierte. Falls ja, in State 2 wechseln, sonst in State 4 wechseln.
  if(state==3){

    #1. Kooperationsrunde
    if(cop==4){ #cop = Zähler für restliche Runden in Kooperations-State
      return(list(a="C",state=state,z=z,cop=cop-1,wdh=wdh,memoryJ=memoryJ))
    }

    #ab Runde 2:
    if(cop>0&cop<4){

      #Zähler z für aufeinanderfolgende Defektionen des Gegeners in den vorherigen Runden aufbauen
      if(obs$a[j]=="D"){z=z+1}
      else{z=0}

      #Runde 4: Defektieren
      if(cop==1){
        return(list(a="D",state=state,z=z,cop=cop-1,wdh=wdh,memoryJ=memoryJ))
      }
      #Runde 2 und 3: Kooperieren
      else{
        return(list(a="C",state=state,z=z,cop=cop-1,wdh=wdh,memoryJ=memoryJ))
      }
    }

    #5. Runde. Hier wird der State gewechselt. Dazu Gegnerverhalten der letzten 3 Runden prüfen.
    else{

      #Bei drei gegnerischen Defektionen in Folge, in State 4 wechseln.
      if(z==3){state=4}

      #Falls mind. 1 mal kooperierte, in State 2 zurück wechseln.
      #Dieses Zurückwechseln ist maximal 5 mal erlaubt. Beim 6. mal wird in State 4 gewechselt.
      else{
        wdh=wdh+1 #Zähler, wie oft in State 2 zurück gewechselt wird
        if(wdh==6){state=4}
        else{return(list(a=obs$a[j],state=2,z=0,cop=4,wdh=wdh,memoryJ=memoryJ))}
      }
    }
  }

  ##################################################
  ##State=4: Immer Defektieren
  #############################
  if(state==4){
    return(list(a="D",state=state,z=z,cop=cop,wdh=wdh,memoryJ=memoryJ))
  }
}

#' A student strategy
#'
#' @export
pudb.strat2 = function(obs,i,t,obs.i=0,obs.j=0,beleidigt = FALSE,...){

  # In der ersten Runde kooperieren wir immer
  if(t==1){
    return(list(a="C",obs.i=obs.i,obs.j=obs.j, beleidigt = beleidigt))
  }

  # Ab Runde 2 wird ein Gedächtnis gebildet, wobei 3-i den Gegner angibt
  obs.i[t-1] = obs$a[i]
  obs.j[t-1] = obs$a[3-i]

  # Auch in der zweiten Runde kooperieren wir immer
  if(t == 2){
    return(list(a="C",obs.i = obs.i, obs.j = obs.j,beleidigt = beleidigt))
  }

  # Defektiert der Gegner zu Beginn 2 mal, so sind wir beleidigt und defektieren
  if(t==3){
    if(obs.j[t-1] == "D" & obs.j[t-2] == "D"){
      beleidigt = TRUE
    }
  }

  # kooperiert der Gegner in der vorherigen Runde, so sind wir nicht mehr beleidigt
  if(obs.j[t-1] == "C"){
    beleidigt = FALSE
  }

  # Reagiert der Gegner auf eine Kooperation zu oft mit Defektion, so sind wir ab
  # jetzt beleidigt und defektieren ab jetzt in jeder Runde
  if(t>20){
    sum.def = sum(obs.i[(1):(t-2)] == "C" & obs.j[2:(t-1)]=="D")
    sum.coop = sum(obs.i == "C")
    if(sum.coop>0){
      if((sum.def/sum.coop) > 0.7){
        beleidigt = TRUE
      }
    }
  }

  # defektiere immer, wenn wir einmal beleidigt sind
  if(beleidigt){
    return(list(a="D",obs.i = obs.i, obs.j = obs.j, beleidigt = beleidigt))
  }

  # Defektiert der Gegner in den letzten 3 Runden, so defektieren wir nun mit einer
  # Wahrscheinlichkeit von 80% und kooperieren mit Wahrscheinlichkeit 20%
  if(t>3){
    if(obs.j[t-1] == "D" & obs.j[t-2]=="D" & obs.j[t-3]=="D"){
      if(runif(1)<=0.8){
        return(list(a="D",obs.i = obs.i, obs.j = obs.j, beleidigt = beleidigt))
      } else{
        return(list(a="C",obs.i = obs.i, obs.j = obs.j, beleidigt = beleidigt))
      }
    }

  }


  # Hat der Gegner in den letzten 5 runden mindestens 3 mal defektiert, so
  # defektieren wir mit einer Wahrscheinlichkeit von 15%
  if(t>5){
    sum.def = sum(obs.j[(t-5):(t-1)]=="D")
    if(sum.def >= 3){
      if(runif(1) <= 0.15){
        return(list(a="D",obs.i = obs.i, obs.j = obs.j, beleidigt = beleidigt))
      }
    }
  }

  # Regiert der Gegner auf eine Kooperation von uns mit Defektion, so
  # defektiern wir mit einer Wahrscheinlichkeit von 45%
  if(obs.j[t-1] == "D" & obs.i[t-2] == "C"){
    if(runif(1)<=0.45){
      return(list(a="D",obs.i = obs.i, obs.j = obs.j, beleidigt = beleidigt))
    }
  }

  # trifft keine der obigen Bedingungen ein, so kooperieren wir in jedem Fall.
  return(list(a="C",obs.i = obs.i, obs.j = obs.j, beleidigt = beleidigt))
}

#' A student strategy
#'
#' @export
nottitfortat = function(obs,i,t,CountC=0,CountD=0,...){

  debug.store("nottitfortat",i,t)
  debug.restore("nottitfortat",i=2,t=2)

  j=3-i

  # Kooperiere in der ersten Runde
  if (t==1) {

    return(list(a="C", CountC=CountC, CountD=CountD))
  }

  # Kooperiere in den weiteren 9 Runden und zähle wie oft der Gegner kooperiert (CountC) bzw.
  # defektiert (CountD)
  else if (1 < t && t < 11) {
    if(obs$a[j]=="C"){
      CountC=CountC+1
    }else{
      CountD=CountD+1
    }
    return(list(a="C", CountC=CountC, CountD=CountD))
  }

  # Zähle ab Runde 11 weiter wie oft der Gegner kooperiert bzw. defektiert
  else {
    if (obs$a[j] == "C") {
      CountC = CountC + 1
    }
    else{
      CountD = CountD + 1
    }

    # Defektiere nun, wenn die Summe der gegnerischen Kooperationen aus den vorherigen Runden grö?er ist
    if ( CountC > CountD) {
      return(list(a="D",CountC=CountC, CountD=CountD))
    }

    # Wenn die Summe der gegnerischen Defektionen aus den vorherigen Runden grö?er ist, defektiere zu 80%
    # und kooperiere zu 20%
    else if ( CountC < CountD) {
      if (runif(1)<80) {
        a = "D"
      } else {
        a = "C"
      }
      return(list(a=a,CountC=CountC, CountD=CountD))
    }

    # Defektiere nun, wenn die Summe der gegnerischen Defektionen gleich der gegnerischen Kooperationen ist
    else {
      return(list(a="D",CountC=CountC, CountD=CountD))
    }
  }
}

#' A student strategy
#'
#' @export
prof.strat = function(obs,i,t, net.nice=0,k=1, ...) {
  if (t==1) {
    return(nlist(a="C",net.nice,k))
  }
  a = obs$a
  j = 3-i
  a.num = ifelse(a=="C",1,0)
  net.nice = net.nice + a.num[i]-a.num[j]
  if (net.nice <= k) {
    return(nlist(a="C",net.nice,k))
  }
  return(nlist(a="D",net.nice,k))
}

#' A student strategy
#'
#' @export
schachmatt_tournament = function(obs,i,t,memoryI=0,memoryJ=0,...) {

  # 1. Runde: Kooperation
  if (t==1) {
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
  }

  # Beginne ab Runde 2 das Gedaechtnis zu bilden. Gespeichert werden die Handlungen
  # beider Spieler in der vorherigen Runde
  # dabei steht 1 für Kooperation und 0 fuer Defektion
  # Definition der Parameter
  j = 3-i

  if(obs$a[i]=="C"){
    memoryI[t-1]=1
  }
  else{
    memoryI[t-1]=0
  }

  if(obs$a[j]=="C"){
    memoryJ[t-1]=1
  }
  else{
    memoryJ[t-1]=0
  }

  Def=1-mean(memoryJ)    # Def = Prozentzahl der Defektion

  # 2. & 3. Runde: Kooperation
  if(t<4){
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
  }

  #Runden 4-10:
  #Sammeln von Informationen ueber die andere Strategie
  #dafuer kooperieren wir mit nicht unkooperativen Strategien
  if(t<=10){
    if(Def <= 0.6){
      return (list(a="C",memoryI=memoryI,memoryJ=memoryJ))
    }
    else{
      return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
    }
  }

  #Auswertung der gesammelten Daten
  #Analyse von reaktionären Strategien
  k=5 #Anzahl der Zuege die max betrachtet werden sollen
  mat=matrix(0,nrow=t-2,ncol=k)
  for (l in 1:k){
    for (m in 1:(t-l-1)){
      #wir lassen die neuste Beobachtung des Gegners (unser letzter Zug) weg, da er noch nicht darauf reagiert hat.
      mat[m,l]=mean(memoryI[m:(l+m-1)])
    }
  }
  mat2=matrix(0,nrow=k,ncol=k)
  if (var(mat[,1])*var(memoryJ[2:(t-1)])!=0){
    mat2[1,1]=cor(mat[,1],memoryJ[2:(t-1)],method="pearson")
  }
  else{
    mat2[1,1]=0
  }
  koeff=c(1,1,mat2[1,1])
  # l Anzahl der Runden, die unser Gegner betrachtet
  for(l in 2:k){
    # m Anzahl der Koop davon
    for(m in 1:l){
      if(var(round(mat[-((t-l):(t-2)),l]+0.5001-m/l))*var(memoryJ[(l+1):(t-1)])!=0){
        mat2[m,l]=cor(round(mat[-((t-l):(t-2)),l]+0.5001-m/l),memoryJ[(l+1):(t-1)],method="pearson")
        if(mat2[m,l]>koeff[3]){
          koeff=c(l,m,mat2[m,l])
        }
      }
      else{
        mat2[m,l]=0
      }
    }
  }
  # im Vektor koeff sind drei Zahlen gespeichert
  # koeff[1] gibt die Zahl an, wie viele Runden unser Gegner betrachtet
  # koeff[2] gibt die Zahl an, wie viele daraus Kooperationen sein muessen, damit unser Gegner auch kooperiert
  #          (falls koeff[3]<0)
  # koeff[3] gibt den Korrelationskoeffizienten an. Je groess?er koeff, desto sicherer besteht eine Korrelation.
  #          Falls koeff[3]<0, spielt unser Gegner immer das Gegenteil von dem, was er beobachtet hat.
  #
  # gegen tit for tat kommt beispielsweise (1,1,0.72) zurueck. Unser Gegner betrachtet einen Zug, dabei muss mind. eine
  # Kooperation sein, mit einer "Wahrscheinlichkeit" von 72%
  # gegen drei.aus.fuenf kommt beispielsweise (5,3,0.73) zur?¼ck.


  #Analyse der Strategien, die ein Muster spielen
  # k ist die max Musterlänge, die betrachtet werden soll
  k=min(10,round(t/2.5))
  musterkoeff=c(0,0,0,0)
  #l moegliche Länge solch eines Musters
  for (l in 2:k){
    #m Anzahl der Defektionen pro Muster
    for(m in 1:(l-1)){
      hilfsvektor=rep(c(rep(0,m),rep(1,(l-m))),(round(t/l)+2))
      #n Stelle an der das Muster beginnt
      for (n in 1:l){
        if(var(memoryJ)*var(hilfsvektor[n:(t-2+n)])!=0){
          if(abs(cor(memoryJ,hilfsvektor[n:(t-2+n)],method="pearson"))>musterkoeff[3]){
            musterkoeff=c(l,m,cor(memoryJ,hilfsvektor[n:(t-2+n)],method="pearson"),n)
          }
        }
      }
    }
  }

  # musterkoeff[1] zeigt die Laenge des Musters an
  # wenn musterkoeff[3]>0, zeigt musterkoeff[2] an, mit wie vielen Defektionen das Muster startet
  # wenn musterkoeff[3]<0, zeigt musterkoeff[2] an, mit wie vielen Kooperationen das Muster startet
  # musterkoeff[3] beinhaltet den Korrelationskoeffizienten
  # musterkoeff[4] zeigt an, an welcher Stelle das Muster beginnt


  ###################
  #####Strategie#####
  ###################

  #Absicherung gegen Strategien, die zu oft defektieren
  #zu oft entspricht einer gespielten Kooperationsrate von 25%, d.h. einer beobachteten von 18.75%
  if (Def >= 0.8125 | mean(memoryJ[(t-7):(t-1)])<0.1 ){
    return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
  }

  # Falls wir gegen Tit.for.tat spielen, spielen wir always.coop
  if (koeff[1]==1 & koeff[2]==1 & koeff[3]>=0.6){
    return (list(a="C",memoryI=memoryI,memoryJ=memoryJ))
  }

  #gegen Strategien, die ein Muster spielen
  if(koeff[3]-abs(musterkoeff[3])+0.09<0 & abs(musterkoeff[3])>0.6){
    if(musterkoeff[3]>0){
      wert=(t-musterkoeff[1]+musterkoeff[4]-1)/musterkoeff[1]-round((t-musterkoeff[1]+musterkoeff[4]-1)/musterkoeff[1])
      if(wert<=0){
        wert=wert+1
      }
      if (wert==1){
        return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
      if(wert>(musterkoeff[2]/musterkoeff[1]+0.01)){
        return (list(a="C",memoryI=memoryI,memoryJ=memoryJ))
      }
      else{
        return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
    }
    else{
      wert=(t-musterkoeff[1]+musterkoeff[4]-1)/musterkoeff[1]-round((t-musterkoeff[1]+musterkoeff[4]-1)/musterkoeff[1])
      if(wert<=0){
        wert=wert+1
      }
      if (wert==1){
        return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
      if(wert>(musterkoeff[2]/musterkoeff[1]+0.01)){
        return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
      }
      else{
        return (list(a="C",memoryI=memoryI,memoryJ=memoryJ))
      }
    }
  }


  # Falls wir gegen einen Gegner spielen, der auf unsere Zuege reagiert
  # betrachte die Beobachtungen unseres Gegners unserer letzten Spielzuege
  if (koeff[3]>=0.5 & koeff[3]-abs(musterkoeff[3])+0.09>0){
    if (mean(memoryI[(t-koeff[1]):(t-1)]) > (koeff[2]+1)/koeff[1]){
      # in diesem Fall koennen wir ungestoert defektieren
      return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
    }
    else if (mean(memoryI[(t-koeff[1]):(t-1)]) < (koeff[2]-1)/koeff[1]){
      # in diesem Fall denkt unser Gegner, wir wuerden ihn ausnutzen (was wir ja niiiiieeeee machen wuerden...)
      # doch es lohnt sich auch nicht, mit ihm zu kooperieren, weil wir mind zwei Runden ausgenutzt würden
      return (list(a="D",memoryI=memoryI,memoryJ=memoryJ))
    }
    else{
      # hier koennen wir ohne Probleme kooperieren
      return (list(a="C",memoryI=memoryI,memoryJ=memoryJ))
    }
  }

  #default-Fall: keine unserer Faelle trifft zu
  return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
}

#' A student strategy
#'
#' @export
phases = function(obs,i,t,equal=TRUE,offender=FALSE,victim=FALSE,...){


  #j beschreibt Index des Gegners
  j=3-i


  # Kooperiere in der ersten Runde
  if(t==1)
    return(list(a="C",offender=offender,equal=equal,victim=victim))

  # Phase equal:
  if(equal){

    #Wir kooperieren wenn unsere beobachteten Handlungen übereinstimmen und bleiben in Phase equal.
    if(obs$a[[j]]==obs$a[[i]]){
      return(list(a="C",offender=offender,equal=equal,victim=victim))
    }

    #Spielt der Gegner eine einseitige Defektion, antworten wir mit einer Defektion und wechseln in Phase victim.
    else if(obs$a[[j]]=="D"){
      return(list(a="D",offender=FALSE,equal=FALSE,victim=TRUE))
    }

    #Spielen wir die einseitige Defektion, antworten wir mit einer Kooperation und welchseln in den Status offender.
    else if (obs$a[[i]]=="D"){
      return(list(a="C",victim=FALSE,equal=FALSE,offender=TRUE))
    }
  }

  #Phase victim: Wir defektieren solange bis unser Gegner Koopertiert.
  if(victim){

    # Defektiert der Gegner, defektieren wir zurück und bleiben in Phase Victim
    if(obs$a[[j]]=="D"){
      return(list(a="D",offender=offender,equal=equal,victim=victim))
    }

    # Koopertiert der Gegner, kooperieren wir zurück und wechseln in Phase equal.
    else{
      return(list(a="C",offender=FALSE,victim=FALSE,equal=TRUE))
    }
  }

  #Phase offender: Wir bleiben solange in dieser Phase und kooperieren, bis eine erfolgreiche Kooperation entsteht.
  if(offender){

    # ?nderung der Phase bei einvernehmlicher Kooperation, wechsel in Phase equal
    if(obs$a[[j]]=="C" && obs$a[[i]]=="C"){
      return(list(a="C",victim=FALSE,offender=FALSE,equal=TRUE))
    }
    # Kooperieren und in Phase bleiben
    else{
      return(list(a="C",offender=offender,equal=equal,victim=victim))
    }
  }

  #nicht notwendig
  else{
    return(list(a="C",offender=offender,equal=equal,victim=victim))
  }
}

#' A student strategy
#'
#' @export
false.friend = function (obs,i,t,memoryJ=0,...) {

  j = 3 - i    #j beschreibt Index des Gegners


  if(t %% 8 == 0){    #schaut ob acht Teiler der aktuellen Rundenzahl ist

    memoryJ[t-1]=obs$a[j]
    return(list(a="D",memoryJ=memoryJ)) # wenn ja: Strategie defektiert

  } else if (t < 6 ) {
    memoryJ[t-1]=obs$a[j]
    return(list(a="C",memoryJ=memoryJ)) # Kooperation in Runden 1-6



    # Kooperation, falls Gegner min. 2 der letzten sechs Runden kooperiert hat
  } else {

    memoryJ[t-1]=obs$a[j]

    # (letzte 6 Aktionen des Gegners werden aus dem Ged?chtnis herausgenommen)
    shortmemory=memoryJ[(length(memoryJ)-5):length(memoryJ)]

    if(length(which(shortmemory=="C"))>=2){
      return(list(a="C",memoryJ=memoryJ))

    } else { # ansonsten defektieren wir
      return(list(a="D",memoryJ=memoryJ))
    }
  }
}

#' A student strategy
#'
#' @export
Globaler.Tit.4.Tat = function(obs,i,t,memoryI=0, memoryJ=0,...) {

  j = 3-i

  # Beginne ab Runde 2 das Gedächtnis zu bilden. Gespeichert werden die beobachteten Handlungen
  # beider Spieler in der vorherigen Rund

  if (t>1){
    memoryI[t-1]=obs$a[i]
    memoryJ[t-1]=obs$a[j]
  }

  # Kooperiere in der ersten Runde
  if (t==1)
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))

  # Spiele abhängig vom Gegnerverhalten der bisherigen Spiele
  if((length(which(memoryJ=="C"))>=(length(which(memoryI=="C"))))){

    # Kooperiere,wenn es gleich oder mehr Kooperationen bei dem Gegner gab
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
  }
  else{
    # Defektiere, wenn Gegner weniger Kooperiert als wir
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ))
  }
}

#' A student strategy
#'
#' @export
viva.PD.Strategy = function(obs,i,t,countD=0,countC=0,memoryJ=0,...){
  j=3-i

  # erste Runde, kooperieren, memory auf C setzen
  if(t==1){
    return(list(a="C",countD=countD,countC=countC, memoryJ=memoryJ))
    memoryJ[1]="C"
  }

  # alle weiteren Runden: zunächst Beobachtung der letzten Runde speichern und falls Gegner in der letzten Runde defektiert, erhöhe Zähler für gegnerische Defektierungen bzw. bei Kooperation erhöhe Zähler für Kooperationen um eins
  else{
    memoryJ[t-1]=obs$a[j]
    if(obs$a[j]=="D"){
      countD=countD+1
    }
    else{
      countC=countC+1
    }

    # ab der fünften Runde: prüfe zusätzlich ob Gegner in den letzten fünf Runden mehr als zwei mal defektiert hat und falls ja, defektiere
    if(t>=5){
      shortmemory=memoryJ[(length(memoryJ)-4):length(memoryJ)]
      if(length(which(shortmemory=="D"))>=3){
        return(list(a="D",countD=countD,countC=countC, memoryJ=memoryJ))
      }
    }

    # ermittle gesamte "Defektierungs-" und "Kooperationsquote" des Gegners in allen Runden und prüfe, welche überwiegt. Dann: Falls Defektierungen bisher überwiegen: defektiere, Kooperation analog
    probD=(countD/(countD+countC))
    probC=(countC/(countD+countC))
    if(probC<=probD){
      return(list(a="D",countD=countD,countC=countC, memoryJ=memoryJ))
    }
    else{
      return(list(a="C",countD=countD,countC=countC, memoryJ=memoryJ))
    }
  }
}

#' A grad student strategy
#'
#' @export
into.spaaaace = function(obs,i,t,preObs=c("C","C"),ans="C",preAns="C",...) {

  # Variable Definitions
  answer="C"
  j = 3-i

  # debug.store("tit.for.tat",i,t) # Store each call for each player
  # debug.restore("tit.for.tat",i=1,t=2) # Restore call for player i in period t

  # Find out if other player punished me because of an observation error
  obserr=FALSE;
  if(preObs[1]=="D" & obs$a[j]=="D" & preAns=="C"){
    obserr=TRUE;
  }

  # Cooperate in the first period
  if (t==1)answer="C"

  # Be forgiving if a previous defection was caused by an observation error.
  # Otherwise play tit-for-tat

  if (obs$a[j]=="C" | obserr){
    answer="C"
  }
  else{
    answer="D"
  }

  preObs=c(obs$a[i],obs$a[j])
  preAns=ans

  return(list(a=answer,preObs=preObs,preAns=ans,ans=answer))
}

#' A grad student strategy
#'
#' @export
screams.in.space = function(obs,i,t,preObs=c("C","C"),ans="C",preAns="C", count.devious=0,clueless=0,count.obserr=0,...) {

  # Variable Definitions
  answer="C"
  j = 3-i

   debug.store("screams.in.space",i,t) # Store each call for each player
   debug.restore("screams.in.space",i=1,t=1) # Restore call for player i in period t
  # Find out if other player punished me because of an observation error
  obserr=FALSE;
  if(preObs[1]=="D" & obs$a[j]=="D" & preAns=="C"){
    obserr=TRUE;
    count.obserr = count.obserr+1
  }

  # Cooperate in the first period
  if (t==1)answer="C"

  # Be forgiving if a previous defection was caused by an observation error.
  # Otherwise play tit-for-tat

  if (obs$a[j]=="C" | obserr){
    if(obs$a[j]=="C" && obserr){ # the other one did not retaliate
      clueless = clueless+1
    }
    answer="C"
  }
  else{
    answer="D"
    if(preObs[1]=="C"){ # I really wanted this to be a nice thing and he saw that
      count.devious = count.devious+1
    }
  }

  if(t>=10){
    if(count.devious/t>0.4){ #the other one is really not nice
      answer="D"
    }
    if(clueless>count.obserr/2){ #more than half of the times there is no retaliation if obs.err
      answer="D"
    }
  }

  preObs=c(obs$a[i],obs$a[j])
  preAns=ans

  return(list(a=answer,preObs=preObs,preAns=ans,ans=answer, count.devious=count.devious, clueless=clueless, count.obserr=count.obserr))
}

#============== Strategies with Answers ===========

##########
# Baseline Scenario
##########


#' A student strategy
#'
#' @export
nice.tit.for.tat = function(obs, i, t, game, def=0, ...) {

  # Im ersten Durchlauf kooperieren

  if (t == 1)
    return(list(a = "C", def = def))

  j = 3 - i
  b = obs$a[j]

  # Ab dem zweiten Spielzug abh?ngig vom Spielzug des Gegners in der Runde davor, allerdings wird zu einer bestimmten Wahrscheinlichkeit (err.D.prob = 0.15) kooperiert, obwohl der Gegner defektiert hat. Gesondert gehen wir mit Hilfe des Z?hlers def auf h?ufiges Defektieren des Gegners ein, indem wir auch defektieren, wenn dieser drei mal defektiert hat.

  if (b=="C"){
    return(list(a = "C", def = def))
  }

  def = def + 1

  if (def == 3){
    def = 1
    return (list(a = "D", def = def))
  }

  do.cooperate = (runif(1) < 0.15)
  if (do.cooperate) {
    return(list(a = "C" , def = def))
  } else {
    return(list(a = "D", def = def))
  }

}

#' A student strategy
#'
#' Answerstrat to 'nice.tit.for.tat'
#'
#' @export
tft.forgive.fast.2 = function(obs,i,t,game,forgive=TRUE, counter=0, ...) {
  debug.store("tft.forgive",i,t) # Store each call for each player
  debug.restore("tft.forgive",i=1,t=2) # Restore call for player i in period t

  if (t==1)
    return(list(a="C",forgive=forgive, counter=0))

  j = 3-i
  if(obs$a[j]=="D" && forgive && counter<2){
    return(list(a="C",forgive=FALSE, counter=counter+1))
  }
  if(obs$a[j]=="D" && forgive==FALSE && counter<2){
    return(list(a="D",forgive=FALSE, counter=counter+1))
  }
  if(obs$a[j]=="D" && forgive==FALSE && counter==2){
    return(list(a="C",forgive=TRUE, counter=0))
  }
  if(obs$a[j]=="C"){
    return(list(a="C",forgive=TRUE, counter=0))
  }

}

#' A student strategy
#'
#' Answerstrat to 'nice.tit.for.tat'
#'
#' @export
counter.nice.tit.for.tat = function(obs,i,t,game,trust,ndef,ncoop,ntrust,param=0.25,...) {
  debug.store("counter.nice.tit.for.tat",i,t)
  debug.restore("counter.nice.tit.for.tat",i=1,t=2)

  j = 3-i
  ergebnis = list(a=obs$a[j])

  if (t==1){
    return(list(a="C",trust=0,ndef=0,ncoop=0,ntrust=0,param=param))
  }else{
    if(t==2){
      if(ergebnis=="D"){
        ncoop = 0
        ndef = 1
        ntrust = 1
        return(list(a="D",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust,param=param))
      }else{
        ncoop = 1
        ndef = 0
        ntrust = 0
        return(list(a="C",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust,param=param))
      }
    }
    if (ergebnis == "D"){
      ndef = ndef+param
      if(ntrust > 3){
        return(list(a="D",trust=trust,ndef=0,ncoop=0,ntrust=ntrust,param=param))
      }else{
        if (ndef > (ceiling(0.5*0.3*20) - trust)){
          return(list(a="D",trust=trust+1,ndef=0,ncoop=0,ntrust=ntrust+4,param=param))
        }else{
          ndef = ndef + 1
          return(list(a="C",trust=trust,ndef=ndef,ncoop=0,ntrust=ntrust,param=param))
        }
      }
    }else{
      if(ntrust > 5){
        return(list(a="D",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1,param=param))
      }else{
        ncoop = ncoop + 1
        return(list(a="C",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1,param=param))
        if (ncoop==3){
          return(list(a="C",trust=0,ndef=0,ncoop=0,ntrust=ntrust-1,param=param))
        }
      }
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'nice.tit.for.tat'
#'
#' @export
a.ntft.1 = function(i,t,obs,game,c=1,plus = 6,...){
  if(t==1) {
    return(list(a="C", c = c, plus=plus))
  }
  if(c == 1){
    c= c + plus
    return(list(a="D", c = c, plus=plus))
  } else {
    c = c - 1
    return(list(a="C", c = c, plus=plus))
  }
}

#' A student strategy
#'
#' Answerstrat to 'nice.tit.for.tat'
#'
#' @export
mean.tit.for.tat = function(obs,i,t,game, ...) {
  return(list(a="C"))
}

#' A student strategy
#'
#' @export
tft.forgive.slow = function(obs,i,t,game,forgive=TRUE, counter=0, ...) {
  debug.store("tft.forgive",i,t) # Store each call for each player
  debug.restore("tft.forgive",i=1,t=2) # Restore call for player i in period t

  if (t==1)
    return(list(a="C",forgive=forgive,counter=0))

  j = 3-i
  if(obs$a[j]=="D" && forgive && counter<5){
    return(list(a="C",forgive=FALSE, counter=counter+1))
  }
  if(obs$a[j]=="D" && forgive==FALSE && counter<5){
    return(list(a="D",forgive=FALSE, counter=counter+1))
  }
  if(obs$a[j]=="D" && forgive==FALSE && counter==5){
    return(list(a="C",forgive=TRUE, counter=0))
  }
  if(obs$a[j]=="C"){
    return(list(a="C",forgive=TRUE, counter=0))
  }

}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.slow'
#'
#' @export
counter.tft.forgive.slow = function(obs,i,t,game,...) {
  debug.store("counter.tft.forgive.slow",i,t)
  debug.restore("counter.tft.forgive.slow",i=1,t=2)

  if (t%%2==0){
    return(list(a="C"))
  } else{
    return(list(a="D"))
  }
}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.slow'
#'
#' @export
forgive.slower= function(obs, i, t, game, def=0, ...){

  if (t == 1)
    return(list(a = "C", def = def))

  j = 3 - i
  b = obs$a[j]

  # Ab dem zweiten Spielzug abh?ngig vom Spielzug des Gegners in der Runde davor, allerdings wird zu einer bestimmten Wahrscheinlichkeit (err.D.prob = 0.15) kooperiert, obwohl der Gegner defektiert hat. Gesondert gehen wir mit Hilfe des Z?hlers def auf h?ufiges Defektieren des Gegners ein, indem wir auch defektieren, wenn dieser drei mal defektiert hat.

  if (b=="C"){
    return(list(a = "C", def = def))
  }

  def = def + 1

  if (def == 3){
    def = 1
    return (list(a = "D", def = def))
  }

  do.cooperate = (runif(1) < 0.15)
  if (do.cooperate) {
    return(list(a = "C" , def = def))
  } else {
    return(list(a = "D", def = def))
  }

}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.slow'
#'
#' @export
tft.forgive.slow.killer = function(obs,i,t,game,count=0, ...) {

  if (t==1)
    return(list(a="D", count=count))

  if(obs$a[i]=="D" && count<5){
    return(list(a="C", count=count+1))
  }else{
    return(list(a="D", count=0))
  }
}

#' A student strategy
#'
#' @export
Rainbow.Unicorns.one <- function(obs, i, t, game, Ccount=0, Positive=0, Negative=0, ...){

  # Beginne mit Kooperation
  if (t==1) {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
  # Ermittle den Durchschnitt der Kooperation
  if (obs$a[3 - i] == 'C'){
    Ccount = Ccount + 1
  }
  # Ermittle aktuelles Ausbeutungsverhalten
  if(obs$a[3 - i] == 'D'){
    Negative=Negative+1
    Positive=0
  } else {
    Negative=0
    Positive=Positive+1
  }
  # Spiele auch im 2. - 5. Zug C
  if (t==2 || t==3 || t==4 || t==5) {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
  # Antworte angemessen
  if(Negative >= 3){
    return(list(a="D", Ccount=Ccount, Positive=Positive, Negative=Negative))
  } else if(Positive >= 2){
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  } else {
    if (round(Ccount / (t - 1)) == 1) {
      return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
    }
    return(list(a="D", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
}

#' A student strategy
#'
#' Answerstrat to Rainbow.Unicorns.one
#'
#' @export
eat.mindfreaks.2 <- function(obs, i, t, game, obs_C=0, ...){

  if (t == 1) {
    return(list(a="C",obs_C=obs_C))
  }

  if (obs$a[i] == "C"){
    obs_C = obs_C + 1
  } else {
    obs_C = obs_C - 1
  }

  if(obs_C <= 2){
    return(list(a="C",obs_C=obs_C))
  } else {
    return(list(a="D",obs_C=obs_C))
  }
}

#' A student strategy
#'
#' Answerstrat to Rainbow.Unicorns.one
#'
#' @export
regenbogen= function(obs, i, t, game,Ccount=0, ...){

  # In der ersten und zweiten Runde defektieren
  if(t==1||t==2){
    return(list(a="D",Ccount=Ccount))
  }

  if (obs$a[i] == "C"){
    Ccount = Ccount + 1
  }

  # Bis Runde 5 3 mal kooperieren und 2 mal defektieren, danach defektieren wenn man im Durchschnitt ?fters kooperiert als defektiert hat

  if (t==3 || t==4 || t==5) {
    return(nlist(a="C",Ccount))
  }
  if (round(Ccount / t) == 1) {
    return(nlist(a="D",Ccount))
  }
  return(nlist(a="C",Ccount))
}

#' A student strategy
#'
#' Answerstrat to Rainbow.Unicorns.one
#'
#' @export
Rainbow.Unicorns.one.killer <- function(obs, i, t, game, Ccount=0, Positive=0, Negative=0, ...){
  debug.store("Rainbow.Unicorns.one.killer",i,t) # Store each call for each player
  debug.restore("Rainbow.Unicorns.one.killer",i=1,t=2) # Restore call for player i in period t

  # Beginne mit Kooperation
  if (t<=2) {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
  # Ermittle den Durchschnitt der Kooperation
  if (obs$a[i] == 'C'){
    Ccount = Ccount + 1
  }
  # Ermittle aktuelles Ausbeutungsverhalten
  if(obs$a[i] == 'D'){
    Negative=Negative+1
    Positive=0
  } else {
    Negative=0
    Positive=Positive+1
  }

  # Handle angemessen
  if(Negative >= 2){
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }

  if (round(Ccount / (t)) == 1) {
    return(list(a="D", Ccount=Ccount, Positive=Positive, Negative=Negative))
  } else {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }

}

#' A student strategy
#
#' @export
seda.strat2 = function(obs, i, t, game, otherD, ...) {
  debug.store("strat2", i, t)  # Store each call for each player
  debug.restore("strat2", i = 1, t = 1)  # Restore call for player i in period t

  # Start nice in first period
  if (t == 1) {
    return(list(a = "C", otherD = 0))
  }
  j = 3 - i  # index of other player

  # If the other player has chosen D three or more times in a row play D
  if (obs$a[[j]] == "D")
    otherD = otherD + 1
  if (otherD > 3)
    return(list(a = "D", otherD = otherD))

  # Play C with probability 90% and with prob. 10% play D
  if (runif(1) < 90) {
    a = "C"
  } else {
    a = "D"
  }
  return(nlist(a = a, otherD))
}

#' A student strategy
#'
#' Answerstrat to seda.strat2
#'
#' @export
destab.strat2.0 = function(obs, i, t, game, obs_D=0, ...) {

  if (t > 1 && obs$a[i] == "D"){
    obs_D = obs_D + 1
  }

  if (obs_D > 3){
    return(list(a = "D", obs_D = obs_D))
  } else {
    return(nlist(a = "C", obs_D = obs_D))
  }
}

#' A student strategy
#'
#' Answerstrat to seda.strat2
#'
#' @export
counter.strat2 = function(obs,i,t,game,otherD,...) {
  debug.store("counter.strat2", i, t)  # Store each call for each player
  debug.restore("counter.strat2", i = 1, t = 2)  # Restore call for player i in period t

  if (t == 1) {
    return(list(a = "C", otherD = 0))
  }
  if (obs$a[i] == "D"){
    otherD = otherD + 1
  }
  if (otherD > 3){
    return(list(a = "D", otherD = otherD))
  }
  return(nlist(a="C",otherD))
}

#' A student strategy
#'
#' Answerstrat to seda.strat2
#'
#' @export
strat2.killer = function(obs, i, t, game, otherD, ...) {
  debug.store("strat2.killer", i, t)  # Store each call for each player
  debug.restore("strat2.killer", i = 1, t = 2)  # Restore call for player i in period t

  if (t==1) {
    return(list(a = "C", otherD = 0))
  }

  if (obs$a[i] == "D")
    otherD = otherD + 1
  if(otherD >3){
    return(list(a = "D", otherD = otherD))
  }else{
    return(list(a="C", otherD=otherD))
  }
}

#' A student strategy
# Answers seda.strat2 [0.714 after 500 Rounds]
#' @export
antistrat2 <- function(obs, i, t, game, otherD, ...) {
  if (t == 1) {
    return(list(a = "D", otherD = 0))
  }
  if (obs$a[[i]] == "D")
    otherD = otherD + 1
  if (otherD > 3)
    return(list(a = "D", otherD = otherD))

  if (runif(1) < 90) {
    a = "C"
  } else {
    a = "D"
  }
  return(nlist(a = a, otherD))
}

#' A student strategy
# Answers seda.strat2
#' @export
answer.strat3= function(obs,i,t,game,otherD, ...) {

  debug.store("answer.strat3",i,t) # Store each call for each player
  debug.restore("answer.strat3",i=1,t=2) # Restore call for player i in period t

  # Start nice in first period
  if (t == 1) {
    return(list(a = "C", otherD = 0))
  }
  j = 3 - i  # index of other player

  # If the other player has chosen D four or more times in a row play D
  if (obs$a[[j]] == "D")
    otherD = otherD + 1
  if (otherD > 4)
    return(list(a = "D", otherD = otherD))

  # Play C with probability 65% and with prob. 35% play D
  if (runif(1) < 65) {
    a="C"
  } else {
    a = "D"
  }
  return(nlist(a = a, otherD))


}

#' A student strategy
#'
#' @export
ta.daaa = function(obs, i, t, game, still.defect=0, ...) {
  debug.store("ta.daaa", i, t)  # Store each call for each player
  debug.restore("ta.daaa", i = 1, t = 2)  # Restore call for player i in period t

  # 1.Peridoe

  j = 3-i

  if ( t== 1){
    return(list(a= "C", still.defect=still.defect))
  }

  if (still.defect== 0){


    # n- Periden

    if ( obs$a[j]=="C"){
      return(list (a="C", still.defect=2))

    }else {
      return(list (a= obs$a[j], still.defect=still.defect))
    }


  }else {
    still.defect=still.defect-1
    return(list(a="C", still.defect=still.defect))
  }



}

#' A student strategy
#'
#' Answer to ta.daaa
#' @export
destab.ta.daaa = function(obs, i, t, game, pred="C", pattern=FALSE, count=2, ...) {

  if ( t== 1){
    pred="C"
    return(list(a= pred,pred=pred, pattern=pattern, count=count))
  }

  if (obs$a[i]=="C" && pred=="C"){
    pattern=TRUE
  }

  if (pattern==TRUE && count > 0){
    count=count-1
    pred="D"
    return(list(a= pred, pred=pred, pattern=pattern, count=count))
  } else if (pattern==TRUE && count==0){
    pattern=FALSE
    pred="C"
    count=2
    return(list(a= "C", pred=pred, pattern=pattern, count=count))
  } else if (pattern==FALSE){
    pred="C"
    return(list(a= "C", pred=pred, pattern=pattern, count=count))
  }
}

#' A student strategy
#'
#' Answer to ta.daaa
#' @export
counter.ta.daaa = function(obs,i,t,game,def=0,played,...) {
  debug.store("counter.ta.daaa",i,t) # Store each call for each player
  debug.restore("counter.ta.daaa",i=1,t=2) # Restore call for player i in period t

  if (t==1) return(list(a="C", def = 2, played = "C"))

  if (def > 0){
    if (obs$a[i]=="D"){
      if(played=="C"){
        return(list(a="C", def = 2, played = "C"))
      }
      return(list(a="D", def = def-1, played ="D"))
    }
    return(list(a="D", def = def-1, played ="D"))
  }else {
    return(list(a="C", def = 2, played ="C"))
  }
}

#' A student strategy
#'
#' Answer to ta.daaa
#' @export
tatada = function(obs, i, t, game, d=0, ...) {

  if (t == 1) {
    return(list(a = "C", d = 2))
  }
  c = obs$a[i]

  if (d == 0){
    return(list(a = "C", d = 2))
  }

  if (d == 2){
    if(c == "D"){
      return(list(a = "C", d = 2))
    }
    return(list(a = "D", d = 1))
  }

  if (d == 1){
    return(list(a = "D", d = 0))
  }
}

#' A student strategy
#'
#' Answer to ta.daaa
#' @export
a.tadaaa.1 = function(i,t,obs,game,c=1,plus = 2,...){
  if(c == 1){
    c= c + plus
    return(list(a="C", c = c, plus=plus))
  } else {
    c = c - 1
    return(list(a="D", c = c, plus=plus))
  }
}

#' A student strategy
#'
#' TikTak1
#' @export
TikTak1 = function(obs,i,t,game,trust,ndef,ncoop,ntrust, ...) {
  debug.store("TikTak1",i,t)
  debug.restore("TikTak1",i=1,t=2)

  # Anderer Spieler und Ergebnis des anderen Spielers herausfinden
  j = 3-i
  ergebnis = list(a=obs$a[j])

  # Kooperation in der ersten Runde
  if (t==1){
    return(list(a="C",trust=1,ndef=0,ncoop=0,ntrust=0))
  }else{
    if (t==2){
      if(ergebnis=="D"){
        ncoop = 0
        ndef = 1
        ntrust = 1
        return(list(a="D",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust))
      }else{
        ncoop = 1
        ndef = 0
        ntrust = 0
        return(list(a="C",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust))
      }
    }
    if (ergebnis == "D"){
      if(ntrust > 3){
        return(list(a="D",trust=trust,ndef=0,ncoop=0,ntrust=ntrust))  # Verraeter bestrafen
      }else{
        if (ndef > (ceiling(0.5*0.15*20) - trust)){
          # ntrust = ntrust + 2 -> Um Vertrauensmissbrauch zu vermeiden/die Strategie auszunutzen
          return(list(a="D",trust=trust+1,ndef=0,ncoop=0,ntrust=ntrust+2))
        }else{
          ndef = ndef + 1
          return(list(a="C",trust=trust,ndef=ndef,ncoop=0,ntrust=ntrust))
        }
      }
    }else{
      # ndef = 0
      if(ntrust > 3){
        return(list(a="D",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1))
      }else{
        ncoop = ncoop + 1
        return(list(a="C",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1))
        if (ncoop==3){
          #trust = 0 -> Schnell vergessend, langsam vergessend/Nachtragend waere trust = trust - 1
          #ntrust = ntrust - 1 -> Vertrauen wiedergewonnen
          return(list(a="C",trust=0,ndef=0,ncoop=0,ntrust=ntrust-1))
        }
      }
    }
  }
}

#' A student strategy
#'
#' Answerstrat to TikTak1
#'
#' @export
eat.unicorns.65 <- function(obs, i, t, game, obs_C=0, ...){

  if (t > 1 && obs$a[i] == "C"){
    obs_C = obs_C + 1
  }

  if (t == 1) {
    return(list(a="C",obs_C=obs_C))
  }

  if(obs_C/t <= 0.65){
    return(list(a="C",obs_C=obs_C))
  } else {
    return(list(a="D",obs_C=obs_C))
  }
}

#' A student strategy
#'
#' Answerstrat to TikTak1
#'
#' @export
TokTok= function(obs,i,t,game,count=0, ...){

  if(count==0|| count==1|| count==2||count==3){
    return(list(a="C",count=count+1))
  }
  if(count==4){
    return(list(a="D",count=0))
  }
  else return(list(a="C",count))
}

#' A student strategy
#'
#' Answerstrat to TikTak1
#'
#' @export
a.TikTak1 = function(i,t,obs,game,c=1,plus = 2, ...){
  if(t==1) {
    return(list(a="C", c = c, plus=plus))
  }
  if(c == 1){
    c= c + plus
    return(list(a="D", c = c, plus=plus))
  } else {
    c = c - 1
    return(list(a="C", c = c, plus=plus))
  }
}

#' A student strategy
#'
#' Answerstrat to TikTak1
#'
#' @export
TakTik1 = function (obs,i,t,game, ...) {
  if (t==1 | t==2) {
    return(nlist(a="D"))
  } else {
    if (obs$a[i]=="C") {
      return(nlist(a="D"))
    } else {
      return(nlist(a="C"))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to TikTak1
#'
#' @export
Antitiktak1 <- function(obs,i,t,game,ntrust=0,...) {
  ergebnis = list(a=obs$a[i])
  if (t==1){
    return(list(a="C",ntrust=0))
  }else{
    if (t==2){
      if(ergebnis=="D"){
        ntrust = 1
        return(list(a="D",ntrust=ntrust))
      }else{
        ntrust = 0
        return(list(a="C",ntrust=ntrust))
      }
    }
    if (ergebnis == "D"){
      if(ntrust > 3){
        return(list(a="D",ntrust=ntrust))
      }else{
        return(list(a="C",ntrust=ntrust))
      }
    }else{
      if(ntrust > 3){
        return(list(a="D",ntrust=ntrust-1))
      }else if(ntrust < 3){
        return(list(a="D",ntrust=ntrust-1))
      }else{
        return(list(a="C",ntrust=ntrust-1))
      }
    }
  }
}

#' A simplified Version of AntiTikTak1
#'
#' Answerstrat to TikTak1
#'
#' @export
Antitiktak1.simplified <- function(obs,i,t,game,...) {
  ergebnis = list(a=obs$a[i])
  if (t==1){
    return(list(a="C"))
  }else{
    if (t==2){
      if(ergebnis=="D"){
        return(list(a="D"))
      }else{
        return(list(a="C"))
      }
    }
    if (ergebnis == "D"){
      return(list(a="C"))
    }else{
      return(list(a="D"))
    }
  }
}

#' An improved Version of AntiTikTak1
#'
#' Answerstrat to TikTak1
#'
#' @export
Antitiktak1.improved <- function(obs,i,t,game,...) {
  ergebnis = list(a=obs$a[i])
  if (t==1){
    return(list(a="C"))
  }else{
    if (ergebnis == "D"){
      return(list(a="C"))
    }else{
      return(list(a="D"))
    }
  }
}

#' A student strategy
#'
#' the.undertaker
#' @export
the.undertaker.1 = function(obs,i,t,game, count.gen, count.spree,...) {
  debug.store("the.undertaker.1",i,t) # Store each call for each player
  debug.restore("the.undertaker.1",i=2,t=1) # Restore call for player i in period t

  j = 3-i
  #cooperate in first round
  if (t==1){
    count.gen <- 0
    count.spree <- 0
    return(list(a="C", count.gen = count.gen, count.spree = count.spree))
  }

  #count total amount of D?s and the D?s in a row
  if(obs$a[j]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }

  #defect when one of our tolerance is reached
  if(count.gen >= 10 || count.spree >= 3) {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree))
  }

  return(list(a="C", count.gen = count.gen, count.spree = count.spree))
}

#' A student strategy
#'
#' Answer to the.undertaker.1
#' @export
counter.the.undertaker.1 = function(obs,i,t,game,count.gen=0,count.spree=0,maxit=2,param=3,param2=10,...) {

  #D in first round
  if (t==1){
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
  }

  #count total amount of D?s and the D?s in a row
  if(obs$a[i]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }

  if(count.spree == maxit){
    return(list(a="C", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
  }else{
    if(count.gen < param){
      return(list(a="D", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
    }else{
      if(count.gen>= param2){
        return(list(a="D", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
      }else{
        return(list(a="C", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
      }
    }
  }
}

#' A student strategy
#'
#' Answer to the.undertaker.1
#' @export
the.overtaker.1 = function (obs,i,t,game,count.gen=0,count.spree=0,spree=FALSE,k=5, ...){
  j = 3-i
  #cooperate in first round
  if (t==1){
    return(list(a="C", count.gen = count.gen, count.spree = count.spree,spree=spree,k=k))
  }
  if (obs$a[i] == "D") {
    count.spree=count.spree+1
    count.gen=count.gen+1
    if (count.spree ==3){
      spree=TRUE
    }
  } else {
    count.spree=0
  }
  if (spree){
    return(list(a="D",count.gen=count.gen,count.spree=count.spree,spree=spree,k=k))
  }
  if ((count.spree <1 & count.gen < k) | count.gen>9) {
    return(list(a="D",count.gen=count.gen,count.spree=count.spree,spree=spree,k=k))
  } else {
    return(list(a="C",count.gen=count.gen,count.spree=count.spree,spree=spree,k=k))
  }

}

#' A student strategy
#'
#' Answer to the.undertaker.1
#' @export
overtaker <- function(obs,i,t, count.gen = 0, count.spree = 0,Factor1 = 5, Factor2 = 1,...){
  if (t==1){
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  }
  if(obs$a[i]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }
  if(count.gen >= 10) {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  } else if(count.gen >= Factor1 || count.spree >= Factor2){
    return(list(a="C", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  } else {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  }
}

#' A student strategy
#'
#' Answer to the.undertaker.1
#' @export
answer.strat2= function(obs,i,t,game,otherD, ...) {

  debug.store("answer.strat2",i,t) # Store each call for each player
  debug.restore("answer.strat2",i=1,t=2) # Restore call for player i in period t

  # Start nice in first period
  if (t == 1) {
    return(list(a = "C", otherD = 0))
  }
  j = 3 - i  # index of other player

  # If the other player has chosen D twelfe or more times in a row play D
  if (obs$a[[j]] == "D")
    otherD = otherD + 1
  if (otherD > 12)
    return(list(a = "D", otherD = otherD))

  # Play C with probability 65% and with prob. 35% play D
  if (runif(1) < 65) {
    a="C"
  } else {
    a = "D"
  }
  return(nlist(a = a, otherD))


}

#' A student strategy
#'
#' @export
probably.nice.Base <- function(obs,i,t,game,P_i=0.5,P_a=0.5, threshold=0.25, Fratio=0.4, ...){
  #Fratio: Familiarity Ratio -> 1 means "nice guy" 0 means "Anti nice guy"

  debug.store("probably.nice",i,t)
  debug.restore("probably.nice",i=2,t=2)

  j=3-i
  P_D <- game.object$game.pars$err.D.prob
  P_C <- game.object$game.pars$err.C.prob


  #Update beliefs
  if(t==1){
    #do nothing
  } else {
    #Update of P_a
    P_a_old <- P_a
    #The other guy would assume, that I am me, given what he knows about me, given that he is me
    if(P_i>=threshold){
      if(obs$a[j] == "C"){
        P_a <- P_a*(1-P_D)/(P_a*(1-P_D)+(1-P_a)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_a <- P_a*P_D/(P_a*(P_D)+(1-P_a)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil
      if(obs$a[j] == "C"){
        P_a <- P_a*P_C/(P_a*P_C + (1-P_a)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_a <- P_a*(1-P_C)/(P_a*(1-P_C)+(1-P_a)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
    #Update my view of myself based on his knowledge
    if(P_a_old>=threshold){
      if(obs$a[i] == "C"){
        P_i <- P_i*(1-P_D)/(P_i*(1-P_D)+(1-P_i)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_i <- P_i*P_D/(P_i*(P_D)+(1-P_i)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil so he should play D
      if(obs$a[i] == "C"){
        P_i <- P_i*P_C/(P_i*P_C + (1-P_i)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_i <- P_i*(1-P_C)/(P_i*(1-P_C)+(1-P_i)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
  }
  #If I think he is me, than cooperate
  if(P_a>=threshold){
    return(list(a="C",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  } else {
    return(list(a="D",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  }
}

#' A student strategy
#'
#' Answerstrat to 'probably.nice'
#'
#' @export
probably.not.that.nice <- function(obs,i,t,game,P_i=0.5,P_a=0.5, threshold=0.25, Fratio=0.4, ...){
  #Fratio: Familiarity Ratio -> 1 means "nice guy" 0 means "Anti nice guy"

  debug.store("probably.not.that.nice",i,t)
  debug.restore("probably.not.that.nice",i=1,t=1)
  j=3-i
  P_D <- game.object$game.pars$err.D.prob
  P_C <- game.object$game.pars$err.C.prob


  #Update beliefs
  if(t==1){
    #do nothing
  } else {
    #Update of P_a
    P_a_old <- P_a
    #The other guy would assume, that I am me, given what he knows about me, given that he is me
    if(P_i>=threshold){
      if(obs$a[j] == "C"){
        P_a <- P_a*(1-P_D)/(P_a*(1-P_D)+(1-P_a)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_a <- P_a*P_D/(P_a*(P_D)+(1-P_a)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil
      if(obs$a[j] == "C"){
        P_a <- P_a*P_C/(P_a*P_C + (1-P_a)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_a <- P_a*(1-P_C)/(P_a*(1-P_C)+(1-P_a)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
    #Update my view of myself based on his knowledge
    if(P_a_old>=threshold){
      if(obs$a[i] == "C"){
        P_i <- P_i*(1-P_D)/(P_i*(1-P_D)+(1-P_i)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_i <- P_i*P_D/(P_i*(P_D)+(1-P_i)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil so he should play D
      if(obs$a[i] == "C"){
        P_i <- P_i*P_C/(P_i*P_C + (1-P_i)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_i <- P_i*(1-P_C)/(P_i*(1-P_C)+(1-P_i)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
  }
  #If I think he is me, than cooperate
  if(P_a > 0.9999999){
    P_a = 0.99
  }
  if(P_i >= 0.85){
    return(list(a="D",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  } else if (P_a >= threshold){
    return(list(a="C",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  } else {
    return(list(a="D",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  }
}

#' A student strategy
#'
#' @export
Mind <-function (obs,i,t,game,NoC=0, ...) {
  if (t==1){
    return(list(a="C",NoC=NoC))
  } else {
    j=3-i
    if (obs$a[j] =="D"){
      NoC = NoC -1
    }
    else {
      NoC=NoC + 1
    }
    if (NoC >= 0){
      return(list(a="C",NoC=NoC))
    } else {
      return(list(a="D",NoC=NoC))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'Mind'
#'
#' @export
eat.unicorns.50 <- function(obs, i, t, game, obs_C=0, ...){

  if (t > 1 && obs$a[i] == "C"){
    obs_C = obs_C + 1
  }

  if (t == 1) {
    return(list(a="C",obs_C=obs_C))
  }

  if(obs_C/t <= 0.5){
    return(list(a="C",obs_C=obs_C))
  } else {
    return(list(a="D",obs_C=obs_C))
  }
}

#' A student strategy
#'
#' Answerstrat to 'Mind'
#'
#' @export
counter.Mind = function (obs,i,t,game,NoC=0,...) {
  debug.store("counter.Mind", i, t)  # Store each call for each player
  debug.restore("counter.Mind", i = 1, t = 2)  # Restore call for player i in period t

  if (t==1){
    return(list(a="C",NoC=NoC))
  }

  if (obs$a[i] =="D"){
    NoC = NoC -1
  } else {
    NoC=NoC + 1
  }

  if (NoC > 1){
    return(list(a="D",NoC=NoC))
  } else {
    return(list(a="C",NoC=NoC))
  }
}

#' A student strategy
#'
#' Answerstrat to 'Mind'
#'
#' @export
dont.mind= function(obs,i,t,game,count=0, ...){
  if (t==1){
    return(list(a="C",count=count))
  }

  if(obs$a[i]=="C"){
    count=count+1
  }else{
    count=count-1
  }
  if(count==2){
    return(nlist(a="D",count=count))
  }
  if (count==1|| count==0 || count==-1){
    return(list(a="C",count=count))
  }
  else return(list(a="C",count=count))
}

#' A student strategy
#'
#' Answerstrat to 'Mind'
#'
#' @export
a.Mind = function (obs,i,t,game,NoC=0, p = 1, ...) {
  if (t==1){
    return(list(a="C",NoC=NoC, p=p))
  } else {
    j=3-i
    if (obs$a[i] =="D"){
      NoC = NoC -1
    }
    else {
      NoC=NoC + 1
    }
    if (NoC <= p){
      return(list(a="C",NoC=NoC, p=p))
    } else {
      return(list(a="D",NoC=NoC, p=p))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'Mind'
#'
#' @export
Antimind <- function (obs,i,t,game,NoC=0, ...) {
  if (t==1){
    return(list(a="C",NoC=NoC))
  } else {
    if (obs$a[i] =="D"){
      NoC = NoC -1
    }
    else {
      NoC=NoC + 1
    }
    if (NoC >= 2){
      return(list(a="D",NoC=NoC))
    } else {
      return(list(a="C",NoC=NoC))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'Mind' and 'nice.tit.for.tat'
#'
#' @export
answer.strat1= function(obs,i,t,game,otherD, ...) {
  debug.store("strat5",i,t) # Store each call for each player
  debug.restore("strat5",i=1,t=2) # Restore call for player i in period t

  # Start nice in first period
  if (t == 1) {
    return(list(a = "C", otherD = 0))
  }
  j = 3 - i  # index of other player

  # If the other player has chosen D five or more times in a row play D
  if (obs$a[[j]] == "D")
    otherD = otherD + 1
  if (otherD > 5)
    return(list(a = "D", otherD = otherD))

  # Play C with probability 60% and with prob. 40% play D
  if (runif(1) < 60) {
    a="C"
  } else {
    a = "D"
  }
  return(nlist(a = a, otherD))
}

#' A prof strategy
#'
#' @export
net.nice0 = function(obs,i,t,net.nice=0,k=0,...) {
  if (t==1)
    return(nlist(a="C",net.nice, k=k))

  # Wie oft habe ich haeufiger C gespielt als mein Partner
  net.nice = net.nice + (obs$a[i]=="C") - (obs$a[[3-i]]=="C")
  if (net.nice <= k + ( runif(1) <(k-floor(k)) ) ) {
    return(nlist(a="C",net.nice, k=k))
  } else {
    return(nlist(a="D",net.nice, k=k))
  }
}

#' A variant to net.nice0
#'
#' @export
net.nice1 = function(obs,i,t,net.nice=0,k=1,...) {
  if (t==1)
    return(nlist(a="C",net.nice, k=k))

  # Wie oft habe ich haeufiger C gespielt als mein Partner
  net.nice = net.nice + (obs$a[i]=="C") - (obs$a[[3-i]]=="C")
  if (net.nice <= k + ( runif(1) <(k-floor(k)) ) ) {
    return(nlist(a="C",net.nice, k=k))
  } else {
    return(nlist(a="D",net.nice, k=k))
  }
}

#' A variant to net.nice0
#'
#' @export
net.nice.minus1 = function(obs,i,t,net.nice=0,k=-1,...) {
  if (t==1)
    return(nlist(a="C",net.nice, k=k))

  # Wie oft habe ich haeufiger C gespielt als mein Partner
  net.nice = net.nice + (obs$a[i]=="C") - (obs$a[[3-i]]=="C")
  if (net.nice <= k + ( runif(1) <(k-floor(k)) ) ) {
    return(nlist(a="C",net.nice, k=k))
  } else {
    return(nlist(a="D",net.nice, k=k))
  }
}

#' A variant to net.nice0
#'
#' @export
net.nice.start1 = function(obs,i,t,net.nice=1,k=0,...) {
  if (t==1)
    return(nlist(a="C",net.nice, k=k))

  # Wie oft habe ich haeufiger C gespielt als mein Partner
  net.nice = net.nice + (obs$a[i]=="C") - (obs$a[[3-i]]=="C")
  if (net.nice <= k + ( runif(1) <(k-floor(k)) ) ) {
    return(nlist(a="C",net.nice, k=k))
  } else {
    return(nlist(a="D",net.nice, k=k))
  }
}

#' A student strategy
#'
#' Answerstrat to 'net.nice0'
#'
#' @export
a.net.nice0 = function(obs,i,t,net.nice=0,...) {
  if (t==1)
    return(nlist(a="C",net.nice))

  net.nice = net.nice + (obs$a[3-i]=="C") - (obs$a[i]=="C")
  if (net.nice < -1 ) {
    return(nlist(a="D",net.nice))
  } else {
    return(nlist(a="C",net.nice))
  }
}

#' A student strategy
#'
#' Answerstrat to 'net.nice0'
#'
#' @export
antiprof2 <- function(obs,i,t,Ccount = 0,Factor=1,...){
  if (t==1)
    return(nlist(a="C",Ccount = Ccount, Factor=Factor))
  Ccount = Ccount + (obs$a[i]=="C") - (obs$a[3-i]=="C")
  if (Ccount > Factor ) {
    return(nlist(a="D",Ccount = Ccount, Factor=Factor))
  } else {
    return(nlist(a="C",Ccount = Ccount, Factor=Factor))
  }
}

#' A student strategy
#'
#' Answerstrat to tft.forgive.slow, Rainbow.Unicorns.one, Rainbow.Unicorns.two, Mind, TikTak1, TikTak2, nice.tit.for.tat
#'
#' @export
ron = function(obs, i, t, game, still.defect =0, ...) {
  debug.store("ron", i, t)  # Store each call for each player
  debug.restore("ron", i = 1, t = 1)  # Restore call for player i in period t


  if (t==1 && t ==2 && t==3 && t==4 && t==5) {
    return(list(a="D", still.defect=still.defect))
  }


  if(still.defect ==0){

    return(list(a="C", still.defect = 1))
  }

  if(still.defect ==1){
    return(list(a="C", still.defect = 2))

  }

  if (still.defect ==2){
    return(list(a="D", still.defect = 0))
  }

}

##########
# High err.D Scenario
##########

#' A student strategy
#'
#' @export
TikTak2 = function(obs,i,t,game,trust,ndef,ncoop,ntrust, ...) {
  debug.store("TikTak2",i,t)
  debug.restore("TikTak2",i=1,t=2)

  # Anderer Spieler und Ergebnis des anderen Spielers herausfinden
  j = 3-i
  ergebnis = list(a=obs$a[j])

  # Kooperation in der ersten Runde
  if (t==1){
    return(list(a="C",trust=1,ndef=0,ncoop=0,ntrust=0))
  }else{
    if(t==2){
      if(ergebnis=="D"){
        ncoop = 0
        ndef = 1
        ntrust = 1
        return(list(a="D",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust))
      }else{
        ncoop = 1
        ndef = 0
        ntrust = 0
        return(list(a="C",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust))
      }
    }
    if (ergebnis == "D"){
      if(ntrust > 3){
        return(list(a="D",trust=trust,ndef=0,ncoop=0,ntrust=ntrust))  # Verraeter bestrafen
      }else{
        if (ndef > (ceiling(0.5*0.3*20) - trust)){
          # ntrust = ntrust + 2 -> Um Vertrauensmissbrauch zu vermeiden/die Strategie auszunutzen
          return(list(a="D",trust=trust+1,ndef=0,ncoop=0,ntrust=ntrust+3))
        }else{
          ndef = ndef + 1
          return(list(a="C",trust=trust,ndef=ndef,ncoop=0,ntrust=ntrust))
        }
      }
    }else{
      # ndef = 0
      if(ntrust > 5){
        return(list(a="D",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1))
      }else{
        ncoop = ncoop + 1
        return(list(a="C",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1))
        if (ncoop==3){
          #trust = 0  #Schnell vergessend, langsam vergessend/Nachtragend waere trust = trust -1
          #ntrust = ntrust -1 Vertrauen wiedergewonnen
          return(list(a="C",trust=0,ndef=0,ncoop=0,ntrust=ntrust-1))
        }
      }
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'TikTak2'
#'
#' @export
a.tiktak.2 = function(i,t,obs,game,c=1,plus=3,...){
  if(t==1) {
    return(list(a="C", c = c, plus=plus))
  }
  if(c == 1){
    c= c + plus
    return(list(a="D", c = c, plus=plus))
  } else {
    c = c - 1
    return(list(a="C", c = c, plus=plus))
  }
}

#' A student strategy
#'
#' Answerstrat to 'TikTak2'
#'
#' @export
TakTik2 = function (obs,i,t,game,y=0, ...) {
  if (t==1 | t==2) {
    return(nlist(a="D",y=y))
  } else {
    if (obs$a[i]=="C"| y>=1) {
      y=y+1
      if(y>=2){
        y=0
      }
      return(nlist(a="D",y=y))
    } else {
      return(nlist(a="C",y=y))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'TikTak2'
#'
#' @export
strat.fot.tik.tak<- function(obs, i, t, game, still.cooperate = 0, ...) {
  debug.store("strat1", i, t)  # Store each call for each player
  debug.restore("strat1", i = 1, t = 2)  # Restore call for player i in period t

  # Randomize between C and D
  if (still.cooperate == 0) {
    do.defect= (runif(1) < 0.7)
    # With 70% probability choose D
    if (do.defect) {
      return(list(a = "C", still.cooperate = 3))
    } else {
      return(list(a = "D", still.cooperate = 0))
    }
  }

  # still.cooperate is bigger 0: play C and reduce still.cooperate by 1
  still.cooperate = still.cooperate - 1
  return(list(a = "C", still.cooperate = still.cooperate))
}

#' A student strategy
#'
#' Answerstrat to 'TikTak2'
#'
#' @export
Antitiktak2 = function(obs,i,t,game,ntrust, ...) {
  ergebnis = list(a=obs$a[i])
  if (t==1){
    return(list(a="C",ntrust=0))
  }else{
    if(t==2){
      if(ergebnis=="D"){
        ntrust = 1
        return(list(a="D",ntrust=ntrust))
      }else{
        ntrust = 0
        return(list(a="C",ntrust=ntrust))
      }
    }
    if (ergebnis == "D"){
      if(ntrust > 3){
        return(list(a="D",ntrust=ntrust))
      }else{
        return(list(a="C",ntrust=ntrust))
      }
    }else{
      if(ntrust > 5){
        return(list(a="D",ntrust=ntrust-1))
      }else if(ntrust < 3){
        return(list(a="D",ntrust=ntrust-1))
      }else{
        return(list(a="C",ntrust=ntrust-1))
      }
    }
  }
}

#' A student strategy
#'
#' @export
probably.nice.High.err <- function(obs,i,t,game,P_i=0.5,P_a=0.5, threshold=0.3, Fratio=0.3, ...){
  #Fratio: Familiarity Ratio -> 1 means "nice guy" 0 means "Anti nice guy"

  debug.store("probably.nice",i,t)
  debug.restore("probably.nice",i=2,t=2)

  j=3-i
  P_D <- game.object$game.pars$err.D.prob
  P_C <- game.object$game.pars$err.C.prob


  #Update beliefs
  if(t==1){
    #do nothing
  } else {
    #Update of P_a
    P_a_old <- P_a
    #The other guy would assume, that I am me, given what he knows about me, given that he is me
    if(P_i>=threshold){
      if(obs$a[j] == "C"){
        P_a <- P_a*(1-P_D)/(P_a*(1-P_D)+(1-P_a)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_a <- P_a*P_D/(P_a*(P_D)+(1-P_a)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil
      if(obs$a[j] == "C"){
        P_a <- P_a*P_C/(P_a*P_C + (1-P_a)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_a <- P_a*(1-P_C)/(P_a*(1-P_C)+(1-P_a)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
    #Update my view of myself based on his knowledge
    if(P_a_old>=threshold){
      if(obs$a[i] == "C"){
        P_i <- P_i*(1-P_D)/(P_i*(1-P_D)+(1-P_i)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_i <- P_i*P_D/(P_i*(P_D)+(1-P_i)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil so he should play D
      if(obs$a[i] == "C"){
        P_i <- P_i*P_C/(P_i*P_C + (1-P_i)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_i <- P_i*(1-P_C)/(P_i*(1-P_C)+(1-P_i)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
  }
  #If I think he is me, than cooperate
  if(P_a>=threshold){
    return(list(a="C",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  } else {
    return(list(a="D",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio))
  }
}

#' A student strategy
#'
#' Answerstrat to 'probably.nice.High.err'
#'
#' @export
probably.not.so.nice <- function(obs,i,t,game,P_i=0.5,P_a=0.5, threshold=0.3, Fratio=0.3,k=0.87, ...){
  #Fratio: Familiarity Ratio -> 1 means "nice guy" 0 means "Anti nice guy"

  debug.store("probably.not.so.nice",i,t)
  debug.restore("probably.not.so.nice",i=2,t=2)

  j=3-i
  P_D <- game.object$game.pars$err.D.prob
  P_C <- game.object$game.pars$err.C.prob


  #Update beliefs
  if(t==1){
    #do nothing
  } else {
    #Update of P_a
    P_a_old <- P_a
    #The other guy would assume, that I am me, given what he knows about me, given that he is me
    if(P_i>=threshold){
      if(obs$a[j] == "C"){
        P_a <- P_a*(1-P_D)/(P_a*(1-P_D)+(1-P_a)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_a <- P_a*P_D/(P_a*(P_D)+(1-P_a)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil
      if(obs$a[j] == "C"){
        P_a <- P_a*P_C/(P_a*P_C + (1-P_a)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_a <- P_a*(1-P_C)/(P_a*(1-P_C)+(1-P_a)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
    #Update my view of myself based on his knowledge
    if(P_a_old>=threshold){
      if(obs$a[i] == "C"){
        P_i <- P_i*(1-P_D)/(P_i*(1-P_D)+(1-P_i)*(P_C+Fratio*(1-P_D-P_C)))
      } else { # Case Defect
        P_i <- P_i*P_D/(P_i*(P_D)+(1-P_i)*(P_D + (1-Fratio)*(1-P_D-P_C)))
      }
    } else { # other guy thinks I am evil so he should play D
      if(obs$a[i] == "C"){
        P_i <- P_i*P_C/(P_i*P_C + (1-P_i)*(P_C + (1-Fratio)*(1-P_D-P_C)))
      } else {
        P_i <- P_i*(1-P_C)/(P_i*(1-P_C)+(1-P_i)*(P_D + Fratio*(1-P_D-P_C)))
      }
    }
  }
  #If I think he is me, than cooperate
  if(P_a > 0.9999999){
    P_a = 0.99
  }
  if(P_i > k){
    return(list(a="D",P_i=P_i,P_a=P_a,threshold=threshold, Fratio=Fratio, k=k))
  }
  if(P_a>=threshold){
    return(list(a="C",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio, k=k))
  } else {
    return(list(a="D",P_i=P_i,P_a=P_a, threshold=threshold, Fratio=Fratio, k=k))
  }
}

#' A student strategy
#'
#' @export
the.undertaker.2 = function(obs,i,t,game, count.gen = 0, count.spree = 0, ...) {
  debug.store("the.undertaker.2",i,t) # Store each call for each player
  debug.restore("the.undertaker.2",i=2,t=6) # Restore call for player i in period t

  j = 3-i

  if (t==1){
    return(list(a="C", count.gen = count.gen, count.spree = count.spree))
  }

  #count total amount of D?s and the D?s in a row
  if(obs$a[j]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }

  #defect when one of our tolerance is reached
  if(count.gen >= 11 || count.spree >= 3) {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree))
  }

  return(list(a="C", count.gen = count.gen, count.spree = count.spree))
}

#' A student strategy
#'
#' Answerstrat to 'the.undertaker.2'
#'
#' @export
counter.the.undertaker.2 = function(obs,i,t,game,count.gen=0,count.spree=0,maxit=2,param=3,param2=11,...) {

  #D in first round
  if (t==1){
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
  }

  #count total amount of D?s and the D?s in a row
  if(obs$a[i]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }

  if(count.spree == maxit){
    return(list(a="C", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
  }else{
    if(count.gen < param){
      return(list(a="D", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
    }else{
      if(count.gen>= param2){
        return(list(a="D", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
      }else{
        return(list(a="C", count.gen = count.gen, count.spree = count.spree, maxit=maxit, param=param, param2=param2))
      }
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'the.undertaker.2'
#'
#' @export
answer.to.undertaker.2 = function(obs,i,t,game, count.gen = 0, count.spree = 0, ...) {
  debug.store("the.undertaker.2",i,t) # Store each call for each player
  debug.restore("the.undertaker.2",i=2,t=6) # Restore call for player i in period t

  j = 3-i

  if (t==1){
    return(list(a="D", count.gen = count.gen, count.spree = count.spree))
  }

  #count total amount of D?s and the D?s in a row
  if(obs$a[j]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }

  #defect when one of our tolerance is reached
  if(count.gen >= 9|| count.spree >= 5) {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree))
  }

  return(list(a="C", count.gen = count.gen, count.spree = count.spree))
}

#' A student strategy
#'
#' Answerstrat to 'the.undertaker.2'
#'
#' @export
overtaker.High.err <- function(obs,i,t, count.gen = 0, count.spree = 0,Factor1 = 5, Factor2 = 1,...){
  if (t==1){
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  }
  if(obs$a[i]=="D"){
    count.gen = count.gen+1
    count.spree = count.spree + 1
  } else {
    count.spree = 0
  }
  if(count.gen >= 10) {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  } else if(count.gen >= Factor1 || count.spree >= Factor2){
    return(list(a="C", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  } else {
    return(list(a="D", count.gen = count.gen, count.spree = count.spree, Factor1=Factor1, Factor2=Factor2))
  }
}

#' A student strategy
#'
#' @export
MindHighD <-function (obs,i,t,game,NoC=1, ...) {
  if (t==1){
    return(list(a="C",NoC=NoC))
  } else {
    j=3-i
    if (obs$a[j] =="D"){
      NoC = NoC -1
    }
    else {
      NoC=NoC + 1.3
    }
    if (NoC >= 0){
      return(list(a="C",NoC=NoC))
    } else {
      return(list(a="D",NoC=NoC))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'MindHighD'
#'
#' @export
eat.unicorns.48 <- function(obs, i, t, game, obs_C=0, ...){

  if (t > 1 && obs$a[i] == "C"){
    obs_C = obs_C + 1
  }

  if (t == 1) {
    return(list(a="C",obs_C=obs_C))
  }

  if(obs_C/t <= 0.479){
    return(list(a="C",obs_C=obs_C))
  } else {
    return(list(a="D",obs_C=obs_C))
  }
}

#' A student strategy
#'
#' Answerstrat to 'MindHighD'
#'
#' @export
counter.MindHighD = function (obs,i,t,game,NoC=0,k=1.25,...) {
  debug.store("counter.MindHighD", i, t)  # Store each call for each player
  debug.restore("counter.MindHighD", i = 1, t = 2)  # Restore call for player i in period t

  if (t==1){
    return(list(a="C",NoC=NoC, k=k))
  }

  if (obs$a[i] =="D"){
    NoC = NoC -1
  } else {
    NoC=NoC + 1.3
  }

  if (NoC > k){
    return(list(a="D",NoC=NoC, k=k))
  } else {
    return(list(a="C",NoC=NoC, k=k))
  }
}

#' A student strategy
#'
#' Answerstrat to 'MindHighD'
#'
#' @export
dont.mind.High.err= function(obs,i,t,game,count=0, ...){
  if (t==1){
    return(list(a="C",count))
  }

  if(obs$a[i]=="C"){
    count=count+1
  }else{
    count=count-1
  }
  if(count==2){
    return(list(a="D",count))
  }
  if (count==1|| count==0 || count==-1){
    return(list(a="C",count))
  }
  else return(list(a="C",count))
}

#' A student strategy
#'
#' Answerstrat to 'MindHighD'
#'
#' @export
a.MindHighD <-function (obs,i,t,game,NoC=1, p = 3.3, ...) {
  if (t==1){
    return(list(a="C",NoC=NoC, p=p))
  } else {
    if (obs$a[i] =="D"){
      NoC = NoC -1
    }
    else {
      NoC=NoC + 1.3
    }
    if (NoC >= p){
      return(list(a="D",NoC=NoC, p=p))
    } else {
      return(list(a="C",NoC=NoC, p=p))
    }
  }
}

#' A student strategy
#'
#' Answerstrat to 'MindHighD'
#'
#' @export
Antimind2 <- function (obs,i,t,game,NoC=0, ...) {
  if (t==1){
    return(list(a="C",NoC=NoC))
  } else {
    if (obs$a[i] =="D"){
      NoC = NoC -1
    }
    else {
      NoC=NoC + 1.3
    }
    if (NoC >= 3){
      return(list(a="D",NoC=NoC))
    } else {
      return(list(a="C",NoC=NoC))
    }
  }
}

#' A student strategy
#'
#' @export
Rainbow.Unicorns.two <- function(obs, i, t, game, Ccount=0, Positive=0, Negative=0, ...){

  # Beginne mit Kooperation
  if (t==1) {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
  # Ermittle den Durchschnitt der Kooperation
  if (obs$a[3 - i] == 'C'){
    Ccount = Ccount + 1
  }
  # Ermittle aktuelles Ausbeutungsverhalten
  if(obs$a[3 - i] == 'D'){
    Negative=Negative+1
    Positive=0
  } else {
    Negative=0
    Positive=Positive+1
  }
  # Spiele auch im 2. - 5. Zug C
  if (t==2 || t==3 || t==4 || t==5) {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
  # Antworte angemessen
  if(Positive >= 2){
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  } else {
    if (round(Ccount / (t - 1)) == 1) {
      return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
    }
    return(list(a="D", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
}

#' A student strategy
#'
#' Answerstrat to 'Rainbow.Unicorns.two'
#'
#' @export
counter.rainbow.unicorns.two = function(obs,i,t,game,coop,me,played,param=6,...) {
  debug.store("counter.rainbow",i,t)
  debug.restore("counter.rainbow",i=1,t=2)
  j = 3-i
  if(t==1){
    return(list(a="C",coop=0,me=0,played="C", param=param))
  }
  if(t<param){
    if(played == obs$a[i]){
      coop = coop+1
    }
    if(coop <3){
      return(list(a="C",coop,me=0,played="C", param=param))
    }else{
      return(list(a="D",coop,me=0,played="D", param=param))
    }
  }
  if(played == obs$a[i]){
    coop = coop+1
  }
  if (round(coop / (t - 1)) == 1) {
    return(list(a="D",coop=0,me=0,played="D", param=param))
  }
  return(list(a="D",coop=0,me=0,played="D", param=param))
}

#' A student strategy
#'
#' Answerstrat to 'Rainbow.Unicorns.two'
#'
#' @export
Rainbow.Unicorns.two.killer <- function(obs, i, t, game, Ccount=0, Positive=0, Negative=0, ...){
  debug.store("Rainbow.Unicorns.two.killer",i,t) # Store each call for each player
  debug.restore("Rainbow.Unicorns.two.killer",i=1,t=2) # Restore call for player i in period t

  # Beginne mit Kooperation
  if (t<=2) {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }
  # Ermittle den Durchschnitt der Kooperation
  if (obs$a[i] == 'C'){
    Ccount = Ccount + 1
  }
  # Ermittle aktuelles Ausbeutungsverhalten
  if(obs$a[i] == 'D'){
    Negative=Negative+1
    Positive=0
  } else {
    Negative=0
    Positive=Positive+1
  }

  # Handle angemessen
  if (round(Ccount / (t)) == 1) {
    return(list(a="D", Ccount=Ccount, Positive=Positive, Negative=Negative))
  } else {
    return(list(a="C", Ccount=Ccount, Positive=Positive, Negative=Negative))
  }

}

#' A student strategy
#'
#' @export
tft.forgive.fast = function(obs,i,t,game,forgive=TRUE, counter=0, ...) {
  debug.store("tft.forgive",i,t) # Store each call for each player
  debug.restore("tft.forgive",i=1,t=2) # Restore call for player i in period t

  if (t==1)
    return(list(a="C",counter=0))

  j = 3-i
  if(obs$a[j]=="D" && forgive && counter<3){
    return(list(a="C",forgive=FALSE, counter=counter+1))
  }
  if(obs$a[j]=="D" && forgive==FALSE && counter<3){
    return(list(a="D",forgive=FALSE, counter=counter+1))
  }
  if(obs$a[j]=="D" && forgive==FALSE && counter==3){
    return(list(a="C",forgive=TRUE, counter=0))
  }
  if(obs$a[j]=="C"){
    return(list(a="C",forgive=TRUE, counter=0))
  }

}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.fast'
#'
#' @export
harry = function(obs, i, t, game, still.defect =0, ...) {
  debug.store("harry", i, t)  # Store each call for each player
  debug.restore("harry", i = 1, t = 2)  # Restore call for player i in period t


  j = 3-i
  if ( t==1)
    return(list (a="C", still.defect=still.defect))





  if (still.defect== 0){


    # n- Periden

    if ( obs$a[j]=="D"){
      return(list (a="D", still.defect=2))

    }
    else {

      return(list (a= obs$a[j], still.defect=still.defect))
    }
  } else {


    if ( still.defect== 2){
      still.defect= still.defect -1
      return(list(a="C", still.defect))

    }else{
      still.defect = still.defect -1
      return (list(a="D", still.defect))
    }
  }

}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.fast'
#'
#' @export
counter.tft.forgive.fast = function(obs,i,t,game,not.me=0,param=1,time=4,...) {
  debug.store("counter.tft.forgive.slow",i,t)
  debug.restore("counter.tft.forgive.slow",i=1,t=2)
  j = 3-i
  if(t==1){
    return(list(a="D",not.me,param,time))
  }
  if(t < time){
    b = obs$a[j]
    if(b == 'C'){
      not.me = not.me+1
    }
  }
  if(not.me<param){
    return(list(a="C",not.me,param,time))
  }
  if (t%%2==0){
    return(list(a="D",not.me,param,time))
  } else{
    return(list(a="C",not.me,param,time))
  }
}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.fast'
#'
#' @export
dont.forgive= function(obs, i, t, game, d=1){

  j=3-i

  # 4 mal defektieren
  if (d==1 || d==2|| d==3 || d==4){
    return(list(a= "D", d=d+1))
  }
  #4 mal kooperieren au?er der andere denkt, dass man in der Runde davor defektiert hat, obwohl man kooperiert hat
  if ((d==6 || d==7 || d==8) && obs$a[i]=="D"){
    return(list(a= "D", d=1))
  }

  if (d==5 || d==6|| d==7){
    return(list(a= "C", d=d+1))
  }
  if (d==8){
    return(list(a= "C", d=1))
  }
}

#' A student strategy
#'
#' Answerstrat to 'tft.forgive.fast'
#'
#' @export
tft.forgive.fast.killer = function(obs,i,t,game,count=0) {
  debug.store("tft.forgive.fast.killer",i,t) # Store each call for each player
  debug.restore("tft.forgive.fast.killer",i=1,t=2) # Restore call for player i in period t

  if (t==1)
    return(list(a="D", count=count))

  if(obs$a[i]=="D" && count<3){
    count=count+1
    return(list(a="C", count=count))
  }else{
    return(list(a="D", count=0))
  }
}

#' A student strategy
#'
#' @export
da.taaa = function(obs, i, t, game, still.defect=0, ...) {
  debug.store("da.taaa", i, t)  # Store each call for each player
  debug.restore("da.taaa", i = 1, t = 2)  # Restore call for player i in period t

  # 1.Peridoe

  j = 3-i

  if ( t== 1)
    return(list(a= "C", still.defect=still.defect))


  if (still.defect== 0){


    # n- Periden

    if ( obs$a[j]=="D"){
      return(list (a="D", still.defect=2))

    }
    else {

      return(list (a= obs$a[j]))
    }
  } else {
    still.defect=still.defect-1
    return(list(a="D", still.defect))
  }

}

#' A student strategy
#'
#' Answerstrat to 'da.aaaa'
#'
#' @export
counter.da.taaa = function(obs,i,t,game,still.defect=0,played,param=3,...) {
  debug.store("counter.tft.forgive.slow",i,t)
  debug.restore("counter.tft.forgive.slow",i=1,t=2)

  j = 3-i

  if ( t== 1)
    return(list(a= "C",still.defect,played="C", param=param))

  if(played == "C"){
    if(obs$a[i]!=played){
      return(list (a="D", still.defect=param,played="D", param=param))
    }
  }
  if (still.defect== 0){
    if ( obs$a[j]=="D"){
      return(list (a="D", still.defect=param,played="D", param=param))
    }
    else {
      return(list (a= obs$a[j],still.defect,played="C", param=param))
    }
  } else {
    still.defect=still.defect-1
    return(list(a="D", still.defect,played="D", param=param))
  }
}

#' A student strategy
#'
#' Answerstrat to 'da.aaaa'
#'
#' @export
a.td.2 = function(i,t,obs,game,c=1,plus = 2,...){ ##<---zerfetzt!!!!
  if(c == 1){
    c= c + plus
    return(list(a="C", c = c, plus=plus))
  } else {
    c = c - 1
    return(list(a="D", c = c, plus=plus))
  }
}

#' A student strategy
#'
#' Answerstrat to 'da.aaaa'
#'
#' @export
da.taaa.counter = function(obs,i,t,game,defect=0, bool=TRUE, ...) {
  if (t==1) {
    return(list(a="C", defect=defect,bool=bool))
  }

  if (obs$a[i]=="D" & defect == 0 & bool) {
    defect = 2
    bool=FALSE
  }
  if (defect > 0) {
    defect=defect -1
    return(list(a="D", defect=defect, bool=bool))
  }
  bool=TRUE


  return(list(a="C",defect=defect,bool=bool))
}

#' A student strategy
#'
#' @export
nice.tit.for.tat.High.err = function(obs, i, t, game, def=0, ...) {

  # Im ersten Durchlauf kooperieren

  if (t == 1)
    return(list(a = "C", def = def))

  j = 3 - i
  b = obs$a[j]

  # Ab dem zweiten Spielzug abh?ngig vom Spielzug des Gegners in der Runde davor, allerdings wird zu einer bestimmten Wahrscheinlichkeit (err.D.prob = 0.3) kooperiert, obwohl der Gegner defektiert hat.Gesondert gehen wir mit Hilfe des Z?hlers def auf h?ufiges Defektieren des Gegners ein, indem wir auch defektieren, wenn dieser drei mal defektiert hat.

  if (b=="C"){
    return(list(a = "C", def = def))
  }

  def = def +1

  if (def == 3){
    def = 1
    return (list(a = "D", def = def))
  }

  do.cooperate = (runif(1) < 0.3)
  if (do.cooperate) {
    return(list(a = "C" , def = def))
  } else {
    return(list(a = "D", def = def))
  }

}

#' A student strategy
#'
#' Answerstrat to 'nice.tit.for.tat.High.err'
#'
#' @export
counter.nice.tit.for.tat.2 = function(obs,i,t,game,trust,ndef,ncoop,ntrust,param=-5,...) {
  debug.store("counter.nice.tit.for.tat.2",i,t)
  debug.restore("counter.nice.tit.for.tat.2",i=1,t=2)

  j = 3-i
  ergebnis = list(a=obs$a[j])

  if (t==1){
    return(list(a="C",trust=0,ndef=0,ncoop=0,ntrust=0, param=param))
  }else{
    if(t==2){
      if(ergebnis=="D"){
        ncoop = 0
        ndef = 1
        ntrust = 1
        return(list(a="D",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust, param=param))
      }else{
        ncoop = 1
        ndef = 0
        ntrust = 0
        return(list(a="C",trust=trust,ndef=ndef,ncoop=ncoop,ntrust=ntrust, param=param))
      }
    }
    if (ergebnis == "D"){
      ndef = ndef+param
      if(ntrust > 3){
        return(list(a="D",trust=trust,ndef=0,ncoop=0,ntrust=ntrust, param=param))
      }else{
        if (ndef > (ceiling(0.5*0.3*20) - trust)){
          return(list(a="D",trust=trust+1,ndef=0,ncoop=0,ntrust=ntrust+4, param=param))
        }else{
          ndef = ndef + 1
          return(list(a="C",trust=trust,ndef=ndef,ncoop=0,ntrust=ntrust, param=param))
        }
      }
    }else{
      if(ntrust > 5){
        return(list(a="D",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1, param=param))
      }else{
        ncoop = ncoop + 1
        return(list(a="C",trust=trust,ndef=0,ncoop=ncoop,ntrust=ntrust-1, param=param))
        if (ncoop==3){
          return(list(a="C",trust=0,ndef=0,ncoop=0,ntrust=ntrust-1, param=param))
        }
      }
    }
  }
}


#' A student strategy
#'
#' Answerstrat to 'seda.strat2' in the High.err Environment
#'
#' @export
antistrat2.High.err <- function(obs, i, t, game, otherD, ...) {
  if (t == 1) {
    return(list(a = "D", otherD = 0))
  }
  if (obs$a[[i]] == "D")
    otherD = otherD + 1
  if (otherD > 3)
    return(list(a = "D", otherD = otherD))
  if (runif(1) < 90) {
    a="C"
  } else {
    a = "D"
  }
  return(nlist(a = a, otherD))
}

#' A student strategy
#'
#' Answerstrat to 'net.nice0' in the High.err Environment
#'
#' @export
el.majestro.incredibile = function(obs,i,t,net.nice=0,...) {
  if (t==1)
    return(nlist(a="C",net.nice))

  # Wie oft habe ich haeufiger C gespielt als mein Partner
  net.nice = net.nice + (obs$a[3-i]=="C") - (obs$a[i]=="C")
  if (net.nice < -1 ) {
    return(nlist("D",net.nice))
  } else {
    return(nlist("C",net.nice))
  }
}

#######################
# 2017 strategies
#######################
#' @export
bot.GraDOS_Ghost.2017 = function(obs,i,t,preObs=c("C","C"),ans="C",preAns="C", count.devious=0,clueless=0,count.obserr=0,...) {

  answer="C"
  j = 3-i

  obserr=FALSE;
  if(preObs[1]=="D" & obs$a[j]=="D" & preAns=="C"){
    obserr=TRUE;
    count.obserr = count.obserr+1
  }

  # Cooperate in the first period
  if (t==1)answer="C"

  # Be forgiving if a previous defection was caused by an observation error.
  # Otherwise play tit-for-tat

  if (obs$a[j]=="C" | obserr){
    if(obs$a[j]=="C" && obserr){ # the other one did not retaliate
      clueless = clueless+1
    }
    answer="C"
  }
  else{
    answer="D"
    if(preObs[1]=="C"){ # I really wanted this to be a nice thing and he saw that
      count.devious = count.devious+1
    }
  }

  if(t>=10){
    if(count.devious/t>0.4){ #the other one is really not nice
      answer="D"
    }
    if(clueless>count.obserr/2){ #more than half of the times there is no retaliation if obs.err
      answer="D"
    }
  }

  preObs=c(obs$a[i],obs$a[j])
  preAns=ans

  return(list(a=answer,preObs=preObs,preAns=ans,ans=answer, count.devious=count.devious, clueless=clueless, count.obserr=count.obserr))
}

#' @export
bot.Legend.2017 = function(obs,i,t,history.opp=0,defectCheck = FALSE,identifCheck = FALSE,shareD = 0,...) {

  j = 3 - i

  # Ab Runde 2 wird eine Historie erstellt und Anteil defect des Gegners berechnet
  if (t != 1){
    history.opp[t-1] = obs$a[j]
    shareD = length(which(history.opp=="D"))/(t-1)
  }

  # Strategie der ersten 7 Runden:

  # Spiele in den Runden 2,3,5 und 7 "D" zur Selbsterkennung (Defect kommt 100% richtig an), ansonsten "C"
  # Zusaetzliche Pruefung  Runde 7: Wurde bislang nur "D" gespielt? --> Keine kooperative Strategie - always.defect - defectCheck aktivieren
  if (t < 8){
    if(t==2){
      return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
    }
    if(t==3){
      return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
    }
    if(t==5){
      return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
    }
    if(t==7){
      if(length(which(history.opp=="D")) == 6){
        defectCheck = TRUE
        return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
      }
      else{
        return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
      }
    }
    else{
      return(list(a="C", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
    }
  }

  # Strategie ab Runde 8:

  # Liegt Anteil "D" ab Runde 14 ueber vorgegebenem Hoechstwert --> unkooperative Strategie: defectCheck aktivieren
  if(t >= 15 & shareD >= 0.75){
    defectCheck = TRUE
    return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
  }

  # Haben wir die eigene Strategie identifiziert, wird nur noch "C" gespielt
  if(identifCheck == TRUE){
    return(list(a="C", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
  }

  # Wenn gegnerische Strategie always.defect oder Aehnliche nicht kooperative Strategie, wird ausschliesslich "D" gespielt
  if(defectCheck == TRUE){
    return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
  }

  # Erkennung der eigenen Strategie: Wurde in Runde 2,3,5 und 7 "D" gespielt: indentifCheck aktivieren
  if (t == 8){
    if(history.opp[2] == "D" & history.opp[3] == "D"){
      if(history.opp[5] == "D" & history.opp[7] == "D"){
        identifCheck = TRUE
      }
    }
  }

  # Gegnerische Strategie ist nicht die eigene und keine unkooperative:
  # Abwechsend "C" und "D" spielen

  # In ungeraden Perioden wird "D" gespielt
  if (t%%2 != 0){
    return(list(a="D", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
  }

  # Trifft keine der Bedingungen zu, wird "C" gespielt
  else{
    return(list(a="C", history.opp = history.opp, defectCheck = defectCheck, identifCheck = identifCheck, shareD = shareD))
  }
}

#' @export
bot.Amateur.2017=function(obs,i,t,p=(c(.9,.1)),x=1,anzahlD=0,...){

  # j beschreibt Index des Gegners
  j=3-i

  # Ged?chtnis mit den gegnerischen Spielz?gen.
  beobachteSpieler2=obs$a[j]

  # Ged?chtnis mit den eigenen Spielz?gen.
  beobachteSpielerMich=obs$a[i]

  #Spiele in der ersten Runde "C".
  if (t==1){
    p=p
    x=x+1 # Erh?he x um eins.
    anzahlD=anzahlD
    return(list(a="C",x=x,p=p,anzahlD=anzahlD))# ?bergebe x,p und anzahlD.
  }

  # Pr?fe
  if( (t>1) && (x==1)){

    # Pr?fe ob Gegner "D" gespielt hat.
    if(beobachteSpieler2=="D"){
      p=p
      x=x+1 #Erh?he x um eins.
      anzahlD=anzahlD # anzahlD wird aus logischen Gr?nden (Verweis:  x=7) nicht erh?ht.

      # Spiele mit Wahrscheinlichkeit p "C" oder "D" und ?bergebe Parameter x, anzahlD.
      return(list(a=sample(c("C","D"),1,replace=TRUE,prob=p),p=p,x=x,anzahlD=anzahlD))
    }

    #Pr?fe ob Gegner "C" gespielt hat.
    if(beobachteSpieler2=="C"){
      p=p
      x=x+1 #Erh?he x um eins.
      anzahlD=anzahlD
      return(list(a="C",p=p,x=x,anzahlD=anzahlD))# Spiele "C" und ?bergebe Parameter x, anzahlD.
    }

  }

  #Pr?fe
  if ((x>=2) && (x<7) ){

    #Spiele, falls Gegner "D" gespielt und wir "C" gespielt haben.
    if(beobachteSpieler2=="D" && beobachteSpielerMich=="C"){
      p=p
      x=x+1 #Erh?he x um eins.
      anzahlD=anzahlD+1 #Erh?he anzahlD um eins.
      return(list(a="D",p=p,x=x,anzahlD=anzahlD))# Spiele "D" und ?bergebe die Parameter.

    }

    #Spiele, falls Gegner "D" gespielt und wir "D" gespielt haben.
    if(beobachteSpieler2=="D" && beobachteSpielerMich=="D"){
      p=p
      x=x+1 #Erh?he x um eins.
      anzahlD=anzahlD+1 #Erh?he anzahlD um eins.
      return(list(a="C",p=p,x=x,anzahlD=anzahlD))#Spiele "C" und ?bergebe Parameter.
    }

    #Spiele, falls Gegner "C" gespielt und wir "C" gespielt haben.
    if(beobachteSpieler2=="C" && beobachteSpielerMich=="C"){
      p=p
      x=x+1 #Erh?he x um eins.
      anzahlD=anzahlD
      return(list(a="C",p=p,x=x,anzahlD=anzahlD)) #Spiele "C" und ?bergebe Parameter.
    }

    #Spiele, falls Gegner "C" gespielt und wir "D" gespielt haben.
    else{
      p=p
      x=x+1 #Erh?he x um eins.
      anzahlD=anzahlD

      return(list(a="C",p=p,x=x,anzahlD=anzahlD)) #Spiele "C"und ?bergebe Parameter.
    }
  }

  #Bestimme p neu.
  p=(c(.9,.1))

  #Pr?fe
  if(x==7){

    #Spiele ah?ngig von Anzahl der gespielten "D"s des Gegeners.

    #Pr?fe
    if((anzahlD >=4) && (anzahlD< (x-2))){
      p=(c(p[1]-.9,p[2]+.9)) #Parameter p wird ver?ndert.
      return(list(a="C",p=p,x=1,anzahlD=0)) #Spiele "C", setze x=1, setze anzahlD=0 und ?bergebe Parameter.
    }

    #Pr?fe
    if((anzahlD >=0) && (anzahlD< (x-3))){
      p=(c(1,0)) #Parameter p wird ver?ndert
      return(list(a="D",p=p,x=1,anzahlD=0)) #Spiele "D", setze x=1, setze anzahlD=0 und ?bergebe Parameter.
    }

    #Pr?fe, ob dauerhaftes "D" des Gegners gespielt wird
    if(anzahlD>= (x-2)){

      #Pr?fe letzte Runde
      if(beobachteSpieler2=="D"){


        return(list(a="D",p=p,x=7,anzahlD=anzahlD))# Gehe in Dauerschleife solange bis Gegner "C" spielt.
      }

      #Pr?fe letzte Runde

      else{
        #Falls letzte Runde "C", gehe aus Dauerschleife raus.

        #Setze x=7, verringere anzahlD um eins und ?bergebe Parameter.
        return(list(a="D",p=p,x=7,anzahlD=anzahlD-1))
      }

    }

  }
}

#' @export
bot.Semi_Pro.2017 = function(obs,i,t,Wir=0,Gegner=0,...) {

  # Spielerindex
  j = 3-i

  # beobachtete Handlung
  if (t>1){
    Wir=obs$a[i]
    Gegner[t-1]=obs$a[j]
  }

  # Kooperiere nicht in der ersten Runde
  if (t==1){
    return(list(a="D",Wir=Wir,Gegner=Gegner))
  }

  # Kooperiere in den Runden 2-8
  if (t>1 & t<=8){
    return(list(a="C",Wir=Wir,Gegner=Gegner))
  }

  # Ged?chtnis der Spielz?ge des Gegner der letzten 8 Runden
  shortmemory=Gegner[(length(Gegner)-7):length(Gegner)]

  # Entscheidungsbaum abh?ngig von unserm Handeln, dem Handeln des Gegner
  # und bei Bedarf das Verhalten des Gegners in den letzten 8 Runden.
  if (Wir=="C") {
    if (Gegner[t-1]=="C") {
      if(length(which(shortmemory=="C"))>7) {
        return(list(a="D",Wir=Wir,Gegner=Gegner))
      } else {
        return(list(a="C",Wir=Wir,Gegner=Gegner))
      }
    } else {
      if (length(which(shortmemory=="D"))>7) {
        return(list(a="D",Wir=Wir,Gegner=Gegner))
      } else {
        return(list(a="C",Wir=Wir,Gegner=Gegner))
      }
    }
  } else {
    if (Gegner[t-1]=="C") {
      return(list(a="D",Wir=Wir,Gegner=Gegner))
    } else {
      if (length(which(shortmemory=="D"))>7) {
        return(list(a="D",Wir=Wir,Gegner=Gegner))
      } else {
        return(list(a="C",Wir=Wir,Gegner=Gegner))
      }
    }
  }
}

#' @export
bot.Beginner.2017 = function(obs,i,t,preObs=c("C","C"),ans="C",preAns="C",...) {

  # Variable Definitions
  answer="C"
  j = 3-i

  # Find out if other player punished me because of an observation error
  obserr=FALSE;
  if(preObs[1]=="D" & obs$a[j]=="D" & preAns=="C"){
    obserr=TRUE;
  }

  # Cooperate in the first period
  if (t==1)answer="C"

  # Be forgiving if a previous defection was caused by an observation error.
  # Otherwise play tit-for-tat

  if (obs$a[j]=="C" | obserr){
    answer="C"
  }
  else{
    if(runif(1)>0.75){
      answer="D"
    }else{
      answer="C"
    }
  }

  preObs=c(obs$a[i],obs$a[j])
  preAns=ans

  return(list(a=answer,preObs=preObs,preAns=ans,ans=answer))
}

#' @export
bot.Expert.2017 = function(obs,i,t, otherC,memoryI=0,memoryJ=0,...) {

  debug.store("tagstrategie",i,t)
  debug.restore("tagstrategie",i=1,t=2)

  # Beschreibt den Index des Gegners

  j = 3-i

  # In der ersten Runde wird Kooperiert

  if (t==1) {
    return(list(a="C",otherC=0,memoryI=memoryI,memoryJ=memoryJ))
  }

  # Ab der zweiten Runde wird ein Ged?chtnis gebildet

  if (t>1){
    memoryI[t-1]=obs$a[i]
    memoryJ[t-1]=obs$a[j]
  }

  # Beobachtete C's werden gez?hlt

  if (obs$a[[j]]=="C") otherC= otherC + 1

  # In den ersten f?nf Runden wird nur kooperiert, wenn die Kooperationsquote (beobachtete C's) ?ber 50% liegt

  if (t<=5 && (otherC/t) > 0.5) {
    return(list(a="C",otherC=otherC,memoryI=memoryI,memoryJ=memoryJ))
  }
  else {return(list(a="D",otherC=otherC,memoryI=memoryI,memoryJ=memoryJ))}

  # Es wird ein Kurzzeitged?chtnis der letzten f?nf Runden erzeugt

  shortmemory=memoryJ[(length(memoryJ)-4):length(memoryJ)]

  # Ab der sechsten Runde wird nur kooperiert, wenn die Kooperationsquote(beobachtete C's) ?ber 50% liegt und in den letzten f?nf Runden mindestens 3 mal C beobachtet wurde.

  if (t>5 && (otherC/t) > 0.5 && length(which(shortmemory=="C"))>=3) {
    return(list(a="C",otherC=otherC,memoryI=memoryI,memoryJ=memoryJ))
  }
  else {return(list(a="D",otherC=otherC,memoryI=memoryI,memoryJ=memoryJ))}


  return(list(a=a,otherC,memoryI=memoryI,memoryJ=memoryJ))

}

#' @export
moneymaker.2017 = function(obs,i,t,own_payoffs=0,...) {

  # Spielernr. berechnen
  j = 3-i

  #################### Strategie ####################

  #kumulierte payoffs aus Observationen berechnen
  if(t>1){
    if(obs$a[i]=="C" && obs$a[j]=="C"){
      own_payoffs[t]<-own_payoffs[t-1]+1
    }

    if(obs$a[i]=="C" && obs$a[j]=="D"){
      own_payoffs[t]<-own_payoffs[t-1]-1
    }

    if(obs$a[i]=="D" && obs$a[j]=="C"){
      own_payoffs[t]<-own_payoffs[t-1]+3
    }

    if(obs$a[i]=="D" && obs$a[j]=="D"){
      own_payoffs[t]<-own_payoffs[t-1]
    }
  }

  # In den ersten 5 Runden kooperieren
  if (t<=5){
    return(list(a="C",own_payoffs=own_payoffs))
  }

  # zufällig zu 5% defect
  if (runif(1)<0.05){
    return(list(a="D",own_payoffs=own_payoffs))
  }

  # kooperieren falls gewünschter payoff erreicht wird
  if(own_payoffs[t]>=0.8*t-5){
    return(list(a="C",own_payoffs=own_payoffs))
  }
  else{
    return(list(a="D",own_payoffs=own_payoffs))
  }

}

#' @export
wallstreetstones.2017 =function (obs,i,t,memoryI=0,memoryJ=0,realmemoryI=0,shortmemoryJ=0,shortmemoryI=0,...){

  # calculate opponent's player index
  j = 3-i

  # memory yours and opponents observation action
  if (t>1){
    memoryI[t-1]=obs$a[i]
    memoryJ[t-1]=obs$a[j]
  }

  # defect in 1st round
  if (t==1){
    realmemoryI[1]="D"
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
  }

  # defect in every sixth round
  if (t%%6==0) {
    realmemoryI[t]="D"
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
  }

  # create a short memory of the last 15 opposite observations
  if (t>15){
    shortmemoryJ=memoryJ[(length(memoryJ)-15):length(memoryJ)]
    shortmemoryI=memoryI[(length(memoryI)-15):length(memoryI)]
  }
  #if the oppenent observed more than 10 cooperations in the last 15 rounds return defect (use the bonus)
  if (t>15){
    if(length(which(shortmemoryI=="D"))<=4){
      realmemoryI[t]="D"
      return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
    }
  }

  # check the strictness of your opponent's strategy (punish for strict strategy)
  if(length(which(shortmemoryI=="D"))<=5){
    if(length(which(shortmemoryJ=="D"))>=6){
      realmemoryI[t]="D"
      return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
    }
    else {
      realmemoryI[t]="C"
      return(list(a="C",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
    }
  }

  # if in the last 15 observations more than 7 times was defect, than defect in every 2nd round
  if(length(which(shortmemoryJ=="D"))>=8){
    if (t%%2==0) {
      realmemoryI[t]="D"
      return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
    }
  }

  #if in the last 15 observations 11 times or more we observed defect, then we defect
  if(length(which(shortmemoryJ=="D"))>=11){
    realmemoryI[t]="D"
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
  }

  #if none of the above is observed then coop
  realmemoryI[t]="C"
  return(list(a="C",memoryI=memoryI,memoryJ=memoryJ,realmemoryI=realmemoryI,shortmemoryJ=shortmemoryJ,shortmemoryI=shortmemoryI))
}

#' @export
waning.generosity.2017 = function(obs,i,t,...) {

  j=3-i

  score = max(100-4*t,-20)

  if(obs$a[j]=="C"){
    score = score + 100
  }

  if (runif(1)*100 < score){
    return(list(a="C"))
  }

  return(list(a="D"))
}

#' @export
slowpoke = function(obs,i,t,buffer="X",...) {

  j = 3-i

  # Always cooperate in the first two rounds
  if (t==1){
    return(list(a="C",buffer=buffer))
  }

  if (t==2){
    return(list(a="C",buffer=obs$a[j]))
  }

  return(list(a=buffer,buffer=obs$a[j]))

}

#' @export
categorizer.2017 = function(obs,i,t,previousAction="X",righteous=0,malicious=0,deplorable=0,...){

  j=3-i

  # Categorize the opponents behaviour
  if(t>2){
    if(previousAction=="C" && obs$a[j]=="C")
      righteous=righteous+1

    if(previousAction=="D" && obs$a[j]=="D")
      righteous=righteous+1

    if(previousAction=="C" && obs$a[j]=="D")
      malicious=malicious+1

    if(previousAction=="D" && obs$a[j]=="C")
      deplorable=deplorable+1
  }

  if(t>1)
    previousAction=obs$a[i]

  # Gather Data in the first ten rounds by playing random stuff
  if (t<10){
    if(runif(1)>0.25){
      return(list(a="C",previousAction=previousAction,righteous=righteous,malicious=malicious,deplorable=deplorable))
    }
    return(list(a="D",previousAction=previousAction,righteous=righteous,malicious=malicious,deplorable=deplorable))
  }

  # Play according to the collected data

  if(righteous>=malicious && righteous>=deplorable){
    return(list(a="C",previousAction=previousAction,righteous=righteous,malicious=malicious,deplorable=deplorable))
  }
  return(list(a="D",previousAction=previousAction,righteous=righteous,malicious=malicious,deplorable=deplorable))

}

#' @export
scorer.2017 = function(obs,i,t,previousAction="X",score=0,...){

  j=3-i

  # Score the opponents behaviour
  if(t>2){
    if(previousAction=="C" && obs$a[j]=="C")
      score = score + 10

    if(previousAction=="D" && obs$a[j]=="D")
      score = score + 0

    if(previousAction=="C" && obs$a[j]=="D")
      score = score - 20

    if(previousAction=="D" && obs$a[j]=="C")
      score = score + 15
  }

  if(t>1)
    previousAction=obs$a[i]

  # Gather Data in the first ten rounds by playing random stuff
  if (t<10){
    if(runif(1)>0.15){
      return(list(a="C",previousAction=previousAction,score=score))
    }
    return(list(a="D",previousAction=previousAction,score=score))
  }

  # Play alway-coop, tit-for-tat or always-defect depending on score

  if(score>25){
    return(list(a="C",previousAction=previousAction,score=score))
  }

  if(score>-25 && obs$a[j]=="C"){
    return(list(a="C",previousAction=previousAction,score=score))
  }

  return(list(a="D",previousAction=previousAction,score=score))

}

#' @export
three.of.five.2017 = function(obs,i,t,memoryI=0,memoryJ=0,...) {

  # calculate opponent's player index
  j = 3-i

  # from period two onward, store each decision in the memory parameters
  if (t>1){
    memoryI[t-1]=obs$a[i]
    memoryJ[t-1]=obs$a[j]
  }

  # cooperate in the first five rounds
  if (t<=5){
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ))
  }

  # create a short term memory of the five most recent decisions
  shortmemory=memoryJ[(length(memoryJ)-4):length(memoryJ)]

  # make a decision depending on this short term memory
  if(length(which(shortmemory=="C"))>=3){
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ)) # cooperate for 3, 4 or 5 out of 5
  } else {
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ)) # defect for 0, 1 or 2 out of 5
  }

}

#' @export
talion.2017 = function(obs,i,t,memoryI=0,memoryJ=0,goodness=0,...) {

  # calculate opponent's player index
  j = 3-i

  # from period two onward, store each decision in the memory parameters
  if (t>1){
    memoryI[t-1]=obs$a[i]
    memoryJ[t-1]=obs$a[j]
  }

  # cooperate in the first five rounds
  if (t<=5){
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ,goodness=goodness))
  }

  # create a short term memory of the five most recent decisions
  shortmemory=memoryJ[(length(memoryJ)-4):length(memoryJ)]

  # create a five period cycle
  subperiod=(t-1)%%5

  # at the beginning of a cycle, tally the opponents cooperations
  # in the previous cycles
  if(subperiod==0){
    goodness=length(which(shortmemory=="C"))
  }

  # Be a bit generous if 4/5 cooperations are detected
  if(goodness==4)goodness=5

  # Opponent receives what he sow
  if(goodness>=subperiod){
    return(list(a="C",memoryI=memoryI,memoryJ=memoryJ,goodness=goodness))
  } else {
    return(list(a="D",memoryI=memoryI,memoryJ=memoryJ,goodness=goodness))
  }

}

##########
# Strategys for special testing purposes
##########
#' @export
tft.2forgive <- function(obs, i, t, game, state="no.info", ...) {

  if (t == 1)
    return(list(a = "C", state = "no.info"))

  j = 3 - i

  observ=obs$a[j]

  if(observ=="D"){
    if(state=="no.info"||state=="C"||state=="D"||state=="CCD"){
      return(list(a = "D", state = "D"))
    }
    if(state=="CC"){
      return(list(a = "C", state = "CCD"))
    }
  }

  if(observ=="C"){
    if(state=="no.info"||state=="D"||state=="CCD"){
      return(list(a = "C", state = "C"))
    }
    if(state=="C"||state=="CC"){
      return(list(a = "C", state = "CC"))
    }
  }
}

#' @export
tft.2forgive.counter <- function(obs, i, t, game, state="no.info", ...) {

  if (t == 1)
    return(list(a = "C", state = "no.info"))

  observ=obs$a[i]

  if(observ=="D"){
    if(state=="no.info"||state=="C"||state=="D"||state=="CCD"){
      return(list(a = "C", state = "D"))
    }
    if(state=="CC"){
      return(list(a = "C", state = "CCD"))
    }
  }

  if(observ=="C"){
    if(state=="no.info"||state=="D"||state=="CCD"){
      return(list(a = "C", state = "C"))
    }
    if(state=="C"){
      return(list(a = "D", state = "CC"))
    }
    if(state=="CC"){
      return(list(a = "D", state = "CC"))
    }
  }
}

#' Strategy highlighting differences in Exploration
#' states are "no.info", "is.nice" [after first 10 rounds], "is.mean" [if defect in first 10 rounds]
#' @export
compare.exploration <- function(obs, i, t, game, state="no.info", ...) {

  ignore.defect <- c(11,15,17,23,26,28,30,34,37,38,40,51,53,56,58)

  if (t == 1)
    return(list(a = "C", state = "is.nice"))

  j = 3 - i
  observ=obs$a[j]
  my.action <- NULL

  if(t<=10 && observ=="D"){
    state="is.mean"
  }

  #Opponent always played nice in the first 10 rounds
  if(state=="is.nice" && t %in% ignore.defect){
    my.action <- "C"
  }

  if(state=="is.nice" && !(t %in% ignore.defect)){
    my.action <- observ #Tit for tat outside of special rounds
  }

  if(state=="is.mean"){
    my.action <- "D"
  }

  return(list(a = my.action, state = state))
}

#' @export
grim.trigger <- function(obs, i, t, game, state="not.triggered", ...) {

  if (t == 1)
    return(list(a = "C", state = "not.triggered"))

  j = 3 - i
  observ=obs$a[j]
  my.action <- NULL

  if(observ=="D"){
    state="triggered"
  }

  if(state=="triggered"){
    my.action <- "D"
  } else {
    my.action <- "C"
  }

  return(list(a = my.action, state = state))
}

#' @export
counter.grim.trigger <- function(obs, i, t, game, state="not.triggered", ...) {
  debug.store("counter.grim.trigger",i,t)
  debug.restore("counter.grim.trigger",i=1,t=7)

  if (t == 1)
    return(list(a = "C", state = "not.triggered"))

  j = 3 - i
  observ.other =obs$a[j]
  observ.me <- obs$a[i]

  if(observ.me=="D"){
    state="triggered"
  }

  if(state=="triggered"){
    my.action <- "D"
  } else {
    my.action <- "C"
  }

  return(list(a = my.action, state = state))
}

#' @export
generous.tit.for.tat <- function(obs, i, t, game, c=0.1, ...) {
  if (t == 1)
    return(list(a = "C", c = c))

  j = 3 - i
  observ=obs$a[j]
  my.action <- NULL

  if(runif(1)<c){
    return(list(a = "C", c=c))
  } else {
    return(list(a = observ, c=c))
  }
}

#' @export
contrite.tit.for.tat.Axelrod <- function(obs, i, t, game, contrite=FALSE, hist.want=c(), hist.obs=c(),...) {
  debug.store("contrite.tit.for.tat",i,t)
  debug.restore("contrite.tit.for.tat",i=1,t=7)

  if (t == 1){
    hist.want[t] = "C"
    return(nlist(a = "C", contrite, hist.want, hist.obs))
  }

  j = 3 - i
  observ <- obs$a[j]
  my.action <- obs$a[i]
  hist.obs[t-1] <- my.action


  if(contrite && my.action=="C"){ #Apology successful
    contrite <- FALSE
    hist.want[t] <- "C"
    return(nlist(a = "C", contrite, hist.want, hist.obs))
  }

  if(hist.want[t-1]!=hist.obs[t-1]){ #Noise
    if(my.action=="D" && observ == "C"){ #bad noise - i want to apologise
      contrite <- TRUE
    }
  }

  #Play Tit.for.Tat
  hist.want[t] <- observ
  return(nlist(a =  observ, contrite, hist.want, hist.obs))
}

#' @export
contrite.tit.for.tat <- function(obs, i, t, game, status="content",...) {
  debug.store("contrite.tit.for.tat.alternative",i,t)
  debug.restore("contrite.tit.for.tat.alternative",i=1,t=7)

  old.status <- status

  if (t == 1){
    return(nlist(a = "C", status))
  }

  j = 3 - i
  his.action <- obs$a[j]
  my.action <- obs$a[i]

  if(his.action=="D" && my.action=="C"){
    if(old.status=="content"){
      status <- "provoked"
    }
  }

  if(his.action=="C"){
    if(old.status=="provoked"){
      status <- "content"
    }
  }

  if(his.action=="C"&&my.action=="D"){
    if(old.status=="content"){
      status <- "contrite"
    }
  }

  if(my.action=="C"){
    if(old.status=="contrite"){
      status <- "content"
    }
  }

  if(status=="content"||status=="contrite"){
    return(nlist(a = "C", status))
  } else { #status is provoked
    return(nlist(a = "D", status))
  }
}

#' @export
counter.contrite.tit.for.tat <- function(obs, i, t, game, status="content", ...) {
  debug.store("contrite.tit.for.tat.alternative",i,t)
  debug.restore("contrite.tit.for.tat.alternative",i=1,t=7)

  old.status <- status

  if (t == 1){
    return(nlist(a = "C", status))
  }

  j = 3 - i
  his.action <- obs$a[j]
  my.action <- obs$a[i]

  if(my.action=="D" && his.action=="C"){
    if(old.status=="content"){
      status <- "provoked"
    }
  }

  if(my.action=="C"){
    if(old.status=="provoked"){
      status <- "content"
    }
  }

  if(my.action=="C"&&his.action=="D"){
    if(old.status=="content"){
      status <- "contrite"
    }
  }

  if(his.action=="C"){
    if(old.status=="contrite"){
      status <- "content"
    }
  }

  if(status=="content"||status=="provoked"){
    return(nlist(a = "C", status))
  } else { #status is contrite
    return(nlist(a = "D", status))
  }
}



#' @export
pavlov <- function(obs, i, t, game, ...) {
  if (t == 1)
    return(list(a = "C"))

  j = 3 - i
  observ <- obs$a[j]
  my.action <- obs$a[i]

  if(observ=="C" && my.action == "C") return(list(a = "C"))
  if(observ=="C" && my.action == "D") return(list(a = "D"))
  if(observ=="D" && my.action == "C") return(list(a = "D"))
  if(observ=="D" && my.action == "D") return(list(a = "C"))
}
MartinKies/USLR documentation built on Nov. 10, 2019, 5:24 a.m.