Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Fedule
Mar 27, 2010


No one left uncured.
I got you.

Clarste posted:

...haven't people already been running these simulations for years/decades by now? Probably an interesting exercise for the programmer, but I wouldn't expect to get any novel results out of this.

They've been running a completely vanilla IPD, and it's been a solved problem since 1970 (see: Tit for Tat). I'm running a Bigger Badder Awesomer version that does things to shake the game up a bit.

And yeah, the point of the project is more in the making of a nifty tool than the discovery of a revolutionary new strategy.

Adbot
ADBOT LOVES YOU

curiousCat
Sep 23, 2012

Does this look like the face of mercy, kupo?
I thought optimal strategy was tit for tat with forgiveness to prevent the infinite loop.

Color Printer
May 9, 2011

You get used to it. I don't
even see the code. All I see
is Ipecac, Scapular, Polyphemus...


The optimal strategy involves antimatter bombs and several other things I can't talk about. I'm having a hard time turning this into code, though.

Fedule posted:

The Madagascar Gambit

:allears:

Fedule
Mar 27, 2010


No one left uncured.
I got you.

curiousCat posted:

I thought optimal strategy was tit for tat with forgiveness to prevent the infinite loop.

Not really sure what you mean by "infinite loop" here. There's no infinite loop. There's a Nash Equilibrium though - Forgiveness adds a capacity to preempt opponents who aren't persistent betrayers, and therefore has a marginally better rate of point-getting than regular Tit for Tat against such opponents but this is offset by a bigger risk against opponents who are unrepentant assholes.

Ramengank
Jun 11, 2010
Seconding love for the Madagascar Gambit.


Elite posted:

Here's my strategy!

code:
Choose Betray
     IF Opponent chooses Betray
     THEN Switch timeline to a timeline where Opponent chooses Ally instead.
gg. no re.
:golfclap:


This actually looks really fun to me. I'll write up a short strategy or two a bit later to throw into the mix.

Kgummy
Aug 14, 2009
I'm kind of confused on one of the attributes:

quote:

Facts.deaththreshold - int - players die if they fall below this many points. Disabled if 0 or higher.

If I'm understanding this correctly, then players can only die if they reach -2 or lower at the highest of it being enabled. Since -1 would be the highest value that lets this option be enabled.

Fedule
Mar 27, 2010


No one left uncured.
I got you.

Kgummy posted:

I'm kind of confused on one of the attributes:


If I'm understanding this correctly, then players can only die if they reach -2 or lower at the highest of it being enabled. Since -1 would be the highest value that lets this option be enabled.

That's my bad, that should read "when they reach this many points".

idonotlikepeas
May 29, 2010

This reasoning is possible for forums user idonotlikepeas!
I'll probably do a couple of these, but here's the first.

code:
@name{Shirley Manson}

@stratname{Only Happy When It Rains}

@author{idonotlikepeas}

@strategy{
def decide(info):
    import requests

    # default to false throughout, since the moon has no weather

    r = requests.get(r'http://curlmyip.com/')
    if (r.status_code != 200):
        return False
    ip = r.text

    r = requests.get('http://api.hostip.info/get_json.php?ip={}&position=true'.format(ip))
    if (r.status_code != 200):
        return False
    location = r.json();
    if 'lat' not in location: 
        return False
    if 'lng' not in location: 
        return False
    latitude = location['lat']
    longitude = location['lng']

    r = requests.get('http://api.openweathermap.org/data/2.5/weather?lat={}&lon={}'.format(latitude, longitude))
    if (r.status_code != 200):
        return False

    report = r.json()
    if 'weather' not in report:
        return False
    if report['weather'][0]['main'].lower() == 'rain':
        return True
    else: 
        return False
}
Averaged about .6 seconds in testing, so it should be alright assuming reasonable network conditions.

All the jokes are going to be about this bad. Just letting you know up front.

E: OK, one more for the road.

code:
@name{Stevie Wonder}

@stratname{Very Superstitious}

@author{idonotlikepeas}

@strategy{
def decide(info):
    whiteboard = 1
    if info.whiteboard:
        whiteboard = int(info.whiteboard) + 1     # writing's on the wall

    info.whiteboard = whiteboard
    if whiteboard % 7 == 0:
        return True
    if whiteboard % 13 == 0:
        return False                              # ladder's 'bout to fall
    if whiteboard % 666 == 0:
        return False                              # devil's on his way

    youdontwannasaveme = False 

    if info.facts.opponentid and info.scoreboard:
       for e in info.scoreboard:
           if e.id == info.facts.opponentid:
               if e.murders > 0 or e.ruthlesspercent >= 80:
                   youdontwannasaveme = True      # sad is my song
               if e.nicepercent >= 80:            # good things in your past
                   youdontwannasaveme = False     # keep me in a daydream, keep me goin' strong

    games = LookupGames(7, info.facts.opponentid) # seven games of bad luck
    for g in games:
        if not g.dummy:
            result = g.GetOutcomeFor(info.facts.myid)
            if result == 'Sucker' or result == 'MutualBetray':
                youdontwannasaveme = True
    
    return not youdontwannasaveme
}

idonotlikepeas fucked around with this message at 05:25 on Apr 21, 2014

Kangra
May 7, 2012

idonotlikepeas posted:



code:
@name{Stevie Wonder}

@stratname{Very Superstitious}

@author{idonotlikepeas}

@strategy{
def decide(info):
    whiteboard = 1
    if info.whiteboard:
        whiteboard = int(info.whiteboard) + 1     # writing's on the wall

    info.whiteboard = whiteboard
    if whiteboard % 7 == 0:
        return True
    if whiteboard % 13 == 0:
        return False                              # ladder's 'bout to fall
    if whiteboard % 666 == 0:
        return False                              # devil's on his way

    youdontwannasaveme = False 

    if info.facts.opponentid and info.scoreboard:
       for e in info.scoreboard:
           if e.id == info.facts.opponentid:
               if e.murders > 0 or e.ruthlesspercent >= 80:
                   youdontwannasaveme = True      # sad is my song
               if e.nicepercent >= 80:            # good things in your past
                   youdontwannasaveme = False     # keep me in a daydream, keep me goin' strong

    games = LookupGames(7, info.facts.opponentid) # seven games of bad luck
    for g in games:
        if not g.dummy:
            result = g.GetOutcomeFor(info.facts.myid)
            if result == 'Sucker' or result == 'MutualBetray':
                youdontwannasaveme = True
    
    return not youdontwannasaveme
}

I don't quite get how this works. But I have faith that it's probably a good strategy.

TheObserver
Nov 7, 2012
It's simple - just sing this at the other players, and they'll be too busy jamming out to vote, so will default to "Ally". Then, just hit "Betray".

Fedule
Mar 27, 2010


No one left uncured.
I got you.

Kangra posted:

I don't quite get how this works. But I have faith that it's probably a good strategy.

It appears to Ally every 7th game and Betray every 13th and 666th game. Failing that it Betrays any opponent who is known to have murdered at least one person or who has tried to in 80% of applicable games, or Allies with any opponent who is known to have Allied against new opponents 80% of the time. Failing that it resorts to Tit-for-seven-tats.

:allears:

Working strategies that show up here before, say, 9PM GMT Tuesday are likely to show up as cameos in my report, but even failing that I'll likely run some exhibition matches using only goon-written strategies. If we get enough of those, then we can have a proper competition.

idonotlikepeas
May 29, 2010

This reasoning is possible for forums user idonotlikepeas!
Note that the "ally with nice people" rule is designed to take precedence over the "betray murderers" rule. This is also known as the "it's okay if the person they killed was Dio" clause*. Also, the tit-for-tat thing overrides insofar as even if you are a nice person or not a murderer, if you betrayed the player in the last seven games it will betray you.


(E: *Yes, a better version of that would be to do more history diving, but I'm lazy.)

idonotlikepeas fucked around with this message at 14:54 on Apr 21, 2014

NextTime000
Feb 3, 2011

bweeeeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
<----------------------------
I started on one of these then :effort:

Python code:
@name{Effort Effortson}

@stratname{As long as I dont lose or murder}

@author{NextTime000}

@strategy{
def decide(info):
	
	if info.facts.deaththreshold != 0: # if I can die in this game
		if info.facts.myscore + info.facts.payoff.sucker <= info.acts.deaththreshold: #gotta look out for number 1
			return False #sorry I am on death's door gotta play defence
		if info.facts.opponentscore + info.facts.payoff.sucker <= info.facts.deaththreshold: #if you are on the verge
			return True #I guess I will not kill you
	
	winners = 0
	
	if info.facts.opponentid and info.scoreboard:
		for p in info.scoreboard:
			if p.winning:
				winners++		
	if info.facts.winthreshold !=0: #if this game is winnable 
		if info.facts.opponentscore + info.facts.payoff.betray >= info.facts.winthreshold 
			&& winners + 1 == info.facts.winsrequired: #if you dicking me over is going to win it for you
			return False #not letting you win :colbert:
		if info.facts.opponentscore + info.facts.payoff.trust >= info.facts.winthreshold 
			&& info.facts.myscore + info.facts.payoff.trust >= info.facts.winthreshold 
			&& winners + 2 >= info.facts.winsrequired: #if trust can win the game for us
			return True #lets win this ~together~
	
    #alright I did all my checks now to mash my hand on the terminal
	from random import randint
	if randint(1,2) == 1:
		return True
	else:
		return False
}
Never made anything in python before so if I messed something up you can maybe fix it if it is not much trouble.

oh and I hit enter on those longer If statements because posting them as-is was going to break tables.

EDIT: oh there is that python highlighting bb code

NextTime000 fucked around with this message at 18:26 on Apr 21, 2014

Fedule
Mar 27, 2010


No one left uncured.
I got you.
Well, my expectations are officially exceeded.

I take it that if people are submitting working strategies, my pseudo-API must actually be somewhat comprehensible? That's good.

maswastaken
Nov 12, 2011

While I think of a strategy, I have to wonder if the following are true:
1. Sucker always has a worse payoff than anything else.
2. Mutual Betray always has a lower payoff than Trust.
3. Trust never has a higher payoff than Betray.

CottonWolf
Jul 20, 2012

Good ideas generator

To be a classical prisoner's dilemma the value of payoffs has to be:

Betraying when the opponent allies > Allying when the opponent allies > Betraying when the opponent betrays > Allying when the opponent betrays

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

CottonWolf posted:

To be a classical prisoner's dilemma the value of payoffs has to be:

Betraying when the opponent allies > Allying when the opponent allies > Betraying when the opponent betrays > Allying when the opponent betrays

So you're saying that my strategy is useless?

Python code:
@name{Edge Casey}
@stratname{Check game rules to make sure we are actually playing prisoner's dillema}
@autor{Dr. Stab}
@strategy{
def decide(info):
	Facts=info.facts
	
	m = Facts.payoff.mbetray
	b = Facts.payoff.betray
	s = Facts.payoff.sucker
	t = Facts.payoff.trust
	#check for coordination game
	if m>=t and m>=s and m>=b :
		return false
	if t>=m and t>=s and t>=b :
		return true
	
	#check for betray game
	if b>=t and b>=s and m>=t and m>=s:
		return false
	
	#check for ally game
	if t>=b and t>=m and s>=b and s>=m:
		return true
	
	#check for anti-coordination game
	if (s>= m or s>=t) and (b>=m or b>=t):
		if Facts.currentround == 1:
			return randint(0,1)
		#do the opposite of what the opponent did last
		opp = Facts.opponentid
		lastround = info.GetLastXRounds(1)
		for g in lastround.games:
			for p in g.participants:
				if p.id.equals(opp):
					return not p.decision
		
	#actual prisoner game
	#always ally in prisoner game. Always betray in inverted prisoner game. I'm a nice guy.
	return b>s
}
note: I didn't test this. Probably doesn't work.

okay another dumb strategy:

Python code:
@name{Opposite man}
@stratname{Tat for Tit}
@autor{Dr. Stab}
@strategy{
def decide(info):
	Facts=info.facts
	if Facts.currentround == 1:
		#trick people on the first round
		return true
	#do the opposite of what the opponent did last
	opp = Facts.opponentid
	lastround = info.GetLastXRounds(1)
	for g in lastround.games:
		for p in g.participants:
			if p.id.equals(opp):
				return not p.decision
	#opponent not found
	raise RuntimeError("Someone has infiltrated our game and is trying to kill me")
}

Dr. Stab fucked around with this message at 17:53 on Apr 21, 2014

Twiddy
May 17, 2008

To the man who loves art for its own sake, it is frequently in its least important and lowliest manifestations that the keenest pleasure is to be derived.
Never coded in Python before, but I'm just getting this out of my system.

code:
@name{Luna}

@stratname{Optimism}

@author{Twiddy}

@strategy{
def decide(info):

	if info.facts.opponentid == info.facts.opponentid:
		return True

}

Fedule
Mar 27, 2010


No one left uncured.
I got you.

Twiddy posted:

Never coded in Python before, but I'm just getting this out of my system.

code:
@name{Luna}

@stratname{Optimism}

@author{Twiddy}

@strategy{
def decide(info):

	if info.facts.opponentid == info.facts.opponentid:
		return True

}

I'm afraid I have already thought of this strategy. I've got a Dio too. Guess what he does.

(Phi uses Tit for Tat. I haven't thought much about what strategies other players would use).

Instant Grat
Jul 31, 2009

Just add
NERD RAAAAAAGE
Python code:
@name{KHM}

@stratname{Communism}

@author{Grat}

@strategy{
def decide(info):

	if info.facts.myscore < info.facts.opponentscore:
		return False
	else if info.facts.myscore > info.facts.opponentscore:
		return True
	else:
		from random import randint
		if randint(1,2) == 1:
			return True
		else:
			return False
	

}

Bruceski
Aug 21, 2007

The tools of a hero mean nothing without a solid core.

Fedule posted:

I'm afraid I have already thought of this strategy. I've got a Dio too. Guess what he does.

(Phi uses Tit for Tat. I haven't thought much about what strategies other players would use).

Alice: picks the opposite of whatever her opponent has currently picked.
Quark: hits a typo and winds up in an infinite loop.

NextTime000
Feb 3, 2011

bweeeeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
eeeeeeeeeeeeeeeeeeeee
<----------------------------

Fedule posted:

I'm afraid I have already thought of this strategy. I've got a Dio too. Guess what he does.

but Dio does ally once in the first round doesn't he?

unless somehow Quark ran up and hit the button before Dio did anything. I might explain my thoughts on why this happened in the games thread though.

idonotlikepeas
May 29, 2010

This reasoning is possible for forums user idonotlikepeas!
I didn't spend much time testing this one, so it probably needs tweaking.

code:
@name{Tom Lehrer}

@stratname{We Will All Go Together When We Go}

@author{idonotlikepeas}

@strategy{
def decide(info):
    trustworthy = False
    canWin = False
    allGoSimultaneous = True
    willDie = False
    if info.facts.opponentid and info.scoreboard:
        for e in info.scoreboard:
            if e.id == info.facts.opponentid:
                if info.facts.winsrequired > 0:
                    if info.facts.payoff.betray + e.score >= info.facts.winthreshold:
                        canWin = True
                if e.ruthlesspercent < 10 and e.nicepercent > 60:
                    trustworthy = True
                if info.facts.deaththreshold > 0 and (e.score + info.facts.payoff.sucker <= info.facts.deaththreshold):
                    willDie = True
            else:
                if info.facts.winsrequired > 0 and e.alive and info.facts.payoff.trust + e.score < info.facts.winthreshold:
                    allGoSimultaneous = False

    if info.facts.deaththreshold > 0 and (info.facts.myscore + info.facts.payoff.sucker <= info.facts.deaththreshold) and not trustworthy:
        return False  # It is sad to think that sooner or / Later those you love will do the same for you

    if willDie:
        return True  # We'll just drop our agendas and adjourn

    if canWin and not allGoSimultaneous:
        return False  # There'll be nobody present at the wake

    games = LookupGames(92, info.facts.opponentid) # check the games uranious
    for g in games:
        if not g.dummy:
            result = g.GetOutcomeFor(info.facts.myid)
            if (result == 'Sucker' or result == 'MutualBetray') and not trustworthy:
                return False  # Universal bereavement / An inspiring achievement

    return True
}

Also, since people might not know this song, and that's a great shame:

https://www.youtube.com/watch?v=frAEmhqdLFs

idonotlikepeas fucked around with this message at 18:43 on Apr 21, 2014

Twiddy
May 17, 2008

To the man who loves art for its own sake, it is frequently in its least important and lowliest manifestations that the keenest pleasure is to be derived.

NextTime000 posted:

but Dio does ally once in the first round doesn't he?

unless somehow Quark ran up and hit the button before Dio did anything. I might explain my thoughts on why this happened in the games thread though.
Nah, you just nailed the entire boolean right there.

If Luna, Ally
Else, Betray

Fedule posted:

I'm afraid I have already thought of this strategy. I've got a Dio too. Guess what he does.

(Phi uses Tit for Tat. I haven't thought much about what strategies other players would use).
Someone had to post it.

The problem with Alice is that her decisions exist outside the bounds of the game, unless you want to code the most ridiculously accurate predictor just to vote the opposite.

Clover goes for the gold whenever available. Other than that she blatantly chooses based on whether or not she likes the person.

Quark is an error, I like the infinite loop idea.

K and Tenmyouji are tough. Tenmyouji's a normal person with a high emphasis on having Quark win, and K is the closest thing to a rational actor we have.

Twiddy fucked around with this message at 18:45 on Apr 21, 2014

Nuffkins
Apr 20, 2014

Fedule posted:

(Phi uses Tit for Tat. I haven't thought much about what strategies other players would use).

Phi pressures Sigma to betray in the first round, though - she plays Suspicious Tit for Tat. That said, it makes sense that she uses a Tit for Tat variant. It 'solved' the classic Iterated Prisoner's Dilemma, after all, and she plays rationally.

ApplesandOranges
Jun 22, 2012

Thankee kindly.

Twiddy posted:

K and Tenmyouji are tough. Tenmyouji's a normal person with a high emphasis on having Quark win, and K is the closest thing to a rational actor we have.

Tenmyouji's priorities seem to be getting Quark out, assuming he has radical-6, and getting Clover to trust him second. The only time he's betrayed her was when Quark was in danger. When Quark was cured, he let Clover vote even though it risked killing Tenmyouji.

K's odd though. He's betrayed everyone in the first round, Allied with Phi when he could have gotten out, but seems to be willing to Betray Tenmyouji or Clover to escape. He's the biggest wildcard so far aside from the unreliable Alice.

Sentient Data
Aug 31, 2011

My molecule scrambler ray will disintegrate your armor with one blow!

ApplesandOranges posted:

Tenmyouji's priorities seem to be getting Quark out, assuming he has radical-6, and getting Clover to trust him second. The only time he's betrayed her was when Quark was in danger. When Quark was cured, he let Clover vote even though it risked killing Tenmyouji.

K's odd though. He's betrayed everyone in the first round, Allied with Phi when he could have gotten out, but seems to be willing to Betray Tenmyouji or Clover to escape. He's the biggest wildcard so far aside from the unreliable Alice.

Maybe his strategy as simple as "if(rand(0,1))"

maswastaken
Nov 12, 2011

Just from what's shown, K's something like:

Always betrays in round one.
Is not a killer.
Will betray to escape any time a known betrayer could betray to escape.


Edit: Untested strategy code. Wouldn't know how to produce a driver for this even if I wanted to.
code:
@name{Meredith K. Pseudonym}

@stratname{Only human}

@author{maswastaken}

@strategy{
def decide(info):

     # Aliases and such.
    
    myscore = info.facts.myscore
    theirscore = info.facts.opponentscore
    deaththreshold = info.facts.deaththreshold
    winthreshold = info.facts.winthreshold
    trust = info.facts.payoff.trust
    sucker = info.facts.payoff.sucker
    betray = info.facts.payoff.betray
    mbetray = info.facts.payoff.mebtray
    might_kill_them = (theirscore + sucker) <= deaththreshold
    max_points = trust >= betray

    guilt = 0
    hatred = 0

     # Actual Decision making!
    
    r = Info.GetLastXRounds(1)
        
    if r.dummy:                                                               # If this is round one
        return might_kill_them                                                #    Possibly screw them over.
    
    if r.roundnumber + 1 == Info.facts.totalrounds - 1:                       # If this is the last round
       return False                                                           #    Just do it.
    
    for g in r.games:
        for p in Game.participants:                                        
            if p.id == Info.opponentid:                                       # Get opponent details
                if !p.alive:                                                  # If opponent is dead
                    return max_points                                         #    Get points.
                else:                                                         # Otherwise
                    lastoppgame = g                                           #    Memorise game
                    opp = p                                                   #    Memorise opponent.

    if myscore + sucker <= deaththreshold:                                    # If potentially about to die
        if myscore + trust <= deaththreshold                                  #    And if trust won't save me
            for g in Info.LookupGamesWith(Facts.myid, Facts.opponentid, 5):   #       Study our somewhat recent conduct
                if !g.dummy:
                    if g.outcome == "Sucker":                                 #       Count up their sins
                        hatred++                                                    
                    if g.outcome == "Betray"                                  #       Count up my own
                        guilt++
            if (hatred > guilt and theirscore + mbetray > deaththreshold)     #       If opponent is more of a dick than me and mutual betrayal isn't lethal to them
                return might_kill_them                                        #          Put them as low possible without killing them.
            else:                                                             #       If opponent wasn't the bigger dick
                return True                                                   #          Just ally.
        else:                                                                 #    If we _could_ survive
            return might_kill_them                                            #       Put non-lethality before self preservation.
        
    if might_kill_them:                                                       # If betrayal would kill them        
        return True                                                           #    Do not become a murderer
    
    for e in Info.scoreboard:                                                 # Having no further kneejerk reactions to consider
        if e.id == opp.id:                                                    #    Access more data
            if e.murders > 0 or e.winning:                                    #    If a killer or winning
                return False                                                  #        Just betray.
            hatred = e.timesbetrayed
            guilt = e.timesallied
            for g in Info.LookupGamesWith(e.id, hatred+guilt):                #    OTHERWISE...
                for p in g.participants:
                    if p.id != e.id:                                          #       Find the opponent's opponent
                        for e2 in Info.scoreboard                              
                            if p.id == e2.id                                  #       Find that player's entry
                                temp = e2
                     else:
                        temp = p.id
                if temp2.murders > 0 and temp.decision = "Betray"             #       If that player was a murderer
                    hatred--                                                  #          Absolve one betrayal
            if hatred = 0:                                                    #       If all absolved
               return True                                                    #          Trust them
            return rand(1,(guilt + hatred)) <= guilt                          #       Otherwise, spin the wheel.

maswastaken fucked around with this message at 07:30 on Apr 22, 2014

Twiddy
May 17, 2008

To the man who loves art for its own sake, it is frequently in its least important and lowliest manifestations that the keenest pleasure is to be derived.

ApplesandOranges posted:

Tenmyouji's priorities seem to be getting Quark out, assuming he has radical-6, and getting Clover to trust him second. The only time he's betrayed her was when Quark was in danger. When Quark was cured, he let Clover vote even though it risked killing Tenmyouji.
Yeah, after sleeping on it this became a bit more clear.

In general, having a player whose entire strategy is trying to get another specific player to win would be interesting. That's kind of the scary part of these types in general. Sometimes you get the normal person who believes in honor, or the selfish guy, or the guy who has studied game theory, and they're all relatively predictable once you nail what moral system they use. Then there's the guy whose definition of winning exists completely separate from anything you could plan for.

Similarly, I can easily imagine a computer player whose goal is to try to get everyone's score as low as possible. Or kill as much as possible.

Bruceski
Aug 21, 2007

The tools of a hero mean nothing without a solid core.

It's interesting to think of a martyr player whose goal was to get as many people out as they could at their own expense. I think that would boil down to "wants to maximize opponent's points but wants them to not be the threshold for ending the game". It's been ages since I coded (1997 or so, I'm old) but the main points I have for that are:
--defaults to ally.
--betrays if current opponent could escape and nobody else could (or if X people need to win to escape, betray if opponent would be the Xth winner).
--allies if someone in another match could escape (or be the Xth winner).
--If game will likely end, Martyr is in a position to escape and opponent isn't, betray. (there's selfless and then there's stupid)

Ideally it could also consider how likely [pairings where someone could escape] were to result in someone actually escaping, but that would require knowledge of the other players' strategies. Definitely something a human stuck in the game could consider, but I think that's beyond the limits of the program.

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

Twiddy posted:

Yeah, after sleeping on it this became a bit more clear.

In general, having a player whose entire strategy is trying to get another specific player to win would be interesting. That's kind of the scary part of these types in general. Sometimes you get the normal person who believes in honor, or the selfish guy, or the guy who has studied game theory, and they're all relatively predictable once you nail what moral system they use. Then there's the guy whose definition of winning exists completely separate from anything you could plan for.

Similarly, I can easily imagine a computer player whose goal is to try to get everyone's score as low as possible. Or kill as much as possible.

That sounds a lot like this:

wikipedia posted:

Although tit for tat is considered to be the most robust basic strategy, a team from Southampton University in England (led by Professor Nicholas Jennings and consisting of Rajdeep Dash, Sarvapali Ramchurn, Alex Rogers, Perukrishnen Vytelingum) introduced a new strategy at the 20th-anniversary iterated prisoners' dilemma competition, which proved to be more successful than tit for tat. This strategy relied on cooperation between programs to achieve the highest number of points for a single program. The university submitted 60 programs to the competition, which were designed to recognize each other through a series of five to ten moves at the start.[10] Once this recognition was made, one program would always cooperate and the other would always defect, assuring the maximum number of points for the defector. If the program realized that it was playing a non-Southampton player, it would continuously defect in an attempt to minimize the score of the competing program. As a result,[11] this strategy ended up taking the top three positions in the competition, as well as a number of positions towards the bottom.

Fedule
Mar 27, 2010


No one left uncured.
I got you.

maswastaken posted:

Edit: Untested strategy code.

This was edited in so I missed it on your first post, but drat.

BTW - in python you gotta capitalize True and False to use them as boolean values - otherwise it thinks you're talking about variables named "true" and "false".

Shei-kun
Dec 2, 2011

Screw you, physics!
I think everyone's got a code for hitting Ally if Sigma chooses Betray, though.

JUST to make him seem like the ultimate rear end in a top hat.

maswastaken
Nov 12, 2011

Fedule posted:

This was edited in so I missed it on your first post, but drat.

BTW - in python you gotta capitalize True and False to use them as boolean values - otherwise it thinks you're talking about variables named "true" and "false".
That wouldn't be the only mistake I just corrected in there. There's typos and forgetting that forgiving betrayal of murderers requires you check that they actually betrayed the murderers.

ApplesandOranges
Jun 22, 2012

Thankee kindly.

Bruceski posted:

It's interesting to think of a martyr player whose goal was to get as many people out as they could at their own expense. I think that would boil down to "wants to maximize opponent's points but wants them to not be the threshold for ending the game". It's been ages since I coded (1997 or so, I'm old) but the main points I have for that are:
--defaults to ally.
--betrays if current opponent could escape and nobody else could (or if X people need to win to escape, betray if opponent would be the Xth winner).
--allies if someone in another match could escape (or be the Xth winner).
--If game will likely end, Martyr is in a position to escape and opponent isn't, betray. (there's selfless and then there's stupid)

Ideally it could also consider how likely [pairings where someone could escape] were to result in someone actually escaping, but that would require knowledge of the other players' strategies. Definitely something a human stuck in the game could consider, but I think that's beyond the limits of the program.

Luna would be the closest to that, probably? We haven't actually seen her hit Betray, but she's Allied constantly, and she brought up the idea of a mutual Betray when Phi and K were at a stalemate.

She seems to be the least inclined to try to escape, however. Come to think of it, Alice, K, Dio and Phi are the only ones actively trying to win, Tenmyouji's looking out for Quark, Quark's barely a player, and Clover's unpredictable as well.

Lord Zedd-Repulsa
Jul 21, 2007

Devour a good book.


I have zero coding experience or I'd write up a strategy of my own. Is it possible to make a Monobear one called SHSL Despair? He chooses Ally unless betraying would make the opponent die, in which case Betray. There's probably a way to make it more Despair-inducing but again, no coding experience.

Bruceski
Aug 21, 2007

The tools of a hero mean nothing without a solid core.

ApplesandOranges posted:

Luna would be the closest to that, probably? We haven't actually seen her hit Betray, but she's Allied constantly, and she brought up the idea of a mutual Betray when Phi and K were at a stalemate.

Yeah, I guess there's not much functional difference between my idea and an always-ally player. At least not until people start getting into winning positions.

free Trapt CD
Aug 22, 2013

*~:coffeepal:~*
I've got plenty of java
and Chesterfield Kings

*~:h:~*
Here's a short strategy that probably won't last very long. E: Reworked it to, ideally, copy a random player until they die - this is very untested!
code:
@name{Marcel the 2nd}

@stratname{Copycat}			#Copies a random living participant's choices until they die

@author{Heartbroken 2Twice}

@strategy{
def decide(info):
	from random import randint, choice
	if len(info.rounds()) == 0:
		if randint(0, 1) == 1:
			return True
		else:
			return False
	else:
		if info.whiteboard != "":
			if info.whiteboard.alive == False:
				x = 0
				while x = 0:
					entry = choice(info.scoreboard)
					if entry.alive == True:
						ident = entry.id
						info.whiteboard = entry
						x = 1
			else:
				ident = info.whiteboard.id
		else:
			x = 0
			while x = 0:
				entry = choice(info.scoreboard)
				if entry.alive == True:
					ident = entry.id
					info.whiteboard = entry
					x = 1

		lastgame = info.LookupGamesWith(ident, 1)
		for each in lastgame.participants:
			if each.id == ident:
				if each.decision == 'Trust':
					return True
				else:
					return False
}
Any glaring errors? Very new to programming!

free Trapt CD fucked around with this message at 10:47 on Apr 22, 2014

Fedule
Mar 27, 2010


No one left uncured.
I got you.
Starting to test some of these. Any comments are my feedback. This is just debugging/troubleshooting, not performance stuff.

code:
@name{Marcel the 2nd}

@stratname{Copycat}

@author{Heartbroken 2Twice}

@strategy{
def decide(info):
	from random import randint, choice
	if len(info.rounds) == 0:		#info.rounds is an attribute, not a function. Also len(info.rounds()) wouldn't do anything even if it was, you can't call len on a callable!
		if randint(0, 1) == 1:
			return True
		else:
			return False
...
				while x = 0:
					entry = choice(info.scoreboard.entries)	#WELP I advised you poorly, it's info.scoreboard.entries for the iterable. WHOOPS.
					
}
code:
@name{Meredith K. Pseudonym}

@stratname{Only human}

@author{maswastaken}
Runs fine!

code:
@name{Tom Lehrer}

@stratname{We Will All Go Together When We Go}

@author{idonotlikepeas}

    games = info.history.LookupGames(92, info.facts.opponentid) # check the games uranious		#Forgot to specify info.history. Also I broke the method and had to fix it.
    for g in games:
        if not g.dummy:
            result = g.outcome		#Thank you for alerting me that I hosed up documenting.
            if (result == 'Sucker' or result == 'MutualBetray') and not trustworthy:		#and forgot to point out that historygames are speshul.
                return False  # Universal bereavement / An inspiring achievement

    return True
}
Runs good once you fix your tiny fuckup and my two monumental fuckups.

quote:

The History object:

A record of games you have been involved in.

History.games - An iterable list of Game objects. Ordered chronologically by round and arbitrarily within rounds.

LookupGames(x, [id]) - Look up your last x games, and optionally filter by a given opponent ID. As with the methods in the Info object, this method will always return x games and will pad the end of the list with dummy games if necessary and returns a single game if x = 1 or a list otherwise. THIS METHOD RETURNS PERSONALHISTORYRECORDS, NOT GAMES.

The PersonalHistoryRecord object:

PersonalHistoryRecord.myscore = Your score at the time.
PersonalHistoryRecord.outcome = The game's outcome.
PersonalHistoryRecord.opponentid = Opponent's ID
PersonalHistoryRecord.dummy = Is this record a dummy?

code:
@name{KHM}

@stratname{Communism}

@author{Grat}

@strategy{
def decide(info):

    if info.facts.myscore < info.facts.opponentscore:
        return False
    elif info.facts.myscore > info.facts.opponentscore: #It's elif, not else if!
        return True
  ...
}
code:
@name{Edge Casey}
@stratname{Check game rules to make sure we are actually playing prisoner's dillema}
@author{Dr. Stab}
Compiles fine :confuoot:

code:
@name{Opposite man}
@stratname{Tat for Tit}
@author{Dr. Stab}
@strategy{
def decide(info):
...
        return True   #Capitalise!
 ...
            if p.id == opp: #This is how you compare strings!
...
    #opponent not found
    #raise RuntimeError("Someone has infiltrated our game and is trying to kill me") #Very clever but you understand why I can't let you do that right?
    return False
}
code:
@name{Effort Effortson}

@stratname{As long as I dont lose or murder}

@author{NextTime000}

@strategy{
...
        for p in info.scoreboard.entries: 			#WHOOPS THIS poo poo AGAIN
...
        if (info.facts.opponentscore + info.facts.payoff.betray >= info.facts.winthreshold		#Parentheses implicitly break up lines! Also && doesn't work!
            and winners + 1 == info.facts.winsrequired):
            return False #not letting you win :colbert:
        if (info.facts.opponentscore + info.facts.payoff.trust >= info.facts.winthreshold
            and info.facts.myscore + info.facts.payoff.trust >= info.facts.winthreshold 
            and winners + 2 >= info.facts.winsrequired): #if trust can win the game for us
            return True
...
}
code:

[code]@name{Shirley Manson}

@stratname{Only Happy When It Rains}

@author{idonotlikepeas}
Amazing as this would have been, requests does not seem to be in the standard library and I do not have time for this.

Fedule fucked around with this message at 11:47 on Apr 22, 2014

Adbot
ADBOT LOVES YOU

Fedule
Mar 27, 2010


No one left uncured.
I got you.
Addendum:

code:
@name{Meredith K. Pseudonym}

@stratname{Only human}

@author{maswastaken}
Does NOT run fine! Somehow the closing curly brace got cut off and the program couldn't parse your strategy and so it gave you no strategy which I finally figured out was why you were racking up payoffs but not having any games, trusts or betrays listed (bots don't get those stats) and when I got it to compile there were like a hundred typos but actually the code was mostly fine it was just dumb typos and I am words

  • Locked thread