andybalaam / rabbit-escape

Android and PC game inspired by Lemmings and Pingus
http://artificialworlds.net/rabbit-escape
GNU General Public License v2.0
73 stars 40 forks source link

RFC: Hydrodynamics #298

Closed tttppp closed 8 years ago

tttppp commented 8 years ago

This isn't Minecraft, but maybe it could get a little closer...

This is a discussion of water, how it affects rabbits and how it interacts with its surroundings.

I propose four water related states:

  1. Springs - water is generated by these.
  2. Water fall - This is a square through which water is falling.
  3. River - This is water about half a square deep, which is non-fatal to rabbits.
  4. Pool - This is water a whole square deep and is fatal to normal rabbits (introduction of snorkels may change things).

Water will follow a path according to the following rules:

  1. A space with a water fall, spring or river above it becomes a water fall.
  2. A water fall with ground or pool under it becomes a river.
  3. A space with ground or pool under it and river next to it becomes a river.
  4. A horizontal row of rivers squares bounded at both ends by walls/ramps becomes a horizontal row of pool squares.
  5. A pool or river without ground under it becomes a water fall (e.g. could be caused by bashing).
  6. A pool with water fall next to it becomes a river.
  7. A horizontal collection of river tiles without a water fall or spring above them dries up (I think this rule in particular needs some thinking about).

Only solid blocks and ramps affect water - bridges have no impact.

Water movement/changes could either be at some speed, or instantaneous. I'm not sure how I feel about this.

tttppp commented 8 years ago

Ideas for puzzles this would create:

Something else I just thought of is that rivers would need to be able to run down ramps.

andybalaam commented 8 years ago

Definite puzzletunities but some serious coding and design to be done. Prototypes welcome.

colonelfazackerley commented 8 years ago

It will be fun. I think it will need particles[1] instead of sprites. I think the water in each cell will need numbers for velocity and how full the cell is.

[1] https://en.wikipedia.org/wiki/Particle_system

tttppp commented 8 years ago

I totally agree that this would be a lot of coding (and testing!) but the main thing I wanted to agree short term was whether this was a good enough reason to reserve "water" as distinct from the static death squares.

I had a quick go at putting together a python-based water flow state machine today. The intention was to test the rules I put above, but it was not trivial.

I like the idea of modelling water with velocity and amount. My original intention was to simplify things so that water doesn't actually move, rather it 'infects' neighbouring squares in a "Game of Life" style.

tttppp commented 8 years ago

Something else that occurred to me was that even more puzzles could be created with this if we also had unbreakable walls (metal?) and Portal-style button/doors (i.e. step on a button to open a metal door). Water could pres buttons, meaning that a player might want to carefully redirect the water to a particular square.

colonelfazackerley commented 8 years ago

Metal blocks are still on the TODO list that pre-dates use of github issues. I like buttons too.

I fear we may be engaging in too much chat and not enough code.

andybalaam commented 8 years ago

Minecraft demonstrates that a cellular automata style of water flow can work. One thing I like about the proposed scheme is that water would interact only with blocks (except when it kills rabbits) so it would not complicate other code.

andybalaam commented 8 years ago

@GamingInky and I are hoping to do metal blocks so please don't start them

andybalaam commented 8 years ago

@tttppp post gifs of prototypes for fun.

tttppp commented 8 years ago

Prototype of water flow using Python:

https://ideone.com/Unvniz

Mini-example (~ is water, N is pool, other symbols you can look up in the script if you want to):

  x  
#  / 
#####

  *  
#  / 
#####

  *  
# |/ 
#####

  *  
# ~/ 
#####

  *  
#~~} 
#####

  *  
#NN] 
#####

 ~X~ 
#NN] 
#####

~~X~|
#NN] 
#####

~~X~|
#NN]|
#####

~~X~|
#NN]~
#####

~~X~|
#NN]~
#####

Currently no support for removing blocks, but water seems to be flowing away from the source fairly well. The script gives a demo of a more complex world filling with water.

colonelfazackerley commented 8 years ago

Nice.

How will this look in swing/android? I think that if the water jumps up a whole square it might look odd. how will the graphics be done? particles or states (half full, full, flowing left, ...) with animations like rabbits?

tttppp commented 8 years ago

I was thinking of animations to go between states, e.g. always the same 10 frames for river turning into pool. This will probably look a little blocky, but when the water level is static (ie most of the time) it should look ok.

Animating rivers turning into water falls might be tough.

colonelfazackerley commented 8 years ago

Animating rivers turning into water falls might be tough.

That's why I was thinking particles.

colonelfazackerley commented 8 years ago

Some thoughts about awkward cases for water. awkward_water If you start some work in a branch, I would be happy to do pull requests into it.

colonelfazackerley commented 8 years ago

A lot of the chars you are using are used already. see

https://github.com/andybalaam/rabbit-escape/blob/master/rabbit-escape-engine/src/rabbitescape/engine/textworld/ChangeRenderer.java

I was going to suggest 'w' for water, but that is taken too. Not sure what to suggest.

tttppp commented 8 years ago

I had realised that some of these characters couldn't be the final ones - I'm not even sure they all need distinct characters. I hadn't however realised how tight the remaining character space is getting! Here's a list of the characters used (according to a script I just wrote):

!$%&+,-.:<=>?@DFGHIJKLPRTUWXY[]^_`aefhmsxy|~

Also that page didn't seem to contain the symbols for blocks, and bridges - off the top of my head that adds # \/{}. Further there's the special character for "see below" *!

Maybe all non-deadly water can be n and pools can be N. If either shares a space with something else then we can use * to output the details at the bottom. (Actually - does the text interface display multiple things in one place with asterisks? I don't remember ever having seen it do that).

tttppp commented 8 years ago

I had originally proposed water passing through (or "behind"?) bridges. I don't have a strong opinion on this though. It's another situation to code for, and the animation for partially laid bridges may be more effort than it's worth. On the other hand I can imagine that building aqueducts might be fun!

tttppp commented 8 years ago

An example of how I thought water might animate. I've aimed to reuse "animation" where ever possible (e.g. water running down slopes is basically the same as water running off an edge). I'm not sure whether than will work or not. Also I've tried to show what rivers rising within each square might look like.

water01 water02 water03 water04 water05 water06 water07

Note how I totally failed that level!

colonelfazackerley commented 8 years ago

I think the chars in ChangeRenderer are only used for tests. you could do tests another way, but planning early for tests is a good idea.

I dont think 2 levels of fullness (well 3 if you count empty) is enough. Consider a room 20 squares wide next to a tower or well with 1 square internal width. The well will fill fast. There is no way the wide room can fill slowly and smoothly if the state is stored in the way you suggest.

tttppp commented 8 years ago

The way I'm suggesting doesn't match physics, but rather is easy (ish) to code and (hopefully) to predict as a player. A well/room fills at exactly the same rate regardless of the width, number of sources feeding it, number of splits in the water since the sources.number

The two levels of filling are because the algorithm (and in theory the player) only needs to worry about "water is passing through this cell" and "rabbits will drown in this cell".

That's my rationale anyway. I can totally understand why we might go for a more complex water model (e.g. A cell can hold at most 10 units of water and sources produce 5 units per time step). But I think it will be complicated, and might not be clear to the player whether their rabbits will drown or not.

tttppp commented 8 years ago

Updated python script to show example of a wide room with a well: https://ideone.com/165jny

It looks like:

   x      
#        #
#        #
#        #
#### #####
#### #####
#### #####
##########

   *      
#        #
#        #
#        #
#### #####
#### #####
#### #####
##########

   *      
#  |     #
#        #
#        #
#### #####
#### #####
#### #####
##########

   *      
#  |     #
#  |     #
#        #
#### #####
#### #####
#### #####
##########

   *      
#  |     #
#  |     #
#  |     #
#### #####
#### #####
#### #####
##########

   *      
#  |     #
#  |     #
#  ~     #
#### #####
#### #####
#### #####
##########

   *      
#  |     #
#  |     #
# ~~|    #
#### #####
#### #####
#### #####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
#### #####
#### #####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
####|#####
#### #####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
####|#####
####|#####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
####|#####
####~#####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
####|#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
####~#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####|#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####~#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~|    #
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~~    #
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~~~   #
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~~~~  #
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~~~~~ #
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#~~~~~~~~#
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#  |     #
#NNNNNNNN#
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#~~~~~~~~#
#NNNNNNNN#
####N#####
####N#####
####N#####
##########

   *      
#  |     #
#NNNNNNNN#
#NNNNNNNN#
####N#####
####N#####
####N#####
##########

   *      
#~~~~~~~~#
#NNNNNNNN#
#NNNNNNNN#
####N#####
####N#####
####N#####
##########

   *      
#NNNNNNNN#
#NNNNNNNN#
#NNNNNNNN#
####N#####
####N#####
####N#####
##########

 ~~X~~~~~ 
#NNNNNNNN#
#NNNNNNNN#
#NNNNNNNN#
####N#####
####N#####
####N#####
##########

Sorry for the crazily long comments.

andybalaam commented 8 years ago

Loving this thread. Yes, ChangeDescription characters are a different and less important name space from level files characters. It doesn't matter if we have many to one relationships there e.g. different types of falling all use 'f'.

colonelfazackerley commented 8 years ago

The water hits that bulkhead and equal amounts should go each way. Then the huge room and the narrow room have the height of water increase at the same rate. It's not going to look right.

                    *  
                    |  

#                   # #
#                   # #
#                   # #
#                   # #
#                   # #
#######################
colonelfazackerley commented 8 years ago

I don't mind long posts, BTW.

tttppp commented 8 years ago

I don't think it's trivial to model correctly though. Each cell would need a float volume of water (ramps would have half the capacity of empty cells), every split would cause the supplied water in each direction to half. In the real world puncturing a hole in a tube of water causes a different speed of spurt depending on the volume of water above it. Water dropping from a height onto a ramp should splash.

I think we have to limit the modelling of water to something much simpler. Maybe my proposal is too simple though.

andybalaam commented 8 years ago

I like your proposal. I think players will accept the world the way it is, and I like the simplicity of the rules that gives nice behaviour.

tttppp commented 8 years ago

I just read a couple of pages about water in minecraft. My conclusion is that this isn't an easy problem :-)

I'm not completely sold on my model, for some of the reasons colonelfazackerley has pointed out, but I haven't yet thought of a simple way to improve this. Other things I worry about are water falling speed relative to rabbit falling speed, and relative to river flowing speed. It might not be easy to judge this until we try some java code.

Currently pools fill even if they have no source, so that needs fixing. This is awkward though, as there are at least two ways a pool can fill. Water falling in from the top, or a source pumping it in from below.

Maybe a different algorithm would solve these problems, eg water produced from the source uses a path finding algorithm and gets added as a block to the current "end" somewhere. This would be more physically accurate (maintaining volume of water) but I'm not sure this would be easy for a player to grasp. It still has the challenge of draining water when blocks are removed.

tttppp commented 8 years ago

Another couple of situations (or test cases) I thought of:

colonelfazackerley commented 8 years ago

I had not thought of that. squares that are full will need pressure (depth) values.

andybalaam commented 8 years ago

I am inclined to go simpler rather than more complex. I am wondering whether a true cellular automaton would be cool I.e. No interactions between squares over 1 square apart. This would not lead to realistic water flow but why would we want realistic water flow?

andybalaam commented 8 years ago

I have been so tired recently I haven't missed any nights' sleep but if/when I do I might try a prototype. On the other hand I might fix some mundane bugs :-)

CodeSmith00 commented 8 years ago

this looks awesome!

tttppp commented 8 years ago

I knocked up a cellular automation version this lunch: https://ideone.com/jedosn

This stores the volume of water in each cell, so water volume is preserved. It has some weird behaviour though - it's not at all easy to guess when different cells will become "pools" (i.e. fatal to rabbits), and it's now possible that not all cells in a row will be at the same depth, so it's usual to get pools next to rivers. Also (and this needs fixing) water doesn't 'level out' around U-bends. I think to fix this we need to store the "pressure" of water in each cell.

Connectivity of cells is really important for this, and since it's the same for rabbits, tokens and water, it will make sense to create a utility that allows access to the connectivity, rather than compute it separately in all places.

I haven't yet perfected the display of my script, so there are temporary floating rivers, but hopefully these examples show roughly how the new algorithm behaves.

Demo with ramp

Room with well

Bulkhead

Stuck in U-bend

colonelfazackerley commented 8 years ago

your pastebin'd bits look good. have you thought about how to make it look good in swing/android?

tttppp commented 8 years ago

I had a few thoughts, but nothing difinitive.

  1. Animate falls, rivers and pools, and variants for river flowing into fall, fall landing on ramp, etc. This requires a lot of animations, but would be in keeping with the current method of animating each cell.
  2. Use the volume being constant to create particles as you suggested before. When ware moves between cells then animate the particles moving in that direction. This would be hard to get a clear distinction between rivers, pools and falls (which may cause problems for the player not knowing if water is dangerous or not).
  3. Animate falls per cell always looking the same. Animate rivers and falls by showing a blue rectangle at the bottom of the cell. The height of the rectangle could exactly match the water level. This still wouldn't be obvious when the water was at a dangerous level, but it should look fairly smooth.

Even if I get the algorithm working then I'm going to need help with the animation side of things.

andybalaam commented 8 years ago

I think we should start with a much simplified version of option 1 looking much like your text. It doesn't have to look real. Then if we design some levels that look really bad we can adjust the animation accordingly.

andybalaam commented 8 years ago

I really like the behaviour from your latest pastes. I think u bends can be safely ignored. Unless we think of a level where we need it.

andybalaam commented 8 years ago

I'd start without even special animations for slopes.

CodeSmith00 commented 8 years ago

I might start doing animations

colonelfazackerley commented 8 years ago

I think it might be best to write a programme to generate the animations. A lot will be needed, and water lends itself to coding.

andybalaam commented 8 years ago

If there were so many animations that e.g. We doubled the size of the jar I would be concerned.

tttppp commented 8 years ago

I spent some time today thinking more about water flow. I think we should aim to get it right first time, because once there are levels with water flowing it will be much harder to change.

I think the U bend problem can be solved by using flood filling to find connected bodies of water, and then giving each node a score based on height it should be possible to try to level the water by moving it along a path to improve the score (reduce the overall gravitational potential energy). Each edge in the network has a maximum capacity for per step, and so iterating will gradually restrict the movement of water that's possible for the time step.

I'm not sure if this makes a lot of sense, but I wanted to make a note in case I forgot.

Ps. I'm excited about the idea of animations. It would be useful to think about what information is needed in order to know how to animate a cell.

andybalaam commented 8 years ago

Our automated tests protect us somewhat from changes so long as they are additive rather than change ative.

andybalaam commented 8 years ago

But yeah. No hurry, so let's wait until we are happy.

tttppp commented 8 years ago

Water is now flowing round U bends. Unfortunately it's pooling in midair, rather than free-falling.

 x #   000000
#  # # 000000
#  # # 000000
#  # # 000000
#    # 000000
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#  # # 000000
#    # 000000
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#  # # 000000
#    # 000000
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#N # # 0a0000
#    # 000000
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#  # # 000000
#N   # 0a0000
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#N # # 0a0000
#~~  # 055000
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#  # # 000000
#~~~ # 066600
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#N # # 0a0000
#~~~~# 055550
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#  # # 000000
#~~~~# 077770
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#N # # 0a0000
#~~~~# 077770
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#  # # 000000
#NNNN# 0aaaa0
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#N # # 0a0000
#NNNN# 0aaaa0
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#~~#~# 033030
#NNNN# 0aaaa0
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#~~#~# 066060
#NNNN# 0aaaa0
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#~~#~# 066060
#NNNN# 0aaaa0
###### 000000

 x #   000000
#| # # 050000
#  # # 000000
#NN#N# 0aa0a0
#NNNN# 0aaaa0
###### 000000

 x #   000000
#  # # 000000
#N # # 0a0000
#NN#N# 0aa0a0
#NNNN# 0aaaa0
###### 000000

 x #   000000
#| # # 050000
#~~#~# 033030
#NN#N# 0aa0a0
#NNNN# 0aaaa0
###### 000000

 x #   000000
#  # # 000000
#~~#~# 066060
#NN#N# 0aa0a0
#NNNN# 0aaaa0
###### 000000

 x #   000000
#| # # 050000
#~~#~# 066060
#NN#N# 0aa0a0
#NNNN# 0aaaa0
###### 000000
andybalaam commented 8 years ago

Nearly there

CodeSmith00 commented 8 years ago

I was thinking about this and #300 here are to suggestions for interactions between them:

(F is fire)

#   #
#  X#
#  |#
#  F#
#####

#   #
#  X#
#  |#
#  ~#
#####,

next one

#   #
#   #
#  F#
# #N#
#####

#   #
#   #
#   #
# #F#
#####
colonelfazackerley commented 8 years ago

I don't think I understand why the water source disappears and the extra block appears at the bottom.

CodeSmith00 commented 8 years ago

Sorry the copying didn't work I'll fix it...

tttppp commented 8 years ago

So I think @gaminginky is suggesting that in some circumstances water is boiled by fire? Presumably this would be when there was a small amount of water in the fire cell?

I'm making progress testing different water algorithms, but I'm not really up to the point of specifying the interactions yet. Maybe this is something we can play with once we have a working water model? (Side note: I read a really interesting article about water modeling in dwarf fortress)