Oven.hpp
//------------------------------------------------------------------------------
/// @file
/// @author ハル研究所プログラミングコンテスト実行委員会
///
/// @copyright Copyright (c) 2018 HAL Laboratory, Inc.
/// @attention このファイルの利用は、同梱のREADMEにある
/// 利用条件に従ってください。
//------------------------------------------------------------------------------
#pragma once
//------------------------------------------------------------------------------
#include "Array.hpp"
#include "OvenRecipe.hpp"
#include "Parameter.hpp"
#include "Piece.hpp"
#include "Vector2i.hpp"
//------------------------------------------------------------------------------
namespace hpc {
/// オーブンの動作に関連する生地の配列。
using OvenedPieces = Array<Piece, Parameter::OvenCellCount>;
/// 生地を焼成する装置、オーブン。
class Oven
{
public:
/// @name コンストラクタ
//@{
Oven();
explicit Oven(const OvenRecipe& aRecipe);
//@}
/// @name 配置問い合わせ
/// @detail 「生地を pos の位置に配置する」ということが
/// どういう配置を意味するかは Piece::pos の説明を参照してください。
//@{
/// 生地を指定した場所に配置できるか?
/// @detail 「配置できる」とは
/// 「生地をそこに配置したとき、オーブンの天板の範囲に収まっていて
/// かつ他の配置済みの生地と被らない」という意味です。
/// @param aPiece 配置したい生地。
/// @param aPos 配置したい場所。
/// @return 配置できるなら true 。
bool isAbleToPut(const Piece& aPiece, const Vector2i& aPos) const;
/// 生地を指定した場所に配置できるか?
/// @detail 「配置できる」とは
/// 「生地をそこに配置したとき、オーブンの天板の範囲に収まっていて
/// かつ他の配置済みの生地と被らない」という意味です。
/// @param aPieceWidth 配置したい生地の横幅。
/// @param aPieceHeight 配置したい生地の縦幅。
/// @param aPos 配置したい場所。
/// @return 配置できるなら true 。
bool isAbleToPut(int aPieceWidth, int aPieceHeight, const Vector2i& aPos) const;
/// 生地を指定した場所に置いたとき、天板に収まるか?
/// @param aPiece 配置したい生地。
/// @param aPos 配置したい場所。
/// @return 収まるなら true 。
bool isInArea(const Piece& aPiece, const Vector2i& aPos) const;
/// 生地を指定した場所に置いたとき、天板に収まるか?
/// @param aPieceWidth 配置したい生地の横幅。
/// @param aPieceHeight 配置したい生地の縦幅。
/// @param aPos 配置したい場所。
/// @return 収まるなら true 。
bool isInArea(int aPieceWidth, int aPieceHeight, const Vector2i& aPos) const;
/// 生地を指定した場所に置いたとき、すでに天板に配置されている他の生地と被るか?
/// @param aPiece 配置したい生地。
/// @param aPos 配置したい場所。
/// @return 被るなら true 。
bool isIntersectAnyBakingPiece(const Piece& aPiece, const Vector2i& aPos) const;
/// 生地を指定した場所に置いたとき、すでに天板に配置されている他の生地と被るか?
/// @param aPieceWidth 配置したい生地の横幅。
/// @param aPieceHeight 配置したい生地の縦幅。
/// @param aPos 配置したい場所。
/// @return 被るなら true 。
bool isIntersectAnyBakingPiece(
int aPieceWidth,
int aPieceHeight,
const Vector2i& aPos
) const;
//@}
/// @name 一般的な問い合わせ
//@{
/// 天板の横幅。
int width() const;
/// 天板の縦幅。
int height() const;
/// 天板の面積。
int area() const;
/// 天板が空っぽか?
/// @return 天板に生地が乗っていない状態だったら true
bool isEmpty() const;
/// 天板上で現在焼いている最中の生地一覧。
const OvenedPieces& bakingPieces() const;
/// 天板上で現在焼いている最中の生地一覧。
OvenedPieces& bakingPieces();
/// 直前のターンで焼き上がった生地一覧。
const OvenedPieces& lastBakedPieces() const;
/// 直前のターンで焼き上がった生地一覧。
OvenedPieces& lastBakedPieces();
//@}
/// @name シミュレーション
//@{
/// オーブンの加熱を1ターンすすめ、焼き上がったものを処分する。
/// @detail オーブンの動作をシミュレートしたいときに使うことを想定しています。
void bakeAndDiscard();
//@}
/// @name 内部用関数
//@{
/// 指定のターン数分、オーブンの加熱時間を進める。
void addHeatTurnCount(int aTurnCount);
/// 直前のターンで焼き上がった生地の情報をクリアする。
void clearLastBakedPieces();
/// 現時点で焼き上がっている生地を回収する。
/// @return 回収された生地の個数。
int gatherBaked();
/// 指定した生地を指定した位置に配置することを試みる。
/// @return 配置に成功したら true 。
/// そこに生地を配置すると天板をはみ出る、とか、
/// 他の生地に被ってしまう、という場合は、
/// 配置に失敗して false が返る。
bool tryToBake(Piece* aPiece, const Vector2i& aPos);
//@}
private:
/// @name プライベートメンバ変数
//@{
/// このオーブンの設定
OvenRecipe mRecipe;
/// 今焼いている生地一覧
OvenedPieces mBakingPieces;
/// 直前のターンで焼き上がった生地一覧
OvenedPieces mLastBakedPieces;
//@}
};
} // namespace
// EOF