class Square( val grid : GridStage, val x : int, val y : int ) { var occupant : Item var entrant : Item var alternateOccupant : Item fun isEmpty() : boolean = occupant == null && alternateOccupant == null && entrant == null fun neighbour( dx : int, dy : int ) = grid.square( x + dx, y + dy ) fun neighbour( direction : int ) = neighbour( Item.getDeltaX( direction ), Item.getDeltaY( direction ) ) fun worldX() = grid.offsetX + x * grid.gridSize fun worldY() = grid.offsetY + y * grid.gridSize fun addOccupant( item : Item) { addOccupant( item, false ) } fun addOccupant( item : Item, alternate : boolean) { // Remove from the old square if ( item.square != null ) { item.square.remove( item ) } if (alternate) { alternateOccupant = item } else { occupant = item } item.square = this } fun remove( item : Item ) { if (occupant == item) { occupant = null item.square = null } if (alternateOccupant == item) { alternateOccupant = null item.square = null } if (entrant == item) { entrant = null } } fun invading( movement : Movement ) { // NOTE. For Compound items, ignore when a part invades the parent if (occupant != null && occupant != movement.item ) { occupant.invading( movement ) } if (alternateOccupant != null) { alternateOccupant.invading( movement ) } } fun invaded( movement : Movement ) : boolean { if (occupant != null && occupant != movement.item) { return occupant.invaded( movement ) } if (alternateOccupant != null) { return alternateOccupant.invaded( movement ) } return true } // NOTE. direction is the direction this square is being looked at, // i.e. the direction that the Movable item wants to travel. fun look( speed : int, direction : int ) : LookedAt { if (entrant == null) { return createLookedAt( occupant, alternateOccupant, speed, direction, true ) } else { if ( occupant == null ) { return createLookedAt( entrant, alternateOccupant, 0, direction, false ) } else { return createLookedAt( entrant, occupant, 0, direction, false ) } } } fun createLookedAt( a : Item, b : Item, speed : int, direction : int, aIsOccupant : boolean ) : LookedAt { if ( a == null || ( aIsOccupant && grid.willMiss( a, speed, direction) ) ) { if ( b == null ) { return Empty.instance } else { return b } } else { if ( b == null ) { return a } else { return LookedAtTwoItems( a, b ) } } } override fun toString() = "Square ($x,$y) occupant: $occupant alternate: $alternateOccupant entrant: $entrant" }