Pencil

Reader

Read the latest posts from Pencil.

from Disaster Drawer

The kerfuffle was starting to wane at the periphery of my hearing, which was growing ever so closely to my immediate surroundings due to the long hours travelling from one point to the next, still on a seat that would constantly rumble and wobble due to the unstable weather. My seat neighbour would tell me that it was a common occurrence, and frequent travellers eventually got used to it, but by that point I barely had any energy to nod along with it without further worsening my sleep deprivation-induced migraines, let alone say that I couldn't have cared less. All the same, I somehow managed to make it to the other side, barely hanging on as I walked behind what felt like an endless line of people traversing a small, square hallway in the longest path physically possible. I made a vow to myself to never travel again, as I held back my tears, trying not to make a scene before dawn. As I stepped outside the birder control office, I was greeted by a mellow scent of raspberry that awakened my senses. The sweet aroma filled my nostrils, wrought havoc on my stomach and moistened my aching palate. And then, I heard a voice.

“Thank you for making it all the way here.”

Although admittedly foggy, ransacking my brain bore no result; I was certain of having never listened to that voice ever before, even if those words rang a distant bell of days past. While the more cautious side of my was tingling for caution, such was my exhaustion that I could not bring myself to care about my safety anymore. Whatever happened beyond this point, I told myself as my vision drifted away, was up to the ever-advancing hands of the clock to decide.

The first thing that I felt after that was the faint rumble of a car. I felt cramped, my knees to the height of my chest and my thighs aching; if I tried to stretch my legs, I would hit something firm with my feet, giving me no respite. I took a deep breath, and the smell of fabric came to me. Confused, I opened my eyes, and found myself lying atop someone else’s lap. I tried to spring away from her, but I was firmly held in place.

“Don’t move so suddenly! The car’s moving.”

The car? Am I being kidnapped, after all? I tried to articulate that I had very little money in my possession, but all that came out of my mouth was incoherent blabber. A finger was laid on top of my lips.

“We’ll have time to talk once you’re a little better rested.” “Is it all okay back there, madam?“ “Yes, it is. Please forgive me; my significant other just came from a day long journey.” “Sounds exhausting.” “I didn’t even want to bother with public transport at this point. But it’s okay – because he’s safe now.”

Consciousness drifted away soon after.

 
Read more...

from Disaster Drawer

Golden

Debían ser las seis de la mañana cuando nos detuvimos en frente de un café de carretera situado en las afueras de la ciudad. La luz de la luna era tenue aquella noche –era comprensible, la luna nueva andaba próxima– y no había ninguna luz artificial cerca más allá de las que proyectaban nuestras bicis –que sólo se activaba en movimiento–, por lo que las luces del café despedían un intenso aura que recordaba a un ángel salvador. Podría haber sido un mensajero celestial que venía a decirnos que toda la guerra había sido un mal sueño, una broma de mal gusto que ya había durado demasiado, pero no; tan sólo era un servicio de hostelería, tan mundano y atrapado en la miseria como nosotras mismas.

Por lo menos, cuando miraba al cielo, la luz de la luna seguía siendo real. Su brillo y su sonrisa quizá no hubieran sido tangibles, pero eso no la hacía una compañera de viaje menos digna en ningún grado. Mientras miraba al cielo, no podía dejar de preguntarme si Red estaría mirando al cielo en este momento. Era muy pronto, ella dormía hasta las diez o las once de un tirón –renacuaja, cómo te envidio–, pero me gustaba pensar que al menos estaba acostada de cara a la ventana y que podríamos haber visto juntas la luna sonriente de haberse despertado.

La guerra nos había traído dolor, desolación y confusión, pero no había podido separarnos; era en estos momentos de crudeza cuando la tan llamada naturaleza humana afloraba para recordarnos una vez más que no somos de piedra, y que dos personas pueden seguir juntas sin importar dónde se encuentren. Si esto hubiera pasado antes de la guerra, habría dado por sentado que volvería a ver a Red nada más entrar por la puerta grande de casa y colarme en su habitación. Podría ver su edredón rojo de lana tejido por la abuela, cubriéndola de los pies a la cabeza, haciendo juego con su pelo… sólo de pensarlo me parece estar viéndola aún después de tantos años. Pero estos tiempos en los que vivimos me han enseñado a no dar tantas cosas por sentado, a replantearme lo que significa una decisión y a sopesar de nuevo cuánto vale una sonrisa.

Por eso llevo plastificada una foto de las dos en el bolsillo de la americana, de forma que lo último que vea antes de morir sea su sonrisa angelical.

Purple

Le dije a Golden que esperase fuera mientras entraba a echar un vistazo, solo para asegurarme de que no era un lugar peligroso. Nada más entrar, pude sentir la presencia de un sinnúmero de espíritus protectores velando por la seguridad de la dueña del lugar y de todos los clientes presentes, que tampoco eran muchos. No había un solo rincón sin proteger ni una sola taza de café sin bendecir; era, en definitiva, un lugar en el que Golden necesitaba estar.

Estaba claro quiénes eran, aún sin utilizar mis útiles de zahorí: eran todos los viajeros que habían tenido que parar por ese café en algún momento de su viaje, asegurándose con una silenciosa sonrisa de que todo el mundo recibiese una buena comida y una velada tranquila. Nunca he creído en las llamadas señales gitanas, pero podría decirse que los espíritus veladores que custodian un lugar son la señal de los clarividentes como yo.

¿Alguna vez has sentido un escalofrío o una sensación de incomodidad al entrar en un sitio nuevo? Podría ser una advertencia, un lugar peligroso en el que no conviene permanecer mucho tiempo. Pero este no era un lugar peligroso en absoluto; más bien, era un lugar que te protegía de los males del mundo exterior.

Quizá si Golden permanecía allí el tiempo suficiente, las almas veladoras serían capaces de devolverle la tranquilidad ya perdida de su alma. Quizá, si permanecía el tiempo suficiente, incluso volvería a sonreír de forma sincera. Quizá esto le hiciera más bien que las escapadas, los paisajes y la luz del sol, ahora que la industria médica se ha vuelto inaccesible para todo el mundo y no podemos llevarla ante las manos de un profesional.

– No puedes confiar ni en los bares de carretera a día de hoy –le dije mientras entrábamos–, ¡pero este lugar es muy diferente! Las grandes compañías pecan de falta de alma, suenan a hueco y te dejan con mal cuerpo cuando sales, pero este lugar, tan pequeño y modesto, te va a proteger. Estoy segura de ello.

Golden trató de sonreír. Ella nunca creyó en estas cosas; a pesar de que intentaba interesarse por mis aficiones, siempre supe que no era un interés real. Me hacía muchas, muchas preguntas sobre ello, pero ninguna de ellas era una pregunta interesante ni quería profundizar en nada. Nunca se lo dije a la cara, ya que ella ya tiene bastantes problemas con los que lidiar, pero me dolía que no le interesaran de verdad estas cosas.

A veces sentía que estábamos destinadas a encontrarnos, pero siempre parecíamos chicas de mundos diferentes. Al final del día, nunca sabía qué pensar.

Golden

Lo primero que me pedí fue un caffé doppio; no es que estuviera cansada ni me gustara especialmente el café, pero habían pasado seis horas desde el último que me tomé y no me apetecía sentirme peor. El café se ha convertido en una de las cosas que más bebo –junto con agua para poder quitarme ese mal sabor de boca, pero al menos el día sólo tiene 24 horas y me paso 10 de ellas durmiendo, así que no me va a dar una sobredosis a corto plazo.

Purple por su parte era un espécimen especial, capaz de tomarse una cerveza en cualquier momento y lugar. A veces me preguntaba si no sería como una planta que sustituye la luz del sol por el alcohol, haciendo la etanosíntesis en lugar de la fotosíntesis convencional. Estuve a punto de decírselo, pero me pareció un chiste tan malo que me dio vergüenza –y eso ya es decir mucho.

Nos fuimos a una mesa que estaba junto a una ventana. No había nada que ver, era todo noche y polvo, con acentos de luz; sin embargo, teníamos que vigilar que no les pasara nada a nuestras bicicletas, porque se había convertido en el único medio de transporte que quedaba desde que estalló la guerra. Ya no había autobuses, ya no había trenes, y todo el petróleo que se podía extraer era destinado a alimentar las máquinas, por lo que era crucial encontrar un medio de transporte autopropulsado. Si alguna vez vuelve todo a la normalidad, el mundo que nos quedará será decididamente distinto al que hemos conocido, aunque no sé si quiero llegar a ver lo que será de todos nosotros.

Había retazos de conversación flotando por todas partes. Si bien los únicos rostros que podía ver eran los de la dependienta y su hija, pude contar una docena de voces resonando a lo largo y ancho del edificio. En tiempos pasados, habría creído que había sucumbido a la locura. Ahora, ya nada me importaba. Sorbí el café y guardé silencio.

– Purple, ¿qué crees que habrá sido de nuestras hermanas? – ¿Por qué preguntas eso tan de repente? – ¿A qué te refieres, de repente? Llevo preguntando eso todo el viaje. Que me hayas ignorado no quiere decir que no te lo haya estado preguntando, y varias veces.

Purple miró hacia la mesa, hacia el resplandor dorado que rebotaba contra la caoba. Era difícil discernir si estaba cansada o melancólica.

– Procuro no pensar en ello cuando estoy despierta, la verdad –confesó–. Ya es lo bastante complicado mantenerse cuerda cuando las ves en sueños una y otra vez. Quiero acercarme, preguntarles qué ha sido de ellas, dónde están… -Tomó un trago– Por un lado sé que no son ellas de verdad, que las de verdad están ahí fuera, pero por otro lado me da miedo que esté viendo todo lo que queda de ellas.

«Todo lo que queda de ellas.»

Purple siempre había podido ver a las voces que yo sólo puedo escuchar, y me explicaba que eran las almas de las personas que alguna vez habían estado en este mundo. Ella me contaba las historias que había detrás de ellas, como si pudiera ver su pasado completo de un chasquido, por lo que yo le preguntaba si podía ver a Red y a Ginger. Pero siempre me decía lo mismo: «en sueños, siempre las veo; despierta, todavía no».

– Pero, si las ves en sueños, ¿quiere eso decir que nos están buscando?

Guardó silencio.

 
Read more...

from HellOps

Let's set the scene. I'm taking over an existing, already set up operation. The topology, per-DC, is something like this:

  • Two redundant gateways, talking via heartbeat – if one dies, the other takes over. Both of them running raid1 mdadm ext4 everything.
  • Three database servers as a percona cluster. Data is on raid1 mdadm ext4, but the base OS is on regular ext4. Var is its own partition and is xfs.
  • A bunch of application servers running standalone ext4.
  • A “backup” server whose job it is to talk to the other machines and take backups. Backups stored locally on its own disk and on an external (usb) disk plugged into it at all times. This machine actually ran UEFI, and thus had a FAT32 partition. It had an experimental btrfs partition on top of the standard standalone ext4. External disk also ext4.

Note that this is a relatively low IO use-case (high on network and compute). The XFS var partition on the DBs probably has half the disk IO use of the rack.

There's several racks like this in different enterprise colocation datacenters. All of them have shared ventilation, air conditioning, PSUs, backup generators, etc. As such, for cost saving all of them are plugged into standard electrical outlets (no in-rack PSU – there's already one handled by the colo!).

One day, there's a huge storm going around. A quarter of the city is already dark, but neither the office nor any of the colocations is. Slowly, more and more of the city's infrastructure goes down (it ended up with being closer to ½ by the end of things). Eventually, everything goes dark in the office. As are two colos. We decide the power is dead and just go home – it'll come back up. The next day, we check. One of the colocations came back up just fine. One of them, however, did not. So grabbing my winter coat (it is very cold in the DC), I head there to look at what's going on.

All of the application servers won't boot. I boot into a rescue system and check – the root partition is dead. On all of them. E2fsck won't even try to repair anything. Okay, let's check the gateways and database servers. Ext4 partitions are dead. Including the raid1 ones. The errors are different across the copies. Well what about the external backup disk? That's just completely dead. Actually fried. Will not even spin up. It was working fine the day before! Some of the drives in general are also fried, mind you – above I was talking about the ones that survived the situation.

I spend the week trying to manually recover data, since e2fsck refused. Things seem to be corrupted at random. For every file I recover, there's one I can't. What's weirder, some of the corrupted files are ones that should not have been experiencing writes at all! I was essentially flying blind (a lot of metadata blocks were also gone) so for every db file I recovered I also recovered something completely useless (like the local cat(1) binary).

At this point, I get curious, asking that DC's administration on what even happened. They say a lightning bolt hit the top of the building. Wait so the shock blew past the UPS, into the servers, frying a bunch of things? How are the motherboards ok? Why didn't the power supplies try to surge protect? I'll never have answers for these questions, though I do know that the PSUs are likely too old to have good protections in place, and the servers did not run on ECC ram (potentially explaining at least some of the corruptions, though far from all of them).

This wasn't that huge of a deal. Databases were recovered from backup (albeit a slightly older one, more on this in a second). The rest of everything just got a clean install from scratch.

What really stood out for me, however, were what survived. The fat32 EFI partition did! The XFS partitions on the database servers either survived intact, or an fsck recovered them. The experimental btrfs partition on the backup host (the source for the database recovery, a bit older because it wasn't in active use yet) had zero issues whatsoever. If it hadn't survived, an even older copy would be available from another DC's backup server (they inter-sync).

That day I learned a couple of lessons:

  1. Use logical backups of data that's important – the other stuff may make restoring as a whole faster, but actively get in the way in most other cases, while also making the backups slower, more cumbersome, and thus less likely to happen often.
  2. Ext4 will eat your data at the slightest provocation, in unpredictable ways.
  3. Lightning strikes will eat your data. Do not trust shared UPS.
  4. Btrfs can survive acts of god (something that it has consistently done for me afterwards as well!). XFS is resistant to acts of god. FAT32 is too dumb to realize what is before it is an act of god, making it similarly resistant for all the wrong reasons.
 
Read more...

from Bunker Labs

I saw people being confused about message queues, so I figured I'd implement one in shell, just for fun. This would also let us explore the common pitfalls in implementing them.

What is a Message Queue?

A message queue is conceptually simple – it's a queue. You know, like the opposite of a stack. You put stuff in it, and later you can take stuff out. The “stuff” are messages. Of course, there is a very limited use-case to having a single queue. So instead, you want to have multiple, “named” queues (i.e “collections”).

Another part of a message queue is how you access it. There is a common type of MQ (Message Queue) called “pub/sub” – in this scheme, the MQ server keeps open connections to all the “subscribers” and sends all of them the message whenever it arrives. The other one is poll-based – the queue keeps each message until it gets explicitly read by a connection, via some sort of “reserve” keyword. This latter type is what we'll be implementing.

So, we have a few basic operations to implement:

  • Write a message to a named queue.
  • Read a message from a named queue.

That's really all there is to it! So let's get to implementing.

Storage Format

We can keep a queue in a flat file. We'll call it "$queue".queue. This allows us to have almost free writes – we just append to the file. Let's not worry about networking for now and write this down in ./lib/push.

# add message from stdin to queue
cat >> "$queue".queue

This has an obvious potential issue: shell operates line-wise, so what if the message we're writing is longer than a one-liner? We'll use the base64 utility. Note that it isn't part of POSIX, but neither is nmap's ncat (which we're going to be using for networking later), with both being extremely common.

We can now rewrite the above like this:

# add message from stdin to queue
base64 >> "$queue".queue

We're still assuming that we're going to get the message via stdin (somehow), and that the queue environment variable will be populated with the queue name.

Still, this storage format is pretty simple – the messages are listed, in order, oldest first, one per line. We can guarantee the “one per line” part because we base64-encode the messages.

Reading Just One Message

We need a way to pop items off the queue. Since we can guarantee there's only one message per line, it means getting the first message (first line) and everything else separately. Let's write a simple utility ./lib/pop that will print the topmost message (decoded), and truncate the old file.

# print message
head -n1 "$queue".queue | base64 -d
# get remaining messages
tail -n+2 "$queue".queue > "$queue".cut
# move post-cut queue into the true queue
mv "$queue".cut "$queue".queue

This has a few obvious disadvantages – it's full of crash-related race conditions. It does do the job, though, so we'll keep it for now.

Networking

We're going to use nmap's netcat implementation to handle networking for us. Initially, it'll look roughly like so, in ./launch:

export PATH="$(dirname $0)/lib:$PATH"
while ncat -l 1234 -c handler; do :; done

This will repeatedly make netcat listen on port 1234. Once a connection arrives, it'll run the handler binary found in PATH. Stdin of handler will be filled with data from the network pipe, and whatever handler prints to stdout will be sent back. Notably, stderr will not be sent over.

Let's write this handler, then: ./lib/handler:

#!/bin/sh
read cmd queue
[ -z "$queue" ] && queue=default
export queue

case "$cmd" in
pop) . pop ;;
push) . push ;;
esac

exit 0

This determines our wire format. The first line sent by the server will contain the command, followed by spaces or tabs, followed by an optional queue name. If there is no queue name, we assume the name is “default”. Currently, valid commands are “pop” and “push”, which run our previously made commands in .. Finally, after handling is done, we successfully quit.

If we want to add more commands, we can do it in the case "$cmd" section later.

Trying it Out

Let's launch it! ./launch

We can connect and see how things behave:

ncat localhost 1234
pop
^D # no output

ncat localhost 1234
push
package 1
^D

ncat localhost 1234
push
package 2
^D

ncat localhost 1234
pop
^D # package 1

Well, that's fun, it's already functional! We can improve it, however.

Crash Race Conditions

We're designing a serious MQ, so we need to think about potential failures. What if the process crashes during a transaction!? We should consider this.

If the launcher loop dies, the server is dead, not much surprise there, so we can ignore it. What if we pop, but crash after sending the data back, but before truncating the old data? This is actually relatively likely with larger queues because we need to process the entire file every time. Let's fix this by implementing a rudimentary rollback journal (first, without actually using it):

CUT="$queue".cut
OUT="$queue".out
QUEUE="$queue".queue

# determine message to send
head -n1 "$QUEUE" | base64 -d > "$OUT"

# calculate remaining messages
tail -n+2 "$QUEUE" > "$CUT"

# move post-queue into the true queue
cp "$CUT" "$QUEUE"

# send the message
cat "$OUT"

# delete rollback journal
rm "$CUT" "$OUT"

We now have a multipart rollback journal. Let's say we crashed before sending the message, and wanted to manually roll back the transaction. We could do that! We would need to write a base64 encoding of $OUT to a file, then append that file with $CUT, and we would have the old state back.

It bears noting that this is not how rollback journals are typically implemented – usually they're implemented by making a copy of the data, then operating on the “real” dataset, with rollback triggering a copy back, and a commit triggering a deletion of the journal. This non-traditional approach allows us to also keep the last transaction in mind for potential repeating, since we want to avoid dropping any jobs.

Of course because we have a queue, the actual state never has to be rolled back. New writes can be added to the state with no problem, and new reads can simply use the rollback journal's data as-is. With this understanding, we can now utilize it:

CUT="$queue".cut
OUT="$queue".out
QUEUE="$queue".queue

# create rollback journal if we don't have one yet
if ! [ -f "$CUT" ]; then
    # this step is idempotent
    head -n1 "$QUEUE" | base64 -d > "$OUT"
    tail -n+2 "$QUEUE" > "$CUT"
fi

# we might have been interrupted last round
# but this is idempotent
# so always do it
cp "$CUT" "$QUEUE"

# finish transaction and delete the rollback journal
cat "$OUT"
rm "$CUT" "$OUT"

Now the operations that take a while (the head, tail, and cp invocations) are guarded by the rollback journal. The only place where corruption can occur is between printing sending the message over and deleting the rollback journal. Furthermore, the consequence of this crash would simply be a repeat send of the message (a much less disastrous consequence than dropping a message).

We didn't eliminate the crash race condition per se, we simply reduced the odds of it triggering dramatically with only a handful of additional lines of code.

Let's take a similar approach for the push operation, but with a copy-on-write (CoW) write-ahead log (WAL). The idea behind the write-ahead log is that doing a verbatim write is faster than an append with post-processing, and that we can resume the post-processing later if need be. Let's look at what kind of workflow we expect to have:

QUEUE="$queue".queue
WAL="$queue".wal

# we perform a fast write
cat > "$WAL".1

# then we do the processing
base64 "$WAL".1 > "$WAL".2

# and the appending
cat "$QUEUE" "$WAL".2 > "$WAL".3

# then we commit
cp "$WAL".3 "$QUEUE"
rm "$WAL".*

As far as the client is concerned, as long as we do those other steps later, the push is done as soon as $WAL.1 is created. The processing can be done “in the background”, between invocations. Let's write the processor wal first:

QUEUE="$queue".queue
WAL="$queue".wal

# there's a transaction to handle
if [ -f "$WAL".1 ]; then
    [ -f "$WAL".2 ] || base64 "$WAL".1 > "$WAL".2
    # we always repeat this step,
    # in case a read has already changed the queue
    cat "$QUEUE" "$WAL".2 > "$WAL".3
    cp "$WAL".3 "$QUEUE"
    rm "$WAL".*
fi

Now we can call it as a part of our launcher loop:

#!/bin/sh
export PATH="$PWD/lib:$PATH"
# process any remaining transactions
checkpoint() (
    for queue in *.queue; do
        queue=$(basename "$queue" .queue)
        . wal
    done
)
checkpoint
while ncat -l 1234 -c handler; do
    # if the handler crashed, we can catch it here
    checkpoint
done

Just as before – we didn't entirely eliminate the crash race condition. After all, the server could crash in the middle of a push. And if we added a notification for completed pushes, the notification could fail to come, while the push would happen. However, we've significantly reduced the odds of queue corruption, to the point where we can avoid worrying about it as much.

Notably, this approach results in potentially missed or corrupted writes, as opposed to potential double-writes. This is to demonstrate how that's done, as opposed to the double-read philosophy we took with pop.

Parallelism

At this point, the server is done, if we're content with a single thread! What if two clients connect simultaneously? As of currently, they can't.

I'm done messing around for today, though, so maybe a follow-up (in a branch) will be made to provide parallelism.

You can find this version of the server over on github.

 
Read more...

from Hannah's Tip Corner

After getting lost in the UHS trying to find out what I was missing, I decided to compile a few hints that seem to work for pretty much everything. I have played and watched a couple of P&C's myself, and I can say that Syberia 1 does things a little differently. For one, there's no “combination” mechanic; you can use everything as-is.

In fact, some people have gone as far as claiming that this is less of a puzzle game and more of an interactive novel. For this reason, if you have the patience to sit through endless conversations and read through documents in seek for hints, this is probably what I'd consider the easiest P&C I've played.

Table of contents

Comparing different releases

PC (Steam) release (tested on Fedora 35):

  • Regular Proton crashes; use GE instead.
  • It will only run in 800x600 windowed mode. dgVoodoo seems to do nothing via Wine, and Dxwnd will crash as soon as you try to set a higher window size.
  • Recommended to use accessibility tools (you need to read documents to get hints).
  • Includes a complete PDF walkthrough if you open the system files.
  • You need to manually hide the cursor, or it will overlap the in-game cursor. Furthermore, it seems that this can only be achieved on X11.

Switch (Syberia 1 & 2) release:

  • There are two alternative modes — touchscreen and controller. Touchscreen mode highlights all elements you can interact with at every moment. Controller mode scrolls through all elements you can interact with, but it does not show them all at once.
  • Phone will not let you use the number pad (phone numbers are added to your contact list automatically).
  • Long dialogues scroll very fast. There are several languages to choose from, so choose one you can understand by hearing. Languages available: German, English, Spanish, French, Italian, Russian, Polish and Japanese.
  • Autosave every time you do something or move from one screen to the next.
  • Bonus content you unlock as you progress (concept sketches, as far as I've seen so far).

DS release:

  • No voice acting.
  • Menu is displayed on the top screen. Touchscreen replaces the mouse.
  • Number pad is hidden.
  • Cinematics look mostly like they do on PC (it seems to be a direct port, after all).
  • Drag items to use them.
  • On the items menu, drag items below the Read sign (not onto).

Have you covered every conversation topic?

I am the kind of person that tries to get to know every NPC, but I know people who just skips dialogue and skims through. In here, you pretty much need to go out of your way to hit every conversation topic at least once. Not only they're giving you hints (duh), but some events are only triggered after hitting the right conversation topics.

Listen to the phone calls, too!

Considering phone calls come from nowhere and disrupt the flow, I wouldn't be surprised if you wanted to ignore them. However, phone calls are also important in the game, as one character will give you a hint you need to use later on.

Maybe you need to check the leaflets again!

I also tend to read every item description and every book, trying to get as much of the lore as possible for extra flavour. This is actually a common trope (2x duh), but sometimes the tips are actually in a leaflet (or a book, or a newspaper cutout, or a-) that you read a long while ago and have forgotten about since.

Talk with the NPCs again! (And listen to them again)

This game seems to be heavy on conversation; you really need to invest yourself in the characters for the plot to progress. Not only is this game lacking combination items, but it also seems to be lax in item usage altogether (at least early on). And remember – they're giving you hints, you need to listen (3x duh)!

A small puzzle spoiler, not saying which one

There is one puzzle where you will only get through after having a back-and-forth conversation with three different parties. You don't need to hit every conversation topic every single time, you will know what you need to choose, but bear this in mind before trying to look for missing items for the upteenth time.

 
Read more...