Two questions about programming Cyberball 5 (how to set the type of speed of balls thrown by NPCs...


Two questions about programming Cyberball 5 (how to set the type of...
Author
Message
S.T
S.T
New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)
Group: Forum Members
Posts: 9, Visits: 38
Hello,

I hope this message finds you well.
I am currently using Inqusit6 to create a Cyberball task for use in fMRI experiment.
I am struggling with two points now.

The first is that even though I can customize the sequence of passes, I cannot set up who throws the strongball(In other word fast speed passes) to whom.
Specifically, for example, NPC1 throws a fast pass to NPC3 while slow to NPC2 (participant) and NPC4.
I want to set up something like this for NPC1, NPC3 and NPC4.
I have tried various ways, but they did not work. I would like to know what code I can use to execute it.

The second is to set a time limit.
In my experiment, I plan to have two types of sessions of the Cyberball task, with each session lasting 3 minutes and repeating this. The number of throws does not indicate the end of the session.
I have tried setting timeout and clocktimer, but 30 throws remain the end condition of the session, and I can't change it.
Is it possible to set time as the end condition for each session of Cyberball task?
And please tell me how to do that.

Thank you in advance for your help.

Best regard,


Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 12K, Visits: 97K
S.T - 12/19/2023
Hello,

I hope this message finds you well.
I am currently using Inqusit6 to create a Cyberball task for use in fMRI experiment.
I am struggling with two points now.

The first is that even though I can customize the sequence of passes, I cannot set up who throws the strongball(In other word fast speed passes) to whom.
Specifically, for example, NPC1 throws a fast pass to NPC3 while slow to NPC2 (participant) and NPC4.
I want to set up something like this for NPC1, NPC3 and NPC4.
I have tried various ways, but they did not work. I would like to know what code I can use to execute it.

The second is to set a time limit.
In my experiment, I plan to have two types of sessions of the Cyberball task, with each session lasting 3 minutes and repeating this. The number of throws does not indicate the end of the session.
I have tried setting timeout and clocktimer, but 30 throws remain the end condition of the session, and I can't change it.
Is it possible to set time as the end condition for each session of Cyberball task?
And please tell me how to do that.

Thank you in advance for your help.

Best regard,


You can implement throw speed changes in the exact same way as other aspects are already implemented, specifically the <list> encoding which player is supposed to pass the ball to which other player, and the time taken for each player to decide before doing the pass.

Look at the custom throwschedule lists (there are several examples included in the code) and the corresponding delayschedule lists. Understand how these work, then do the same thing to encode schedule throw "strength."

> I  have tried setting timeout and clocktimer, but 30 throws remain the end condition of the session, and I can't change it.

You need to spend more time reading and understanding the code.

Here is where the stop bit is set in <trial throw>:

/ ontrialend = [
    if (values.throwcount >= parameters.nthrows){
        values.stop = true;
    } else {
        values.stop = false;
    };
...
]


If the number of throws performed (values.throwcount) is greater or equal than the pre-set number of throws (parameters.nthrows), the block is stopped. If you don't want that and/or want a different stop condition, then change it.
S.T
S.T
New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)
Group: Forum Members
Posts: 9, Visits: 38
Dear Dave.

Hello,
I hope you had a wonderful holiday season.
Thank you for your reply the other day.
Some things are still unresolved, but things are going better than last time.

I have one additional question.
Usually in cyberball tasks, subjects respond with a button or a click.
However, I want to do cyberball with MRI, so instead of buttons and clicks, I want to use the keyboard to enter the subject's responses.
I have tried something, but all I get are errors (worst case is a force close for unknown reason).

Could you please tell me how to convert cyberball5 to keyboard input or what code to use?
Thank you in advance.

Respectfully yours,
S.T

S.T
S.T
New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)
Group: Forum Members
Posts: 9, Visits: 38
Dave - 12/19/2023

Dear Dave.

Sorry for the addition.
The other day when I told you that I could not schedule the speed of the passes thrown by npcs, I was told by you the following.

---------------------------------------------------------------------------------------------
 You can implement throw speed changes in the exact same way as other aspects are already implemented, specifically the <list> encoding which player is You can implement implement throw speed changes in the exact same way as other aspects are already implemented, specifically the <list> encoding which player is supposed to pass the ball to which other player, and the time taken for each player to decide before doing the pass.

Look at the custom throwschedule lists (there are several examples included in the code) and the corresponding delayschedule lists. Understand how these work, then do the same thing to encode schedule throw "strength"
---------------------------------------------------------------------------------------------

While considering how the other schedules (throwschedule, delayschedule) work, I created a similar one named speedschedule.
When I run the experiment, a bug occurs: from the start, the ball thrown by npcs disappears and the assignment is over in about 3 seconds.
What are the possible causes?

I apologize for the repetitiveness.
Thank you very much in advance.

Respectfully yours,


Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 12K, Visits: 97K
S.T - 1/22/2024
Dave - 12/19/2023

Dear Dave.

Sorry for the addition.
The other day when I told you that I could not schedule the speed of the passes thrown by npcs, I was told by you the following.

---------------------------------------------------------------------------------------------
 You can implement throw speed changes in the exact same way as other aspects are already implemented, specifically the <list> encoding which player is You can implement implement throw speed changes in the exact same way as other aspects are already implemented, specifically the <list> encoding which player is supposed to pass the ball to which other player, and the time taken for each player to decide before doing the pass.

Look at the custom throwschedule lists (there are several examples included in the code) and the corresponding delayschedule lists. Understand how these work, then do the same thing to encode schedule throw "strength"
---------------------------------------------------------------------------------------------

While considering how the other schedules (throwschedule, delayschedule) work, I created a similar one named speedschedule.
When I run the experiment, a bug occurs: from the start, the ball thrown by npcs disappears and the assignment is over in about 3 seconds.
What are the possible causes?

I apologize for the repetitiveness.
Thank you very much in advance.

Respectfully yours,


Regarding your first question, you can find previous forum posts dealing with that: https://forums.millisecond.com/Topic35694.aspx
Your second question isn't answerable without you providing the faulty code and explaining exactly what you did and why.
S.T
S.T
New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)
Group: Forum Members
Posts: 9, Visits: 38


Dave - 1/22/2024


Dear Dave,
Thanks for the reply.
I will try the question about the keyboard.

I will change my question about setting the speed of the throws by the NPCs.
I had a suggestion the other day to create a scheduling list, but that didn't work and instead I used "if else" and it worked.
What I want to do is have the NPCs (P1, P4) only make fast passes to other NPCs (P3).
If a fast pass is thrown by another player (mainly participant P2), it is constrained to throw only slow passes, not fast passes.

With the code below(The green line drawn corresponds to the area), I could set up P1 or P4 to only make fast passes against P3.
However, the "if fast paths are received, only slow paths can be thrown" constraint, which was working until I wrote the if else to do this, does not work in this code.
In other words, if a fast pass is received from P2 (participant), the NPCs will throw a fast pass against P3.

What part of the code is incorrect?
Currently, the program for the trial looks like this:

**************************************************************************************************************
**************************************************************************************************************
    TRIALS
**************************************************************************************************************
**************************************************************************************************************
// handles the NPCs (virtual players) as well as player 2 in "spectate" conditions
<trial npctrial>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    values.ball_at = values.throw_to;
    if (values.ball_at == 2) {
        values.player2received += 1;
    };
    
    expressions.set_offsets;
    
    values.player1state = (values.ball_at == 1) + 1;
    values.player2state = (values.ball_at == 2) + 1;
    values.player3state = (values.ball_at == 3) + 1;
    values.player4state = (values.ball_at == 4) + 1;
    values.player5state = (values.ball_at == 5) + 1;
    values.player6state = (values.ball_at == 6) + 1;
    values.player7state = (values.ball_at == 7) + 1;
    values.player8state = (values.ball_at == 8) + 1;
    values.player9state = (values.ball_at == 9) + 1;
    
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    if (values.throw_to == 0){
    values.throw_to = list.npcs.nextindex;
    values.delay = round(rand(1, 4)) * 1000;
    };
    while (values.throw_to == values.ball_at){
        values.deprecated +=1;
        values.throw_to = list.throwschedule.nextvalue;
        values.delay = list.delayschedule.nextvalue;
    };
]

/ ontrialend = [
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.throwcount += 1;
    values.previousthrowspeed = parameters.throwspeed;
    if (values.previousthrowspeed == parameters.fastspeed) { // if previous throw was fast
        parameters.throwspeed = parameters.slowspeed; // next throw must be slow
    } else if(values.throw_to == 3){
        parameters.throwspeed = parameters.fastspeed;
    } else {
      parameters.throwspeed = parameters.slowspeed;
    };
    if (values.ball_at == 2) {
        values.player2thrown += 1;
    };

]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats]

/ inputdevice = keyboard
/ showmousecursor = false
/ validresponse = (0)
/ trialduration = values.delay
/ branch = [
    return trial.throw;
]
</trial>

<trial player2forceslow>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    parameters.throwspeed = parameters.slowspeed;
]
/ validresponse = (0)
/ trialduration = 0
/ branch = [
    return trial.player2;
]
/ recorddata = false
</trial>

// handles the human player
<trial player2speed>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    if (trial.player2speed.response == "slow") {
        parameters.throwspeed = parameters.slowspeed;
    } else if (trial.player2speed.response == "fast") {
        parameters.throwspeed = parameters.fastspeed;
    };
]
/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats, slow, fast]
/ validresponse = (button.slow, button.fast)
/ branch = [
    return trial.player2;
]
/ recorddata = false
</trial>

<button slow>
/ caption = "SLOW THROW"
/ size = (15%, 8%)
/ position = (50%, 45%)
/ fontstyle = ("Verdana", 3%, true)
</button>

<button fast>
/ caption = "FAST THROW"
/ size = (15%, 8%)
/ position = (50%, 55%)
/ fontstyle = ("Verdana", 3%, true)
</button>

<trial player2>
/ ontrialbegin = [
    //values.received_from = values.ball_at;
    //expressions.set_offsets;
    
    //values.player2received += 1;
    
    //values.player1state = 1;
    //catch
    //values.player2state = 2;
    //values.player3state = 1;
    //values.player4state = 1;
    //values.player5state = 1;
    //values.player6state = 1;
    //values.player7state = 1;
    //values.player8state = 1;
    //values.player9state = 1;
    
    //values.ball_at = 2;
    //values.throw_to = list.throwschedule.nextvalue;
    //values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    values.throw_to = substring(trial.player2.response, length(trial.player2.response)-1, 1);
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.player2thrown += 1;
    values.throwcount += 1;
]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats]

/ validresponse = (player1, player3, player4, player5, player6, player7, player8, player9)
/ responsemessage = (player1, player1click, 100)
/ responsemessage = (player3, player3click, 100)
/ responsemessage = (player4, player4click, 100)
/ responsemessage = (player5, player5click, 100)
/ responsemessage = (player6, player6click, 100)
/ responsemessage = (player7, player7click, 100)
/ responsemessage = (player8, player8click, 100)
/ responsemessage = (player9, player9click, 100)
/ branch = [
    return trial.throw;
]
</trial>

// implements the throw animation
<trial throw>
/ ontrialbegin = [
    trial.throw.resetstimulusframes();
    if (parameters.throwspeed == parameters.fastspeed) {
        systembeep.duration = 2000;
        systembeep.frequency = 100;
        systembeep.playthrough = true;
        trial.throw.insertstimulustime(systembeep, 900 + expressions.throwduration);
    };
    picture.player1.skip = expressions.skip_player1pic;
    picture.player2.skip = expressions.skip_player2pic;
    picture.player3.skip = expressions.skip_player3pic;
    picture.player4.skip = expressions.skip_player4pic;
    picture.player5.skip = expressions.skip_player5pic;
    picture.player6.skip = expressions.skip_player6pic;
    picture.player7.skip = expressions.skip_player7pic;
    picture.player8.skip = expressions.skip_player8pic;
    picture.player9.skip = expressions.skip_player9pic;
    
    values.throwingplayer_x = list.player_x.item(values.ball_at);
    values.throwingplayer_y = list.player_y.item(values.ball_at);
    values.receivingplayer_x = list.player_x.item(values.throw_to);
    values.receivingplayer_y = list.player_y.item(values.throw_to);
    values.ball_x = values.receivingplayer_x;
    expressions.set_throwoffset;
]

/ ontrialend = [
    if (values.throwcount >= parameters.nthrows){
        values.stop = true;
    } else {
        values.stop = false;
    };
    picture.player1.skip = false;
    picture.player2.skip = false;
    picture.player3.skip = false;
    picture.player4.skip = false;
    picture.player5.skip = false;
    picture.player6.skip = false;
    picture.player7.skip = false;
    picture.player8.skip = false;
    picture.player9.skip = false;
]

/ stimulustimes = [0=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow0, stats;
    
    500=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow1, stats;
    
    600=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow2, stats;
    
    700=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow3, stats;
    
    800=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow4, stats;
    
    900=ball_to]
    
/ inputdevice = keyboard
/ showmousecursor = false
/ validresponse = (0)
/ trialduration = 900 + expressions.throwduration
/ branch = [
    if (values.throw_to == 2 && !parameters.spectate){
        if (parameters.throwspeed == parameters.fastspeed) { // if throw received was fast
            return trial.player2forceslow; // player 2 must throw slow
        } else if (parameters.throwspeed == parameters.slowspeed) { // otherwise go to speed selection first
            return trial.player2speed;
        };
    } else {
        return trial.npctrial;
    }
]
/ recorddata = false
</trial>

// displays the welcome message / instructions / game cover story
<trial instructions>
/ stimulusframes = [1=clearscreen, banner, logo, instructions, play]
/ validresponse = (play)
/ recorddata = false
</trial>

// displays the "Connecting to other players..." message and animation
<trial start>
/ ontrialbegin = [
    list.npcs.reset();
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.ball_x = list.player_x.item(values.throw_to);
]
/ stimulusframes = [1=clearscreen, connectingmessage, connectinganimation]
/ inputdevice = keyboard
/ validresponse = (0)
/ trialduration = replace(5000,6000,7000)
/ branch = [
    if (values.throw_to == 2 && !parameters.spectate){
        return trial.player2speed; //trial.player2;
    } else {
        return trial.npctrial;
    }
]
/ recorddata = false
</trial>

// end screen with exit button
<trial thankyou>
/ stimulusframes = [1=clearscreen, thankyoumessage, exit]
/ validresponse = (exit)
/ recorddata = false
</trial>



Sorry for the length of this message.
Please confirm.

Respectfully yours,

Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 12K, Visits: 97K
S.T - 1/24/2024


Dave - 1/22/2024


Dear Dave,
Thanks for the reply.
I will try the question about the keyboard.

I will change my question about setting the speed of the throws by the NPCs.
I had a suggestion the other day to create a scheduling list, but that didn't work and instead I used "if else" and it worked.
What I want to do is have the NPCs (P1, P4) only make fast passes to other NPCs (P3).
If a fast pass is thrown by another player (mainly participant P2), it is constrained to throw only slow passes, not fast passes.

With the code below(The green line drawn corresponds to the area), I could set up P1 or P4 to only make fast passes against P3.
However, the "if fast paths are received, only slow paths can be thrown" constraint, which was working until I wrote the if else to do this, does not work in this code.
In other words, if a fast pass is received from P2 (participant), the NPCs will throw a fast pass against P3.

What part of the code is incorrect?
Currently, the program for the trial looks like this:

**************************************************************************************************************
**************************************************************************************************************
    TRIALS
**************************************************************************************************************
**************************************************************************************************************
// handles the NPCs (virtual players) as well as player 2 in "spectate" conditions
<trial npctrial>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    values.ball_at = values.throw_to;
    if (values.ball_at == 2) {
        values.player2received += 1;
    };
    
    expressions.set_offsets;
    
    values.player1state = (values.ball_at == 1) + 1;
    values.player2state = (values.ball_at == 2) + 1;
    values.player3state = (values.ball_at == 3) + 1;
    values.player4state = (values.ball_at == 4) + 1;
    values.player5state = (values.ball_at == 5) + 1;
    values.player6state = (values.ball_at == 6) + 1;
    values.player7state = (values.ball_at == 7) + 1;
    values.player8state = (values.ball_at == 8) + 1;
    values.player9state = (values.ball_at == 9) + 1;
    
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    if (values.throw_to == 0){
    values.throw_to = list.npcs.nextindex;
    values.delay = round(rand(1, 4)) * 1000;
    };
    while (values.throw_to == values.ball_at){
        values.deprecated +=1;
        values.throw_to = list.throwschedule.nextvalue;
        values.delay = list.delayschedule.nextvalue;
    };
]

/ ontrialend = [
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.throwcount += 1;
    values.previousthrowspeed = parameters.throwspeed;
    if (values.previousthrowspeed == parameters.fastspeed) { // if previous throw was fast
        parameters.throwspeed = parameters.slowspeed; // next throw must be slow
    } else if(values.throw_to == 3){
        parameters.throwspeed = parameters.fastspeed;
    } else {
      parameters.throwspeed = parameters.slowspeed;
    };
    if (values.ball_at == 2) {
        values.player2thrown += 1;
    };

]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats]

/ inputdevice = keyboard
/ showmousecursor = false
/ validresponse = (0)
/ trialduration = values.delay
/ branch = [
    return trial.throw;
]
</trial>

<trial player2forceslow>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    parameters.throwspeed = parameters.slowspeed;
]
/ validresponse = (0)
/ trialduration = 0
/ branch = [
    return trial.player2;
]
/ recorddata = false
</trial>

// handles the human player
<trial player2speed>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    if (trial.player2speed.response == "slow") {
        parameters.throwspeed = parameters.slowspeed;
    } else if (trial.player2speed.response == "fast") {
        parameters.throwspeed = parameters.fastspeed;
    };
]
/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats, slow, fast]
/ validresponse = (button.slow, button.fast)
/ branch = [
    return trial.player2;
]
/ recorddata = false
</trial>

<button slow>
/ caption = "SLOW THROW"
/ size = (15%, 8%)
/ position = (50%, 45%)
/ fontstyle = ("Verdana", 3%, true)
</button>

<button fast>
/ caption = "FAST THROW"
/ size = (15%, 8%)
/ position = (50%, 55%)
/ fontstyle = ("Verdana", 3%, true)
</button>

<trial player2>
/ ontrialbegin = [
    //values.received_from = values.ball_at;
    //expressions.set_offsets;
    
    //values.player2received += 1;
    
    //values.player1state = 1;
    //catch
    //values.player2state = 2;
    //values.player3state = 1;
    //values.player4state = 1;
    //values.player5state = 1;
    //values.player6state = 1;
    //values.player7state = 1;
    //values.player8state = 1;
    //values.player9state = 1;
    
    //values.ball_at = 2;
    //values.throw_to = list.throwschedule.nextvalue;
    //values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    values.throw_to = substring(trial.player2.response, length(trial.player2.response)-1, 1);
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.player2thrown += 1;
    values.throwcount += 1;
]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats]

/ validresponse = (player1, player3, player4, player5, player6, player7, player8, player9)
/ responsemessage = (player1, player1click, 100)
/ responsemessage = (player3, player3click, 100)
/ responsemessage = (player4, player4click, 100)
/ responsemessage = (player5, player5click, 100)
/ responsemessage = (player6, player6click, 100)
/ responsemessage = (player7, player7click, 100)
/ responsemessage = (player8, player8click, 100)
/ responsemessage = (player9, player9click, 100)
/ branch = [
    return trial.throw;
]
</trial>

// implements the throw animation
<trial throw>
/ ontrialbegin = [
    trial.throw.resetstimulusframes();
    if (parameters.throwspeed == parameters.fastspeed) {
        systembeep.duration = 2000;
        systembeep.frequency = 100;
        systembeep.playthrough = true;
        trial.throw.insertstimulustime(systembeep, 900 + expressions.throwduration);
    };
    picture.player1.skip = expressions.skip_player1pic;
    picture.player2.skip = expressions.skip_player2pic;
    picture.player3.skip = expressions.skip_player3pic;
    picture.player4.skip = expressions.skip_player4pic;
    picture.player5.skip = expressions.skip_player5pic;
    picture.player6.skip = expressions.skip_player6pic;
    picture.player7.skip = expressions.skip_player7pic;
    picture.player8.skip = expressions.skip_player8pic;
    picture.player9.skip = expressions.skip_player9pic;
    
    values.throwingplayer_x = list.player_x.item(values.ball_at);
    values.throwingplayer_y = list.player_y.item(values.ball_at);
    values.receivingplayer_x = list.player_x.item(values.throw_to);
    values.receivingplayer_y = list.player_y.item(values.throw_to);
    values.ball_x = values.receivingplayer_x;
    expressions.set_throwoffset;
]

/ ontrialend = [
    if (values.throwcount >= parameters.nthrows){
        values.stop = true;
    } else {
        values.stop = false;
    };
    picture.player1.skip = false;
    picture.player2.skip = false;
    picture.player3.skip = false;
    picture.player4.skip = false;
    picture.player5.skip = false;
    picture.player6.skip = false;
    picture.player7.skip = false;
    picture.player8.skip = false;
    picture.player9.skip = false;
]

/ stimulustimes = [0=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow0, stats;
    
    500=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow1, stats;
    
    600=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow2, stats;
    
    700=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow3, stats;
    
    800=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow4, stats;
    
    900=ball_to]
    
/ inputdevice = keyboard
/ showmousecursor = false
/ validresponse = (0)
/ trialduration = 900 + expressions.throwduration
/ branch = [
    if (values.throw_to == 2 && !parameters.spectate){
        if (parameters.throwspeed == parameters.fastspeed) { // if throw received was fast
            return trial.player2forceslow; // player 2 must throw slow
        } else if (parameters.throwspeed == parameters.slowspeed) { // otherwise go to speed selection first
            return trial.player2speed;
        };
    } else {
        return trial.npctrial;
    }
]
/ recorddata = false
</trial>

// displays the welcome message / instructions / game cover story
<trial instructions>
/ stimulusframes = [1=clearscreen, banner, logo, instructions, play]
/ validresponse = (play)
/ recorddata = false
</trial>

// displays the "Connecting to other players..." message and animation
<trial start>
/ ontrialbegin = [
    list.npcs.reset();
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.ball_x = list.player_x.item(values.throw_to);
]
/ stimulusframes = [1=clearscreen, connectingmessage, connectinganimation]
/ inputdevice = keyboard
/ validresponse = (0)
/ trialduration = replace(5000,6000,7000)
/ branch = [
    if (values.throw_to == 2 && !parameters.spectate){
        return trial.player2speed; //trial.player2;
    } else {
        return trial.npctrial;
    }
]
/ recorddata = false
</trial>

// end screen with exit button
<trial thankyou>
/ stimulusframes = [1=clearscreen, thankyoumessage, exit]
/ validresponse = (exit)
/ recorddata = false
</trial>



Sorry for the length of this message.
Please confirm.

Respectfully yours,

/ ontrialend = [
    ...
    values.previousthrowspeed = parameters.throwspeed; // record speed of previous throw
    
    if (values.throw_to == 3) { // if recipient is P3
        parameters.throwspeed = parameters.fastspeed; // throw fast ball by default
    };
    // BUT
    if (values.previousthrowspeed == parameters.fastspeed) { // if previous throw was fast
    parameters.throwspeed = parameters.slowspeed; // next throw must be slow
    };
...
]


Should be as simple as that?
S.T
S.T
New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)
Group: Forum Members
Posts: 9, Visits: 38
Dave - 1/24/2024


Dear, Dave
Thanks for the reply.
As you said, I was thinking too hard.

Sorry for repeating but I would like to ask one more question.
It's about the problem about wanting to get the participant's response with the keyboard instead of a click.

I could change about the start, end and the choice of player to throw.
But there are two problems.
First, about <trial player2speed>.
There are two different speeds for the pass, but the default is button, so it needs to be changed.
If I make the following code, there is no problem when selecting "s" or "f".
However, when "f" is selected, it never becomes Fastspeed. (The code for the button did not change whether I wrote it or not.)
What code is correct?

Second, about <trial player2>.
The current code is making numbers like 1,3,5 the target of the response.
I really want to make "r", "g", "b", and "y" the response codes, but if I make them not numbers, the game will be forced to terminate the moment a participant holds the ball (bug).
What part am I not understanding?

Thank you in advance for your help.
Respetfully yours,


Currently, the program for the trial looks like this:
**************************************************************************************************************
**************************************************************************************************************
    TRIALS
**************************************************************************************************************
**************************************************************************************************************
// handles the NPCs (virtual players) as well as player 2 in "spectate" conditions
<trial npctrial>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    values.ball_at = values.throw_to;
    if (values.ball_at == 2) {
        values.player2received += 1;
    };
    
    expressions.set_offsets;
    
    values.player1state = (values.ball_at == 1) + 1;
    values.player2state = (values.ball_at == 2) + 1;
    values.player3state = (values.ball_at == 3) + 1;
    values.player4state = (values.ball_at == 4) + 1;
    values.player5state = (values.ball_at == 5) + 1;
    values.player6state = (values.ball_at == 6) + 1;
    values.player7state = (values.ball_at == 7) + 1;
    values.player8state = (values.ball_at == 8) + 1;
    values.player9state = (values.ball_at == 9) + 1;
    
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    if (values.throw_to == 0){
    values.throw_to = list.npcs.nextindex;
    values.delay = round(rand(1, 4)) * 1000;
    };
    while (values.throw_to == values.ball_at){
        values.deprecated +=1;
        values.throw_to = list.throwschedule.nextvalue;
        values.delay = list.delayschedule.nextvalue;
    };
]

/ ontrialend = [
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.throwcount += 1;
    values.previousthrowspeed = parameters.throwspeed;
    if (values.previousthrowspeed == parameters.fastspeed) { // if previous throw was fast
        parameters.throwspeed = parameters.slowspeed; // next throw must be slow
    } else if (values.throw_to == 3) {
        parameters.throwspeed = parameters.fastspeed;
    } else {
      parameters.throwspeed = parameters.slowspeed;
    };

    if (values.ball_at == 2) {
        values.player2thrown += 1;
    };
]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats]

/ inputdevice = keyboard
/ showmousecursor = false
/ validresponse = (0)
/ trialduration = values.delay
/ branch = [
    return trial.throw;
]
</trial>

<trial player2forceslow>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    parameters.throwspeed = parameters.slowspeed;
]
/ validresponse = (0)
/ trialduration = 0
/ branch = [
    return trial.player2;
]
/ recorddata = false
</trial>

// handles the human player
<trial player2speed>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    if (trial.player2speed.response == "slow") {
        parameters.throwspeed = parameters.slowspeed;
    } else if (trial.player2speed.response == "fast") {
        parameters.throwspeed = parameters.fastspeed;
    };
]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats, slow, fast]
/ validresponse = ("s", "f")
/ responsemessage = ("s", button.slow, 100)
/ responsemessage = ("f", button.fast, 100)
/ inputdevice = keyboard
/ branch = [
  if (trial.player2.response == "s") {
      parameters.throwspeed = parameters.slowspeed;
    };
]
/ branch = [
  if (trial.player2.response == "f") {
        parameters.throwspeed = parameters.fastspeed;
    };
]
/ branch = [
    return trial.player2;
]
/ recorddata = false
</trial>

<button slow>
/ caption = "SLOW THROW"
/ size = (15%, 8%)
/ position = (50%, 45%)
/ fontstyle = ("Verdana", 3%, true)
</button>

<button fast>
/ caption = "FAST THROW"
/ size = (15%, 8%)
/ position = (50%, 55%)
/ fontstyle = ("Verdana", 3%, true)
</button>

<trial player2>
/ ontrialbegin = [
    values.received_from = values.ball_at;
    expressions.set_offsets;
    
    values.player2received += 1;
    
    values.player1state = 1;
    //catch
    values.player2state = 2;
    values.player3state = 1;
    values.player4state = 1;
    values.player5state = 1;
    values.player6state = 1;
    values.player7state = 1;
    values.player8state = 1;
    values.player9state = 1;
    
    values.ball_at = 2;
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    
]

/ ontrialend = [
    values.throw_to = substring(trial.player2.response, length(trial.player2.response)-1, 1);
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.player2thrown += 1;
    values.throwcount += 1;
]

/ stimulusframes = [1=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    stats]

/ validresponse = ("1", "3", "5" player5, player6, player7, player8, player9)
/ responsemessage = ("1", player1click, 100)
/ responsemessage = ("3", player3click, 100)
/ responsemessage = ("5", player4click, 100)

/ responsemessage = (player5, player5click, 100)
/ responsemessage = (player6, player6click, 100)
/ responsemessage = (player7, player7click, 100)
/ responsemessage = (player8, player8click, 100)
/ responsemessage = (player9, player9click, 100)
/ inputdevice = keyboard
/ branch = [
  if (trial.player2.response == 2) {
      values.throw_to = 1; // use assignment operator, separate statements properly
   return trial.throw;
    };
]
/ branch = [
  if (trial.player2.response == 4) {
        values.throw_to = 3; // use assignment operator, separate statements properly
   return trial.throw;
    };
]
/ branch = [
  if (trial.player2.response == 6) {
        values.throw_to = 4; // use assignment operator, separate statements properly
   return trial.throw;
    };
]

</trial>


// implements the throw animation
<trial throw>
/ ontrialbegin = [
    trial.throw.resetstimulusframes();
    if (parameters.throwspeed == parameters.fastspeed) {
        systembeep.duration = 2000;
        systembeep.frequency = 100;
        systembeep.playthrough = true;
        trial.throw.insertstimulustime(systembeep, 900 + expressions.throwduration);
    };
    picture.player1.skip = expressions.skip_player1pic;
    picture.player2.skip = expressions.skip_player2pic;
    picture.player3.skip = expressions.skip_player3pic;
    picture.player4.skip = expressions.skip_player4pic;
    picture.player5.skip = expressions.skip_player5pic;
    picture.player6.skip = expressions.skip_player6pic;
    picture.player7.skip = expressions.skip_player7pic;
    picture.player8.skip = expressions.skip_player8pic;
    picture.player9.skip = expressions.skip_player9pic;
    
    values.throwingplayer_x = list.player_x.item(values.ball_at);
    values.throwingplayer_y = list.player_y.item(values.ball_at);
    values.receivingplayer_x = list.player_x.item(values.throw_to);
    values.receivingplayer_y = list.player_y.item(values.throw_to);
    values.ball_x = values.receivingplayer_x;
    expressions.set_throwoffset;
]

/ ontrialend = [
    if (values.throwcount >= parameters.nthrows){
        values.stop = true;
    } else {
        values.stop = false;
    };
    picture.player1.skip = false;
    picture.player2.skip = false;
    picture.player3.skip = false;
    picture.player4.skip = false;
    picture.player5.skip = false;
    picture.player6.skip = false;
    picture.player7.skip = false;
    picture.player8.skip = false;
    picture.player9.skip = false;
]

/ stimulustimes = [0=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow0, stats;
    
    500=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow1, stats;
    
    600=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow2, stats;
    
    700=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow3, stats;
    
    800=clearscreen, player1, player2, player3, player4, player5, player6, player7, player8, player9,
    player1label, player2label, player3label, player4label, player5label, player6label, player7label, player8label, player9label,
    player1avatar, player2avatar, player3avatar, player4avatar, player5avatar, player6avatar, player7avatar, player8avatar, player9avatar,
    playerthrow4, stats;
    
    900=ball_to]
    
/ inputdevice = keyboard
/ showmousecursor = false
/ validresponse = (0)
/ trialduration = 900 + expressions.throwduration
/ branch = [
    if (values.throw_to == 2 && !parameters.spectate){
        if (parameters.throwspeed == parameters.fastspeed) { // if throw received was fast
            return trial.player2forceslow; // player 2 must throw slow
        } else if (parameters.throwspeed == parameters.slowspeed) { // otherwise go to speed selection first
            return trial.player2speed;
        };
    } else {
        return trial.npctrial;
    }
]
/ recorddata = false
</trial>

// displays the welcome message / instructions / game cover story
<trial instructions>
/ stimulusframes = [1=clearscreen, banner, logo, instructions]
/ validresponse = ("r")
/ inputdevice = keyboard
/ recorddata = false
</trial>

// displays the "Connecting to other players..." message and animation
<trial start>
/ ontrialbegin = [
    list.npcs.reset();
    values.throw_to = list.throwschedule.nextvalue;
    values.delay = list.delayschedule.nextvalue;
    values.realizedThrowSchedule = concat(values.realizedThrowSchedule, values.throw_to);
    values.ball_x = list.player_x.item(values.throw_to);
]
/ stimulusframes = [1=clearscreen, connectingmessage, connectinganimation]
/ inputdevice = keyboard
/ validresponse = ("r")
/ trialduration = replace(5000,6000,7000)
/ branch = [
    if (values.throw_to == 2 && !parameters.spectate){
        return trial.player2speed; //trial.player2;
    } else {
        return trial.npctrial;
    }
]
/ recorddata = false
</trial>

// end screen with exit
<trial thankyou>
/ stimulusframes = [1=clearscreen, thankyoumessage]
/ inputdevice = keyboard
/ validresponse = ("r")
/ recorddata = false
</trial>

S.T
S.T
New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)New Member (20 reputation)
Group: Forum Members
Posts: 9, Visits: 38
Dave - 1/24/2024


Dear Dave,

The second question was resolved as a result of adopting a different approach.
Please consider the first issue about trial player2speed (Fastspeed is not executed).

Thank you.
Respectfully yours,

Dave
Dave
Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)Supreme Being (1M reputation)
Group: Administrators
Posts: 12K, Visits: 97K
S.T - 1/26/2024
Dave - 1/24/2024


Dear Dave,

The second question was resolved as a result of adopting a different approach.
Please consider the first issue about trial player2speed (Fastspeed is not executed).

Thank you.
Respectfully yours,

The response property does not return the character, it returns the numerical keyboard scancode.

https://www.millisecond.com/support/docs/current/html/language/scancodes.htm

If you want the character, you need to work with the responsetext property.

<block exampleblock>
/ trials = [1-4 = trial.example]
</block>

<trial example>
/ stimulusframes = [1=text.exampletext]
/ validresponse = (anyresponse)
/ inputdevice = keyboard
/ branch = [
    return trial.showresponse;
]
</trial>

<trial showresponse>
/ stimulusframes = [1=text.showresponse]
/ trialduration = 5000
/ validresponse = (0)
</trial>

<text exampletext>
/ items = ("Press any key")
</text>

<text showresponse>
/ items = ("Scan code: <%trial.example.response%> | Character: <%trial.example.responsetext%>")
</text>




GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Reading This Topic

Explore
Messages
Mentions
Search