SOLVED: Objects chosen in correct order

Started by Slasher, Thu 18/07/2013 10:49:59

Previous topic - Next topic

Slasher

Hi

I have been searching high and low to bring this to a conclusion and solved:

There are 8 objects. Using inventory on any object changes that object's graphic, repeating changes graphic back.

You have only to change 5 objects to be successful, however, they need to be done in the correct order.

Objects are:

obutt1
obutt2
obutt3
obutt4
obutt5
obutt7
obutt8
obutt9

I have also given each object a boolean used when changing its graphic and a value int if correct.

Example: Think along the lines of a musical keyboard and playing only the correct notes and in the right order. Playing a wrong note will void the sequence.

Everything works except the order.

Have you got any pointers as to the best way of doing this or at least help with some assistance?

cheers



Snarky

#1
I'm not gonna ask what those objects are...

The general answer to this type of problem is a state machine. In this case you should only need a very simple one.

Code: AGS

int correctStepCount = 0;
int correctStepIndex[9];

// Call this first to set up the array
void InitCorrectSteps()
{
  correctStepIndex[0] = obutt1.ID;
  correctStepIndex[1] = obutt2.ID;
  // And so on...
}

// Call this any time the user changes one of the butts (WTF?)
bool actionCorrect(Object* butt)
{
  if(butt.ID == correctStepIndex[correctStepCount])
  {
    correctStepCount++;
    return true;
  }
  else
  {
    correctStepCount = 0;
    return false;
  }
}


And then check if the stepCount >= 5. (You might prefer that to be the return value of the function. Depending on which outcomes you need to deal with specially, you could also make it return an enum with three possible values: eButtReset, eButtStepOk, eButtFinish or whatever.)

Khris

First of all, you shouldn't need an additional boolean per object, you can check the object's .Graphic property (I assume all buttons share the same two sprites, right?)

As for sequences, there's another way I like to use, which easily allows detecting a specific sequence without resetting everything.
In each object's use inv on event line (in the object's event pane), instead of "obutt1_Useinv", put "button_press".

Then add this to your room script:
Code: ags
String sequence;

function button_press() {
  if (player.ActiveInv != iReallyLongfinger) {
    Display("You can't use that here.");
    return;
  }

  Object *o = Object.GetAtScreenXY(mouse.x, mouse.y);
  if (o == null) return;
  int b = o.ID+1;  // assuming the 9 buttons have IDs 0-8, b now holds the number of the button

  // init sequence string
  is (String.IsNullOrEmpty(sequence)) sequence = "";

  if (o.Graphic == 123) {  // turned off sprite slot
    o.Graphic = 124;   // turned on sprite slot
    // add to sequence;
    sequence = String.Format("%s%d", sequence, b);
    
    // truncate
    if (sequence.Length == 6) sequence = sequence.Substring(1, 5);  // remove first character

    // win?
    if (sequence.CompareTo("13579") == 0) {
      // drop balloons here (:
    }
  }
  else o.Graphic = 123; // turn off
}

Snarky

#3
Ryan Timothy would say that code proves you're a terrible programmer, Khris. :)

It occurs to me that the original question is ill-defined. You have nine objects, but the user has to click on 5 of them "in correct order"? What does that mean? How do any of the 4 others come into it?

My code accepts (only) the sequence: 1,2,3,4,5
Khris's code (for some reason) accepts only: 1,3,5,7,9

What about 2,3,4,5,6 (sequential, but starting from a different value)? Is that a correct sequence?
Or what about 1,3,4,6,7 (ordered, but not sequential)? Is that correct?
How about 7,8,9,1,2 (wraparound)? Accepted or not?

We need more details, slasher.

Khris

5 out of 9, in correct order. I don't see any problem with that. My 13579 was just an example.

But, why would Ryan say that? Just curious :)

Slasher

#5
Ok guys, more info:

Please note that we are talking objects acting as buttons and not actual gui buttons.

You have 8 musical buttons which are actually objects with a different sound attached to each.

All objects start as RED and when you use correct inventory item on any of them the object that you clicked on turns GREEN and the appropriate sound plays. If you repeat on a GREEN object again it turns back to RED. This can be repeated for each object.

All objects share the same sprite numbers.

The object of the exercise is to only turn the correct objects green and in the right order.

If you happen to have 4 correct greens (correct order done that far)and then choose an incorrect note that turns green then selecting the last correct note will not set off events until the incorrect object is back to RED.

I know its awkward if you are not there as it were.

Hope this expands explanation ok.

cheers






Khris

I was suspecting something like this, but I'd say the mechanics are off (I still followed them in my code though).

What should happen is: if you use the item on a green button, nothing happens. Using it on a red button, it turns green, the sound plays. At this point, there's a check for whether we have turned the fifth button green. If yes, but the sequence wasn't correct, turn all buttons red (basically: do a reset of the puzzle). If the sequence was correct, WIN.

Slasher

Hi Khris,

The thing is is that the correct sequance is checked by Rep exec and events run.

That's how it checked is at the present time.

There is no 'button' to check if correct to do a restart of puzzle if incorrect.

I have it all working except the correct sequence bit.

* I obviously need a way to check for other GREENS before proceeding with the correct events as you say.

Perhaps I should do the mechanics in a different way?

cheers




Snarky

Quote from: Khris on Thu 18/07/2013 12:10:37
5 out of 9, in correct order. I don't see any problem with that.

Well, I think the only sequence that's obviously "in correct order" of 5 elements out of 9 is 12345. Whether the other examples I mentioned count is not clear from the original description. For example, I would not count 13569 as "playing only the correct notes and in the right order," because after 1, the correct next note is 2.

QuoteMy 13579 was just an example.

Wouldn't your code need to have a separate condition for every possible correct sequence? That seems extremely tedious (and error-prone). In my code, by contrast, you could just change it to:

Code: AGS

#define STEP_COUNT 9
int stateNumber = 0;
int sequenceLength = 0;
int correctStepIndex[STEP_COUNT];

// Call this first to set up the array
void InitCorrectSteps()
{
  correctStepIndex[0] = obutt1.ID;
  correctStepIndex[1] = obutt2.ID;
  // And so on...
}

// Find the next occurence of step in the array, starting from startIndex
int GetStepIndex(int step, int startIndex)
{
  int i=startIndex;
  while(i<STEP_COUNT)
  {
    if(correctStepIndex[i] == step)
      return i;
    i++;
  }
  return -1;
}

// Call this any time the user changes one of the butts (WTF?)
bool actionCorrect(Object* butt)
{
  if(GetStepIndex(butt.ID, stateNumber) >= 0) // Changed the condition to check if the chosen butt is anywhere higher in the order
  {
    stateNumber = GetStepIndex(butt.ID, stateNumber) + 1;
    sequenceLength++;
    return true;
  }
  else
  {
    sequenceLength = 0;
    stateNumber = 0;
    // If you want a wrong choice to count as the start of a new sequence, do this instead:
/*
    sequenceLength = 1;
    stateNumber = GetStepIndex(butt.ID, 0);
*/
    return false;
  }
}


QuoteBut, why would Ryan say that? Just curious :)

http://www.adventuregamestudio.co.uk/forums/index.php?topic=48535.msg636459836#msg636459836

Agreed with Khris that the mechanics described are off. Not really much of a puzzle if doing a wrong move immediately disables all other actions apart from correcting the move, is it?

Hernald

#9
Here's my stab at it. I was struggling with the formatting which is why I didn't post sooner.
Code: AGS

// Get five buttons in the correct order
int RightButt[5];
int RBInd;
int result;
int GoodButt(int theButt) {
	if(theButt==RightButt[RBInd]) {
		if (RBInd==4) {
                        RBInd=0;
			cEgo.Say("I've done it!");
			return 3; 
		}
		RBInd++;
		cEgo.Say("So far so good!");
		return 2;
	}
	int ButtErr=0;
	while (ButtErr<5) {
		if (theButt==RightButt[ButtErr]) {
			RBInd=0;
			cEgo.Say("Drat! Back to Square One.");
			return 0; //Fail
		}
		ButtErr++;
	}
	cEgo.Say("That one didn't count.");
	return 1; //Neutral choice; still good to go
}

function room_FirstLoad(){
	RightButt[0]=oButt4.ID;
	RightButt[1]=oButt9.ID;
	RightButt[2]=oButt3.ID;
	RightButt[3]=oButt1.ID;
	RightButt[4]=oButt7.ID;
	RBInd=0;
}


function oButt1_Interact(){
	result=GoodButt(oButt1.ID);
}

function oButt2_Interact(){
	result=GoodButt(oButt2.ID);
}

function oButt3_Interact(){
	result=GoodButt(oButt3.ID);
}

function oButt4_Interact(){
	result=GoodButt(oButt4.ID);
}

function oButt5_Interact(){
	result=GoodButt(oButt5.ID);
}

function oButt6_Interact(){
	result=GoodButt(oButt6.ID);
}

function oButt7_Interact(){
	result=GoodButt(oButt7.ID);	
}

function oButt8_Interact(){
	result=GoodButt(oButt8.ID);
}

function oButt9_Interact(){
	result=GoodButt(oButt9.ID);
}

Ryan Timothy B

Quote from: Snarky on Thu 18/07/2013 11:56:32
Ryan Timothy would say that code proves you're a terrible programmer, Khris. :)
Bah. In a real programming language, mostly yes. But with AGS script being so shite in comparison, no. It gives you little to work with.

Slasher

Thanks to Hernald a solution has been adopted and solved.

SMF spam blocked by CleanTalk