Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - fernewelten

#101
Completed Game Announcements / Commando Raid
Sun 12/09/2021 00:33:37
Hello community,

after much delay, I'd like to present my game and tied winner of the  MAGS 2018/05 jam (Theme: “Rats”):



The Devious and Daring
Commando Raid
of Linkattus, The Lowly Janitor Rat,
In Order to Free
Ratzelda, the Princess of His Dreams,
And to Get Her, Too

(What? That whole string is the title of this adventure! 8-) )

It features:

  • a BASS like interface,
  • hand-drawn art in Inkscape,
  • original music, recorded from a Yamaha keyboard and edited in Audacity
  • the AGS system by Chris Jones and later contributors
  • lots of Adventuring and Frolicking :-)
  • Rats
  • and a Cat.
Oh, and bugs (probably :-[ ).


Get the game here

Have lots of fun!
#102
I'm not quite sure where to put this, so I'm going to put this here.

I started out without using any source control whatsoever. My games all had an "_Assets" folder within the main game folder that contained all the assets and their respective source files for the game.

For backups and intermediate states, I simply copied all the whole main game folder with all its files to an USB stick into a suitably named folder ("AGS/TheSpecificGame/1999-12-04a/" and such). Nowadays, sticks have so much memory that a single stick will have storage for many saves even if you blindly copy all the files. And my computer itself is set up with an automatic backup system that does regular saves, so this simple system was enough to guarantee that I'd never lose more than a few hour's work in case of a system failure. That was sufficient for the typical month-long jam.

Trouble is, by now i've written several adventures, and this simple system has rapidly come to its limits.

By now,

  • The different adventures have their own assets (of course)
  • but they also share some assets, particularly background music, sounds, fonts, cursor sprites, and character sprites.
  • Shared assets evolve at a different pace from the games that use them. They've become separate, independent entities with their own version progression.
  • The adventures and assets have been written with different AGS versions. Different versions aren't always freely exchangeable, due to their file format: If GUIs or (I think) modules have been saved with a specific AGS version, they won't be importable into an AGS that is older. If I don't want to be forced to upgrade the whole game just because I need to fix something tiny, I need to juggle with different save formats.
  • Due to space constraints, my games proper have ended up at a different place from the shared assets, on another volume even.

Simply "saving everything" won't cut it any longer, it's no longer error-proof when different shared assets in different places are involved.

Just source controlling the game would similarly not be good enough; how do I keep the shared files in sync that reside in different locations, even on a different volume?

Putting a copy of the shared assets into the individual games is ugly, too. Then if the copy of the assets is modified/improved, these modifications might get lost on the original shared asset.

So something must come; I haven't a clear idea what exactly.

What system have you come up with to keep track of all your sprites, pics, and sources?

BTW. I'm noticing that the AGS documentation on source control discusses SourceSafe (that I've never heard of) but not git. AGS doesn't detect git either although git is indeed installed on my box and integrated into Visual Studio.



#103
There's a very good argument for getting vaccinated:

All the other measures are meant for protecting the bystanders, not so much yourself. For instance, by wearing a surgical mask, you are mainly filtering your own breath that might contain the virus so that it won't reach the bystanders.

This means that if you go to some public event, you are at the mercy of everyone else abiding by the rules. If some aren't, you might be exposed to a superspreader event without being wise.

You can check at a glance whether everyone in the room is wearing a mask, but try checking at a glance whether everyone in the room that claims to have been tested negative in the last 24 hours has actually been tested with a negative result. There's been some shenanigans going on, and some “official” testing stations have actually been caught at certifying a test that they haven't actually done. And those "antigen" tests that are usually used for this so-called "passporting" haven't really been designed for that use case; they aren't really reliable enough although they are still used that way.

Unless ... you're vaccinated yourself. Getting vaccinated is a measure that is designed to protect you yourself from a "severe" course of disease and that is effective at protecting you even if not all the bystanders are playing by the rules.
#104
2x Biontech / Pfizer. I've been formally counted as “completely vaccinated” (as per the German definition) since the start of August.

I didn't get any ache; got by with some tingling in the arm that got the jab and some fatigue. Both times the effects went away within 24 hours.The second time around, the effects were more pronounced than the first time, but even then it was just a nuisance, I wasn't hindered or incapacitated in any way.

I did refrain from doing sports or manual work on the day that I got the jab and the day after, as per the doctor's recommendation.

The first time around, getting vaccinated was still a Very Big Thing: I'd telephoned a central hotline for days and days to get an appointment in any of five vaccination centres in a 40-mile radius, with no luck whatsover. You weren't allowed to put your name on any waiting list, but “feel free to try again in some hours' time.”  :~( Then I got lucky at last in my family doctor's office. The vaccines were rationed and so I had to prove that I was even entitled to get the shot.

Five weeks later, they had set up a tent on the parking lot of the local supermarket. “Come in droves, tell friends and acquaintances, we've got plenty of all the brands. What's keeping you all?” I got my jab and bought some salad afterwards. Oh my, how times have been changing!


#105
What the engine needs of all this is only in structs, at what offsets the pointers are and what the types of thes pointers are.

We could store this separately for the benefit of the engine as a compact list of (offset, type-id), e.g.,
<id> -->
<number_of_entries>
<offset_1><type_id_1>
<offset_2><type_id_2>
....
<offset_n><type_id_n>
#106
So currently, what I basically have as type information in the symbol table is this:

A type is either atomic

  • primitive types: int, short, char; float; string
  • enumerations (currently equivalent to int)
or compound

  • non-dynamic array with specific_number elements of a type
  • dynarray of a type
  • dynpointer of type
  • struct, composed of

    • optionally the parent (another struct)
    • a list of (fieldname, type)

There's no built-in restriction in the symbol table itself that compound types must consist of atomic types. Compound types can consist of compound types. (But the compiler ensures with code that the types are limited by what the engine can currently handle. For instance, no dynarrays of structs that contain pointers and non-pointers.)

That's what has already been implemented, i.e., what the (new) compiler is currently working with.
#107
Quote from: Crimson Wizard on Thu 15/07/2021 11:35:59
I did a small experiment for fun, generating such table along with the script data, and letting engine consult it when disposing managed structs.
https://github.com/ivan-mogilko/ags-refactoring/commits/experiment--rtti

Having a look to see just what the compiler would need to provide.
#108
Quote from: fernewelten on Tue 03/08/2021 00:50:41
I _think_ there's a way to get all of the InputBox input to show: Namely, by configuring a really tiny font directly before calling Game.InputBox() and restoring the original configuration directly after.

I've found it. Include some tiny (for a 720p game) font and name it, e.g., eFontTiny. Do
Code: ags

FontType current_font = Game.NormalFont;
Game.NormalFont = eFontTiny;
String answer = Game.InputBox();
Game.NormalFont = current_font;


The input box won't get any bigger and will stay just as ugly, but the text that is input now fits into its area, and the button texts aren't off.

In principle, that would work with SaveGame() and RestoreGame(), too. But there's no good place to restore Game.NormalFont to what it was. These windows are always displayed after the end of the current control flow no matter where the corresponding functions have been called.



Edit: Implemented this in Castle escape; 12 pt seems to work best with the font
Also reworded the "Present" question.

#109
I've been thinking about Crimson's idea a little.

Here's a very tentative and high-level idea that builds on this.

Currently, the Editor is holding a complete copy of the Compiler.
When a program is run in debug mode and halted, then the Editor is running.
This means that the Compiler is available at that point in time and can be called.
It might "compile" an expression such as "Weapon[15].Shield.Damage",
and then you'd get the Bytecode for it, i.e., a step-for-step instruction for the Engine of just how to reach that value at this point in time.
The Engine already knows how to run Bytecode.
It could be configured to save its current state (content of the registers and so on) and then temporarily execute the Bytecode of the expression.
Then it would have the expression result in AX (or in the memory cell that MAR points to), ready to be passed to the Editor to be displayed.
Afterwards, it would retrieve its current state and continue running.

Now we don't need to see the compiler as a cumbersome and heavy-weight blob of software that can only deal with complete programs:
it consists of several separate classes that can operate independently, such as a scanning class..
These parts of the compiler that specifically deal with expressions could be further split off, giving an "expression parser class".
The compiler itself would use this "expression parser class", and the "expression parser class" could also be used independently.
That's what would happen at debugging time:
For each expression to be watched, the debugging mode of the Editor would call the scanner class and then the "expression parser class".

It's inevitable that the compiler will evolve over time.
Modifications will be made, new features will be added, and so on.
In these cases, the "debugger" will neatly follow suit.
It uses the same parts that the compiler uses, so when the compiler changes, the debugger changes.
So the "debugger code" can't become out ouf sync to the "compiler code".

This is an advantage of the approach. But this can also be a disadvantage:
The compiler would no longer be free to do whatever it wants to.
There would be an interface that the debugger uses,
and that interface would need to remain rather stable.
And so the compiler would also need to be rather stable, as concerns calling this interface.

An expression such as  "Weapon[15].Shield.Damage" changes its meaning dependent on the context.
For instance, "Weapon" might be a local variable at some point in time, and another local variable at another point in time.
So we will need to construct the context at the point that is being debugged.
When the compiler runs its proper compiling run, it has this context available: When it's in the middle of compiling some function, it knows exactly what variables are at what stack offsets and so on.
When the debugger runs and wants to query a variable, this context must be reconstructed.
For instance, when the debugger halts, e.g., on line 42 of "globalscript.asc", then the context at this line 42 must be reconstructed.
This means that the compiler must write the various contexts into, e.g., a debugging file in the proper compiling run,
and a function such as "recall_context(debugging_file, "globalscript.asc", 42)" must be provided that the debugger can use.

So in total, when the debugger halts alt line 42 of file "globalscript.asc" and wants to know the value of "Weapon[15].Shield.Damage", it must;
- call recall_context(debugging_file, "globalscript.asc", 42)
- call expression_parse(scan("Weapon[15].Shield.Damage"))
- pass the resulting Bytecode to the Engine for executing
- the Engine must save its current state,
- execute the Bytecode
- report AX (or the value of the memory that MAR points to)
- restore its current state

------

We have:
the compiler
the Engine

We need
- to split off the expression parser from the compiler. This is time-consuming, but will strongly improve the compiler (it will become more modularized and easier to modify and extend).
- to make the compiler write the context information. This information is available in the symbol table. It gets there incrementally, so at the point where a local variable is added or invalidated, this can also be written into the "debugging file". This part is probably fairly easy.
- to write recall_context(). One way of going about it is to start with a given context, e.g., at the start of a function, and then "replay" the context steps until the line in question is reached. This can probably be done with middling effort.
- The last two steps must be developed in tandem, of course.

- to prepare the Engine for
    = saving its state, executing "temporary" bytecode, restoring its state
    = passing register AX (or the value that MAR points to) to the Editor
I don't know enough of the Engine to make educated guesses on how cumbrous this is.

By the way, if the compiler can find an instruction sequence that makes MAR point to the memory that contains the value, then it is possible in principle to "patch in" another value at debugging time. So variables can not only be watched but even modified. This may open a can of worms, so we'd better not do this right from the beginning. But it's a perspective.
#110
I _think_ there's a way to get all of the InputBox input to show: Namely, by configuring a really tiny font directly before calling Game.InputBox() and restoring the original configuration directly after.

I'll have to look up the details. If I remember correctly, you need to configure some specific font number (might be the font #1) or the font used for Dialog() commands or some such ... 

That shouldn't be too hard to put in and make the Shoes puzzle much more playable.
#111
Quote from: heltenjon on Mon 02/08/2021 23:01:48
How is the input box supposed to look?

Here's a screenshot of my setup:


Yes, this is u-g-l-y and a custom GUI would look much nicer. But there's a very good reason to prefer the humble Game.InputBox() in a game jam context: AGS doesn't have the concept of a "modal" GUI. As soon as you put up your own GUI, you break up your program flow very drastically and are saddled with lots of gratuitous code ugliness.

For instance, here in the current example, I'm in the middle of an AGS 'dialog'. I can EITHER  do String answer = Game.Inputbox(); and continue with processing answer at once. That's all I need. answer is a local variable, and when I've done with it, it will go away automatically.

OR, the alternative is to design a custom GUI, which is time-consuming. Then I need to do SomeGui.Visible = true; into my code and exit out of the AGS 'dialog' completely at this point. Control will continue at a completely different place in code (i.e, with the event handler of the OK button of the GUI), so the context of where I came from is unavailable.  In order to get at the answer and process it, I will have to use an ugly global variable (probably a text field of that GUI). That variable will never go away, and remnants from old answers in it can wreak havoc when I'm not careful. When I happen to call that custom GUI several times from different places, then the program flow will always end up at the same place, (i.e., in the exact same button event handler), no matter where the logic has come from, so I have to resort to very ugly kludges to keep the different control flows apart. ...

,,, well I'd better stop with my ranting right now. You get the picture. The point is, in a jam context where you're stressed for time, the lowly Game.InputBox is far superior to custom GUIs, for all its ugliness.  :X
#112
Quote from: Shadow1000 on Mon 02/08/2021 22:02:52
I am confused about your first suggestion of
Spoiler
standing on the nighttable and looking under the canopy
[close]
How does that participate in the solution...?

This will become important when Lady Anemone has got her alarm clock.

Spoiler
Bumbley will find himself imprisoned in his own bedroom. So now he must somehow sway his captors. It may be called, "freedom", but it isn't free of charge...
[close]
#113
This might be a left-click / right-click issue. In order to find the alarm clock, I've coded that
Spoiler
Bumbly must EXAMINE (right-click on) the spot under the bed.

INTERACTING (left-click) won't work (Bumbley will think that you want him to dust there and won't see the point of that)
USING INVENTORY won't work either without having examined the spot first (Bumbley will think that you want to deposit the book there for bedtime reading).
[close]
#114
Quote from: heltenjon on Mon 02/08/2021 20:46:04
My problem was that
Spoiler
The dialogue box wasn't showing. I didn't know that I could type anything. This ought to be inside a square, I think.
[close]

In my opinion, that's more of a bug in the AGS than a coding error: I am using the command "Game.Inputbox()" and that should show the box no matter what. If there is a way to reproduce the error, we might report it. I've had no luck reproducing it on my system.
#115
Quote from: heltenjon on Mon 02/08/2021 16:22:42
I'm stuck on the shoes puzzle. I've exhausted the dialogue, and the shoes basically tell me
Spoiler
that they want to be polished.
[close]



You're n-e-a-r-l-y there! :-D
But it seemingly isn't clear that a substantive is needed. I'd better rephrase the dialog option then. Would the following work better?
Code: ags

player: "I could find you a present! What do you say to the following item:"
    String answer = Game.InputBox("!My offer:"); 


Any answer for "present" will work
Spoiler
that contains "shoe polish" or for that matter, "polish" in any (upper or lower) casing.
[close]
#116
I don't know exactly where you're stuck.

If you've retrieved the alarm clock,
Spoiler
either interact with the door or use the alarm clock on the door.
[close]

If you have found out what the shoes want

I thing I've made a mistake here. I should have put better signposting in a specific hotspot. As it is, you always get the same reaction even when you've made progress which is bad.

So here goes:
Spoiler
If you examine some things, specific details will only become apparent if you are really near to them
[close]
Spoiler
Examine under the canopy when standing on the nighttable
[close]

Spoiler
Anemone has locked the wardrope, but perhaps there's something important inside?
[close]
#117
I like your art style. What drawing program did you do your art in?
#118
About the shoes puzzle ... here's a little tip that may help:

When the conversation subject starts touching bribes trades presents...
Spoiler
the shoes start to obsess on one specific word in their replies ...
[close]

These options are among the ones that stay turned on (if I haven't made a coding mistake) and so are ready for replay.
#119
So I'd like to proudly present, as an entry for MAGS July 2021:

Castle Escape: Chapter 1
Count Bumbley is a brave chap that is living in a castle. One day, his girlfriend of two years is springing a little surprise on him ... and he must do something fast to prevent an imminent catastrophe from happening.

Help Bumbley save his life ... or at least life as he knows it!

Standard BASS interface (left-click: interact, right-click: Examine).
Get the inventory via the top-left  "hamburger" icon or by hitting "i".

Get the game here:

There are bound to still be rough edges, sorry about that.

I haven't had the time to do a 'Credits' room, but the upshot is, this has been a lone ride.
#120
The standard 'C' and 'C++' way of concatenating literal strings is to separate them by whitespace: Whenever the compiler encounters "This is" " a " "string " "in " "five parts." it converts this into one big literal string "This is a string in five parts." and then processes this big literal string.

Newlines are a kind of whitespace, so that allows you to put several strings  onto several lines:

(not implemented)
Code: ags

cButcher.SayAtBubble(butcher_talk_x,butcher_talk_y,
    "&3 I am the only one of my kind here. \n"
    "My pappa left me. My mother was destroyed. \n"
    "I am ashamed...");


I've toyed repeatedly with suggesting and implementing this in the new compiler, but haven't gotten around to get this started.
SMF spam blocked by CleanTalk