Unknown language and progressive letters discovery ?! (unlock letters system)

Hi there, the title is not so understandable but I didn’t know how to explain it !
What I’m trying to achieve is something like this :

  • player finds stuff written in a foreign language ( looking like zakdhazkjfabf,b )
  • player can learn this language through the game, which implies that letters would be “translated” depending on the player progression

What I imagine I guess is a kind of array containing all the alphabet letters and for each a boolean (known/unknown)

When a message is read, it would ask a “reading” class how to display it, and the display class would check into a “language manager” which letters are known or not.

  • unknown letters, for each of these a random “letter” is picked (in an array, list, whatever).
  • if letter is “known”, the right letter is display.

The whole system is pretty “clear” to me(hum…), but I don’t really know how to manage the “runtime display” of the messages and how to write the classes…

Any input would be really appreciated !

Hmm how much writing is there? The best thing I can think of off of the top of my head is having a different textbox for each letter that renders in an unreadable font and if they have unlocked it, changing the font to something that actually represents the English alphabet (or whatever language it’s meant for) letter. This could be a huge pain to implement though.

The code itself would be pretty simple at least. Have an array that’s 26 booleans. Make a for loop that checks if each is true, if so change the font in the matching text box.

design question: is it just a single “strange character” per letter, or a random “strange character” question… if it’s a single character per real character users can decode the language without “knowing” it in game via basic puzzle solving… how “encrypted” do you want this?

Well, I already thought about Flaring Afro idea but as he mentioned, the one box/letter seems like a real pain in the neck…
Lefty, your question is not so relevant as I don’t think that it really matters from a “script” standpoint, does it ?Anyway, to answer, I want the player not to be able to deduce anything so I’m looking for a random stuff here.

( but again, this is not the tricky part, I could do something like :

  • unknown letter ?
    → then var RNG = random.range(1,20) and my letter just becomes a random sign in a 20 elements array.

The real work seems to be : how to get each letter printed without “baking” every possible combination or setting manually a textbox for each of them :confused:

Well here’s a fairly generic method of doing it:

public class StringMasker
{

    private HashSet<char> _unlocked = new HashSet<char>();
    private StringBuilder _builder = new StringBuilder();//recycle the string builder for gc efficiency
    private Random _rand = new Random();
    private char[] _maskSet;

    public StringMasker()
    {
        _maskSet = new char[] {'

You unlock characters with the ‘SetLocked’ method.

And you mask out a message with the ‘Mask’ method.

You can control the set of characters that are used for masking.

This only works with letters, you can modify to also mask numbers and other things too.

Note - completely untested, written in notepad real fast, just to give a general idea of how it would work. Tweak to your needs.

Honestly I had no idea how to explain this clearly, so I just slapped the code together instead.,‘!’, ‘A’, … insert full set of masking characters};
}

public StringMasker(char[] maskSet)
{
    _maskSet = maskSet;
}

public bool IsLocked(char c)
{
    return !_unlocked.Contains(c);
}

public void SetLocked(char c, bool locked)
{
    if(locked)
        _unlocked.Remove(c);
    else
        _unlocked.Add(c);
}

public string Mask(string s)
{
    _builder.Clear();
    if(s.Length > _builder.Capacity) _builder.Capacity = s.Length;

    //use enumerator for gc efficiency
    var e = s.GetEnumerator();
    while(e.MoveNext())
    {
        if(!char.IsLetter(e.Current) || _unlocked.Contains(e.Current))
            _builder.Append(e.Current);
        else
        {
            int i = _rand.Next(_maskSet.Length);
            _builder.Append(_maskSet[i]);
        }
    }

    return _builder.ToString();
}

}


You unlock characters with the 'SetLocked' method.

And you mask out a message with the 'Mask' method.

You can control the set of characters that are used for masking.

This only works with letters, you can modify to also mask numbers and other things too.

Note - completely untested, written in notepad real fast, just to give a general idea of how it would work. Tweak to your needs.

Honestly I had no idea how to explain this clearly, so I just slapped the code together instead.

Oh wait… I like this one better.

It allows you to set up the mask and the characters that are to be masked on the fly.

public class StringMasker
{

#region Fields

    private HashSet<char> _unlocked = new HashSet<char>();
    private StringBuilder _builder = new StringBuilder();//recycle the string builder for gc efficiency

    private Func<char, bool> _validate;
    private Func<char, char> _mask;

#endregion

#region CONSTRUCTOR

    public StringMasker()
    {
        this.Init(null, null);
    }

    public StringMasker(Func<char, bool> validateCallback)
    {
        this.Init(validateCallback, null);
    }

    public StringMasker(Func<char, bool> validateCallback, Func<char, char> maskCallback)
    {
        this.Init(validateCallback, maskCallback);
    }

    private void Init(Func<char, bool> validateCallback, Func<char, char> maskCallback)
    {
        if(validateCallback == null)
            validateCallback = (c) => !char.IsLetter(c);
        if (maskCallback == null)
        {
            var maskSet = new char[] {'

So like if you wanted to mask letters and numbers:

var masker = new StringMasker((c) => !(char.IsLetter(c) || char.IsDigit(c)));

,‘!’, ‘A’, … insert full set of masking characters};
var rand = new Random();
_mask = (c) => maskSet[rand.Next(maskSet.Length)];
}
}

#endregion

#region Properties

/// Returns true if the character should not be masked
public Func<char, bool> Validate
{
    get { return _validate; }
    set
    {
        if(value == null) throw new ArgumentNullException();
        _validate = value;
    }
}

/// Returns a masked character for the given character
public Func<char, char> Mask
{
    get { return _mask; }
    set
    {
        if(value == null) throw new ArgumentNullException();
        _mask = value;
    }
}

#endregion

#region Methods

public bool IsLocked(char c)
{
    return !_unlocked.Contains(c);
}

public void SetLocked(char c, bool locked)
{
    if(locked)
        _unlocked.Remove(c);
    else
        _unlocked.Add(c);
}

public string Mask(string s)
{
    _builder.Clear();
    if(s.Length > _builder.Capacity) _builder.Capacity = s.Length;

    //use enumerator for gc efficiency
    var e = s.GetEnumerator();
    while(e.MoveNext())
    {
        if(_unlocked.Contains(e.Current) || _validate.Contains(e.Current))
            _builder.Append(e.Current);
        else
            _builder.Append(_mask(e.Current));
    }

    return _builder.ToString();
}

#endregion

}


So like if you wanted to mask letters and numbers:

§DISCOURSE_HOISTED_CODE_1§

1 Like

@lordofduct having reread the thread I think he might be asking how to support two fonts within the same textbox since you can’t set font per char.
You might want to consider using a completely custom font where the “normal” characters are “normal” and the greek chars are replaced by your “alien symbols” and use the greek chars in the masking set.

*sets about trying to understand lod code :eyes::stuck_out_tongue: *

1 Like

Oh… did they want some other fonts thrown in there…

In that case I’d suggest creating a custom font (just google custom font creator and you’ll find various tools to do it… we did it to create a ‘handwritten’ font that looked like my buddies handwriting). With it, insert custom ‘weird’ glyphs for characters outside of the common character range (replace weird characters up in the 150 range or something). Then with my code, make the mask set be those characters.

There, now you have weird alien glyphs when masked. And real english characters when not.

2 Likes

Wow ! Thank u so much Lord, this seems really cool (i could never come up with such an advanced code)

I can’t test it before monday though, but I’ll let u know guys how it turn sur out :slight_smile: